enable_lazy_load_no_trans - springboottest org hibernate lazyinitializationexception could not initialize proxy no session




Hibernate: LazyInitializationException: Proxy konnte nicht initialisiert werden (10)

Das Problem besteht darin, dass Sie versuchen, auf eine Auflistung in einem Objekt zuzugreifen, das getrennt ist. Sie müssen das Objekt erneut anfügen, bevor Sie auf die Sammlung für die aktuelle Sitzung zugreifen. Du kannst das durchmachen

session.update(object);

Die Verwendung von lazy=false ist keine gute Lösung, da Sie die Lazy Initialization-Funktion von hibernate wegwerfen. Wenn lazy=false , wird die Sammlung zur gleichen Zeit in den Speicher geladen, zu der das Objekt angefordert wird. Das heißt, wenn wir eine Sammlung mit 1000 Elementen haben, werden sie alle in den Speicher geladen, obwohl wir darauf zugreifen wollen oder nicht. Und das ist nicht gut.

Bitte lesen Sie diesen article in dem es das Problem erklärt, die möglichen Lösungen und warum es so umgesetzt wird. Um Sessions und Transaktionen zu verstehen, müssen Sie diesen anderen Artikel lesen.

Hier ist einer, der mich perplex hat. Ich versuche, eine grundlegende Hibernate-DAO-Struktur zu implementieren, habe aber ein Problem.

Hier ist der wesentliche Code:

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() ) );

Es schlägt auf dem dritten assertTrue fehl, wo es versucht, einen Wert in sf mit dem entsprechenden Wert in sf2 zu vergleichen. Hier ist die Ausnahme:

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)

Dies bedeutet im Allgemeinen, dass die besitzende Hibernate-Sitzung bereits geschlossen wurde. Sie können einen der folgenden Schritte ausführen, um den Fehler zu beheben:

  1. Welches Objekt auch immer dieses Problem verursacht, verwenden Sie HibernateTemplate.initialize(object name)
  2. Verwenden Sie in Ihren hbm-Dateien lazy=false .

Ich denke, Piko meint in seiner Antwort, dass es die hbm-Datei gibt. Ich habe eine Datei namens Tax.java. Die Zuordnungsinformationen werden in der Datei hbm (= hibernate mapping) gespeichert. Im Klassen-Tag gibt es eine Eigenschaft namens faul . Setzen Sie diese Eigenschaft auf true. Das folgende HBM-Beispiel zeigt eine Möglichkeit, die faule Eigenschaft auf false zu setzen .

"Es ..."

Wenn Sie Annotationen verwenden, schauen Sie stattdessen in die Hibernation-Dokumentation. http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/

Ich hoffe, das hat geholfen.


Okay, endlich herausgefunden, wo ich nachlässig war. Ich hatte die falsche Vorstellung, dass ich jede DAO-Methode in eine Transaktion integrieren sollte. Schrecklich falsch! Ich habe meine Lektion gelernt. Ich habe den gesamten Transaktionscode von allen DAO-Methoden geholt und habe Transaktionen ausschließlich auf der Ebene der Anwendung / des Managers eingerichtet. Das hat meine Probleme vollständig gelöst. Die Daten werden ordnungsgemäß lazy geladen, wenn ich sie brauche, eingepackt und geschlossen, sobald ich das Commit mache.

Das Leben ist gut ... :)


Standardmäßig werden alle one-to-many und many-to-many Many many-to-many Zuordnungen beim erstmaligen Zugriff getrost abgerufen.

In Ihrem Anwendungsfall können Sie dieses Problem lösen, indem Sie alle DAO-Operationen in eine logische Transaktion einschließen:

transactionTemplate.execute(new TransactionCallback<Void>() {
    @Override
    public Void doInTransaction(TransactionStatus transactionStatus) {

        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() ) );

        return null;
    }
});

Eine andere Möglichkeit besteht darin, alle LAZY-Assoziationen beim Laden Ihrer Entität abzurufen, damit:

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

sollte auch den LAZY-supplierType abrufen:

select sf
from SecurityFiling sf
left join fetch.sf.submissionType

Auf diese Weise holen Sie eifrig alle faulen Eigenschaften und Sie können auf sie zugreifen, nachdem auch die Sitzung geschlossen wurde.

Sie können so viele [one|many]-to-one Zuordnungen und eine "[one | many] -to-many" Listenzuordnungen abrufen (weil ein kartesisches Produkt ausgeführt wird).

Um mehrere "[one | many] -to-many" zu initialisieren, sollten Sie Hibernate.initialize(collection) direkt nach dem Laden Ihrer root-Entity verwenden.


Verwenden Sie Hibernate.initialize für Lazy-Feld


Wenn Sie Hibernate mit JPA-Anmerkungen verwenden, ist dies nützlich. In Ihrer Serviceklasse sollte ein Setter für den Entity Manager mit @PersistenceContext vorhanden sein. Ändern Sie dies in @PersistenceContext (type = PersistenceContextType.EXTENDED). Dann können Sie in jedem beliebigen Bereich auf eine faule Eigenschaft zugreifen.


Wenn Sie Lazy Loading verwenden, muss Ihre Methode mit kommentiert werden

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) für Stateless Session EJB


Wenn Sie die Spring- und JPA-Annotation verwenden, ist das Replaysing der einfachste Weg, um ein Problem mit der Session in Faul Initialize zu vermeiden:

@PersistenceContext   

zu

@PersistenceContext(type = PersistenceContextType.EXTENDED)

Wir sind diesem Fehler ebenfalls begegnet. Was wir getan haben, um das Problem zu lösen, ist, dass wir in der Hibernate Mapping-Datei einen Lazy = False hinzugefügt haben.

Anscheinend hatten wir eine Klasse A innerhalb einer Sitzung, die eine andere Klasse B lädt. Wir versuchen, auf die Daten in Klasse B zuzugreifen, aber diese Klasse B ist von der Sitzung getrennt.

Damit wir auf diese Klasse B zugreifen können, mussten wir in der Hibernate-Zuordnungsdatei der Klasse A das Attribut lazy = false angeben. Beispielsweise,

     <many-to-one name="classA" 
                 class="classB"
                 lazy="false">
        <column name="classb_id"
                sql-type="bigint(10)" 
                not-null="true"/>
    </many-to-one>  




lazy-evaluation