70 votes

hibernate : LazyInitializationException : impossible d'initialiser le proxy

En voici une qui me laisse perplexe. J'essaie d'implémenter une structure DAO Hibernate de base, mais je rencontre un problème.

Voici le code essentiel :

    int startingCount = sfdao.count();

    sfdao.create( sf );

    SecurityFiling sf2 = sfdao.read( sf.getId() );

    sfdao.delete( sf );

    int endingCount = sfdao.count();

    assertTrue( startingCount == endingCount );
    assertTrue( sf.getId().longValue() == sf2.getId().longValue() );
    assertTrue( sf.getSfSubmissionType().equals( sf2.getSfSubmissionType() ) );
    assertTrue( sf.getSfTransactionNumber().equals( sf2.getSfTransactionNumber() ) );

Il échoue au troisième assertTrue où il essaie de comparer une valeur dans sf à la valeur correspondante dans sf2. Voici l'exception :

org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:86)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:140)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
    at com.freightgate.domain.SecurityFiling_$$_javassist_7.getSfSubmissionType(SecurityFiling_$$_javassist_7.java)
    at com.freightgate.dao.SecurityFilingTest.test(SecurityFilingTest.java:73)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:40)

Je peux poster mon code DAO et d'annotation si nécessaire. Veuillez indiquer ce qui est nécessaire.

TIA

Piko

68voto

pakore Points 4226

Le problème, c'est que vous essayez d'accéder à une collection dans un objet qui est détaché . Vous devez rattacher l'objet avant d'accéder à la collection à la session actuelle. Vous pouvez le faire par le biais de

session.update(object);

Utilisation de lazy=false n'est pas une bonne solution car vous vous débarrassez de la fonction d'initialisation paresseuse d'Hibernate. Lorsque lazy=false la collection est chargée en mémoire en même temps que l'objet est demandé. Cela signifie que si nous avons une collection de 1000 éléments, ils seront tous chargés en mémoire, que nous y accédions ou non. Et ce n'est pas bon.

Veuillez lire ceci article où il explique le problème, les solutions possibles et pourquoi il est mis en œuvre de cette manière. En outre, pour comprendre les Sessions et les Transactions, vous devez lire cet autre article .

14voto

digitalsanctum Points 1937

Cela signifie généralement que la session Hibernate propriétaire a déjà été fermée. Vous pouvez effectuer l'une des opérations suivantes pour résoudre ce problème :

  1. quel que soit l'objet qui crée ce problème, utilisez HibernateTemplate.initialize(object name)
  2. Utilisez lazy=false dans vos fichiers hbm.

11voto

Tim Sabin Points 81

Voir mon article. J'ai eu le même problème - LazyInitializationException - et voici la réponse que j'ai finalement trouvée :
http://community.jboss.org/wiki/LazyInitializationExceptionovercome
Définir lazy=false n'est pas la solution - cela peut tout charger en même temps, et ce n'est pas forcément bon. Exemple :
1 table d'enregistrement A références :
5 enregistrements table B références :
25 enregistrements table C références :
125 enregistrements table D
...
etc. Ce n'est qu'un exemple de ce qui peut mal tourner.
--Tim Sabin

7voto

konda Points 61

Si vous utilisez Hibernate avec les annotations JPA, ce sera une utilisation complète. Dans votre classe de service, il devrait y avoir un setter pour le gestionnaire d'entités avec @PersistenceContext. Changez-le en @PersistenceContext(type = PersistenceContextType.EXTENDED). Vous pourrez alors accéder à la propriété paresseuse à n'importe quel endroit.

4voto

Rolando Quezada Points 31

Si vous utilisez le chargement paresseux, votre méthode doit être annotée avec

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) pour les EJB de session apatrides

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X