ibernazione: LazyInitializationException: imansible inizializzare il proxy

Eccone uno che mi lascia perplesso. Sto cercando di implementare una struttura DAO di Hibernate di base, ma sto avendo un problema.

Ecco il codice essenziale:

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

Fallisce sul terzo assertTrue dove sta cercando di confrontare un valore in sf con il valore corrispondente in sf2. Ecco l’eccezione:

 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) 

    Il problema è che stai provando ad accedere ad una collezione in un object che è stato staccato . È necessario ricolbind l’object prima di accedere alla raccolta alla sessione corrente. Puoi farlo attraverso

     session.update(object); 

    L’utilizzo di lazy=false non è una buona soluzione perché stai buttando via la funzione di inizializzazione pigra di ibernazione. Quando lazy=false , la raccolta viene caricata in memoria nello stesso momento in cui viene richiesto l’object. Ciò significa che se abbiamo una collezione con 1000 elementi, saranno tutti caricati in memoria, nonostante potremo accedervi o meno. E questo non va bene.

    Per favore leggi questo articolo dove spiega il problema, le possibili soluzioni e perché viene implementato in questo modo. Inoltre, per comprendere Sessioni e Transazioni devi leggere questo altro articolo .

    Questo in genere significa che la sessione di sospensione di proprietario è già stata chiusa. Puoi eseguire una delle seguenti operazioni per risolvere il problema:

    1. qualsiasi object che crea questo problema, usa HibernateTemplate.initialize(object name)
    2. Usa lazy=false nei tuoi file hbm.

    Vedi il mio articolo. Ho avuto lo stesso problema – LazyInitializationException – ed ecco la risposta che ho finalmente trovato:
    http://community.jboss.org/wiki/LazyInitializationExceptionovercome
    L’impostazione lazy = false non è la risposta: può caricare tutto tutto in una volta e ciò non è necessariamente positivo. Esempio:
    1 tabella dei record A riferimenti:
    5 riferimenti della tabella B dei record:
    25 riferimenti della tabella C dei record:
    125 tabella registrazioni D

    ecc. Questo è solo un esempio di cosa può andare storto.
    – Tim Sabin

    Se si utilizza la sospensione con annotazioni JPA, ciò sarà utile. Nella tua class di servizio dovrebbe esserci un setter per il gestore di quadro con @PersistenceContext. cambiala in @PersistenceContext (type = PersistenceContextType.EXTENDED). Quindi è ansible accedere a proprietà pigro in qualsiasi dove.

    se si utilizza il caricamento Lazy, il metodo deve essere annotato con

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) per EJB Sessione Stateless

    Abbiamo riscontrato anche questo errore. Quello che abbiamo fatto per risolvere il problema è che abbiamo aggiunto un lazy = false nel file di mapping di Hibernate.

    Sembra che avessimo una class A all’interno di una sessione che carica un’altra class B. Stiamo provando ad accedere ai dati sulla class B ma questa class B è scollegata dalla sessione.

    Per permetterci di accedere a questa Classe B, abbiamo dovuto specificare nel file di mapping Hibernate della class A l’attributo lazy = false. Per esempio,

         

    Ok, finalmente ho capito dove ero negligente. Avevo l’errata idea che dovevo racchiudere ogni metodo DAO in una transazione. Terribilmente sbagliato! Ho imparato la mia lezione Ho trascinato tutto il codice transazione da tutti i metodi DAO e ho impostato le transazioni rigorosamente a livello di applicazione / gestore. Questo ha completamente risolto tutti i miei problemi. I dati sono correttamente caricati come se ne avessi bisogno, avviluppati e chiusi una volta eseguito il commit.

    La vita è bella … 🙂

    Se si conosce l’impatto di lazy=false e si desidera comunque renderlo come predefinito (ad esempio, per scopi di prototipazione), è ansible utilizzare uno dei seguenti elementi:

    • se si utilizza la configurazione XML: aggiungere default-lazy="false" all’elemento
    • se stai usando la configurazione delle annotazioni: aggiungi @Proxy(lazy=false) alle tue classi di quadro

    Sembra che solo il tuo DAO stia usando la sessione. Quindi una nuova sessione è aperta e quindi chiusa per ogni chiamata a un metodo DAO. Quindi l’esecuzione del programma può essere ripresa come:

     // open a session, get the number of entity and close the session int startingCount = sfdao.count(); // open a session, create a new entity and close the session sfdao.create( sf ); // open a session, read an entity and close the session SecurityFiling sf2 = sfdao.read( sf.getId() ); // open a session, delete an entity and close the session sfdao.delete( sf ); etc... 

    Per impostazione predefinita, la raccolta e l’associazione in un’ quadro sono pigri: vengono caricati dal database su richiesta. Così:

    sf.getSfSubmissionType().equals( sf2.getSfSubmissionType() )

    sta generando un’eccezione perché richiede un nuovo caricamento dal database e la sessione associata al caricamento dell’ quadro è già stata chiusa.

    Esistono due approcci per risolvere questo problema:

    • creare una sessione per racchiudere tutto il nostro codice. Quindi significherebbe cambiare il contenuto DAO per evitare di aprire una seconda sessione

    • creare una sessione quindi aggiornare (cioè ricolbind) la propria entity framework a questa sessione prima delle asserzioni.

      Session.update (object);

    Se stai gestendo manualmente la sessione di Hibernate, potresti voler esaminare sessionFactory.getCurrentSession () e documenti associati qui:

    http://www.hibernate.org/hib_docs/v3/reference/en/html/architecture-current-session.html

    Penso che Piko nella sua risposta significhi che esiste il file hbm. Ho un file chiamato Tax.java. Le informazioni di mapping vengono salvate nel file hbm (= hibernate mapping). Nel tag class esiste una proprietà chiamata lazy . Imposta quella proprietà su true. Il seguente esempio di hbm mostra un modo per impostare la proprietà lazy su false .

    ‘id …’

    Se stai usando le Annotazioni, guarda invece nella documenazione di ibernazione. http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/

    Spero che questo abbia aiutato.

    usa Hibernate.initialize per il campo pigro

    Se si utilizza l’annotazione Spring e JPA, il modo più semplice per evitare problemi con la sessione in initial pigro è la riproduzione:

     @PersistenceContext 

    a

     @PersistenceContext(type = PersistenceContextType.EXTENDED) 

    Per impostazione predefinita, tutte le associazioni one-to-many e many-to-many vengono recuperate pigramente dopo essere state visitate per la prima volta.

    Nel tuo caso d’uso, puoi risolvere questo problema avvolgendo tutte le operazioni DAO in una transazione logica:

     transactionTemplate.execute(new TransactionCallback() { @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; } }); 

    Un’altra opzione è quella di recuperare tutte le associazioni LAZY caricando la tua quadro, in modo che:

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

    dovrebbe andare a prendere anche il TOTTO di submissionType LAZY:

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

    In questo modo, recuperi tutte le proprietà pigri e puoi accedervi anche dopo la chiusura della sessione.

    È ansible recuperare tutte le associazioni [one|many]-to-one e le associazioni di “[uno | molti] -a-molti” (a causa dell’esecuzione di un prodotto cartesiano).

    Per inizializzare più “[one | many] -to-many”, dovresti usare Hibernate.initialize (collection) , subito dopo aver caricato l’ quadro root.