In spring con jpa / hibernate, come posso mantenere aperta una sessione per evitare le eccezioni di inizializzazione pigra?

Attualmente contrassegno le raccolte in bean di quadro come desiderose di evitare di ottenere un’eccezione di inizializzazione pigra quando provo ad accedere alle proprietà della raccolta dopo aver caricato il bean con EntityManager.

Se invece lascio la raccolta come caricamento lento, come posso mantenere aperta una sessione? Ho pensato di provare @Transactional, ma anche se funzionasse, non vorrei farlo perché non sembra giusto lasciare una transazione aperta su un lungo metodo.

https://www.hibernate.org/43.html

Fondamentalmente, hai alcune opzioni.

-È ansible utilizzare il modello “open session in view” in cui si utilizza una logica di filtro / interceptor / AOP – style per aprire una sessione quando inizia la logica lato server e chiuderla quando è completa.

-È ansible implementare conversazioni che coprono diversi cicli di richiesta-risposta.

Un semplice vecchio filtro servlet è il più semplice.

Un’ultima opzione che sembra mancare è che puoi build il tuo grafo di oggetti basato sul tuo caso d’uso usando un JOIN.

Ciò comporterà l’inizializzazione dell’object, vale a dire che non sarà un proxy.

Utilizza questo approccio se hai il controllo del cliente (ovvero non stai creando un servizio aperto pubblicando un’API) perché devi sapere quale stato viene toccato quando la sessione viene chiusa perché la transazione è stata chiusa.

Come altri hanno già detto, dovresti leggere il modello “open session in view”, la cui idea di base è di avere una sessione di ibernazione aperta per tutta la durata dell’elaborazione della richiesta http. Ci sono sia soluzioni specifiche per l’ibernazione sia soluzioni primaverili – ho usato la spring prima e funziona perfettamente.

Nella domanda hai detto che non vuoi avere una transazione aperta per molto tempo. Per la maggior parte delle persone questo non è un problema perché ogni richiesta viene elaborata in tempi relativamente brevi. Tuttavia, se nel tuo caso è davvero imansible, questo modello non funzionerà per te. Puoi approfondire il motivo per cui non vuoi che le transazioni siano mantenute aperte?

Stai usando Spring’s HibernateTemplate? Gestirò la sessione per te credo. In alternativa, se si è su Hibernate 3.0.1 o successivo, Spring dovrebbe comunque essere in grado di gestire la sessione.

C’è una voce del blog SpringSource che descrive come configurarlo. Ho incluso un estratto qui sotto:

Da quando Hibernate 3.0.1 (e Java Persistence API dal momento in cui è stato rilasciato per la prima volta) è diventato ansible per Spring gestire la risorsa sottostante senza dover passare attraverso nessuno dei modelli disponibili per quelle tecnologie. Ciò significa che anche se si sta utilizzando direttamente l’API di Hibernate (ad esempio attraverso SessionFactory.getCurrentSession ()), si continuerà a utilizzare una sessione di sospensione gestita da Spring. Lo stesso vale per un EntityManager ottenuto tramite EntityManagerFactory JPA. Questo è un altro motivo per cui non devi più utilizzare Spring’s HibernateTemplate per ottenere un’esperienza integrata. […]

Quello che segue è l’XML che useremo per assemblare l’applicazione. Come puoi vedere, stiamo ancora utilizzando il modo Spring di configurare Hibernate (usando LocalSessionFactoryBean).

      

Ora, come ho detto prima, a causa di un piccolo cambiamento in Hibernate 3.0.1, Spring è in grado di gestire la sessione di Hibernate per te, senza che tu debba passare attraverso la sessione di Hibernate. L’unica cosa che mancava era la traduzione delle eccezioni. Per ottenere ciò, è sufficiente annotare il repository con l’annotazione @Repository (fornita da Spring) e triggersre la traduzione delle eccezioni utilizzando un post processore.

 @Repository // from org.springframework.stereotype public class HibernateAccountRepository implements AccountRepository { // see above for full impl… } 

Quando lasci aperta una sessione che ha letto alcuni dati, lascerai aperta quella transazione. Le transazioni a lungo termine non sono un grosso problema (anche se ciò potrebbe dipendere dal database) ciò che causa veramente dei problemi sono i blocchi da lungo tempo, ma questi potrebbero essere creati solo dopo aver effettivamente modificato i dati nel database. Ancora una volta dipende dal tuo database.

Ora, non ho usato Spring, ma ho usato Hibernate in diversi progetti. L’approccio su cui mi sono basato per il progetto più recente è nato dal modello di gestione della sessione difensiva (in combinazione con un filtro servlet) e ne siamo soddisfatti. Puoi trovare più modelli di design qui .