Come posso accedere ai campi pigri-caricato dopo che la sessione è chiuso, usando Hibernate?
-
21-08-2019 - |
Domanda
considerare questo scenario:
- Ho caricato un'entità genitore attraverso hibernate
- Parent contiene una raccolta di bambini che è grande e caricato in modo pigro
- La sessione Hibernate è chiusa dopo questo caricamento iniziale mentre l'utente visualizza i dati padre
- L'utente può scegliere di visualizzare il contenuto della collezione bambini pigri
- Ora desidero che la raccolta caricare
Quali sono i modi / miglior modo di carico questa collezione?
- Si supponga session-in-vista non è un'opzione come il recupero della collezione bambini sarebbe accaduto solo dopo che l'utente ha visto il padre e ha deciso di vedere i figli.
- Questo è un servizio che sarà accessibile da remoto da web client e desktop basato su.
Grazie.
Soluzione
Sto facendo alcune ipotesi su ciò che l'utente sta guardando, ma sembra che si desidera solo recuperare i bambini se l'utente ha già visualizzato il genitore e vuole vedere i bambini in realtà.
Perché non prova ad aprire una nuova sessione e andare a prendere i bambini dai loro genitori? Qualcosa sulla falsariga di ...
criteria = session.createCriteria(Child.class);
criteria.add(Restrictions.eq("parent", parent));
List<Child> children = criteria.list();
Altri suggerimenti
La collezione pigro può essere caricato utilizzando Hibernate.initialize (parent.getCollection ()) tranne che l'oggetto padre ha bisogno di essere collegato a una sessione attiva.
Questa soluzione prende il genitore Entità ed il nome del campo pigro-caricato e restituisce l'entità con la collezione a pieno carico.
Purtroppo, come deve essere riattaccato alla sessione di recente apertura il genitore, non posso utilizzare un riferimento alla raccolta pigro quanto ciò riferimento la versione distaccata dell'Ente; quindi la nomeCampo e la riflessione. Per lo stesso motivo, questo deve restituire il controllante allegato.
Quindi, nello scenario OP, questa chiamata può essere effettuata quando l'utente sceglie di vedere la collezione pigro:
Parent parentWithChildren = dao.initialize(parent,"lazyCollectionName");
Il Metodo:
public Entity initialize(Entity detachedParent,String fieldName) {
// ...open a hibernate session...
// reattaches parent to session
Entity reattachedParent = (Entity) session.merge(detachedParent);
// get the field from the entity and initialize it
Field fieldToInitialize = detachedParent.getClass().getDeclaredField(fieldName);
fieldToInitialize.setAccessible(true);
Object objectToInitialize = fieldToInitialize.get(reattachedParent);
Hibernate.initialize(objectToInitialize);
return reattachedParent;
}
Hibernate gestisce le collezioni in un modo diverso che i campi normali.
Al mio lavoro si ottiene intorno a questo solo l'inizializzazione dei campi nel caricamento iniziale che abbiamo bisogno su un caso per caso. Ad esempio, in un metodo di carico facciata che è circondato da una transazione potrebbe essere:
public Parent loadParentWithIntent1(Long parentId)
{
Parent parent = loadParentFromDAO();
for (Child c : parent.getChildren())
{
c.getField1();
}
}
e noi abbiamo una chiamata facciata diverso per ogni intento. Questo realizza in sostanza ciò che è necessario perché saresti caricare questi campi specifici quando si ha bisogno di loro in qualsiasi modo e questo solo li mette nella sessione in fase di caricamento.