2013-05-09 14 views
13

Mi viene il buono, vecchio e temuto TransientObjectException e, come spesso accade in tal caso, sto avendo problemi a localizzare quale tipo di bug sottile nel codice sta causando il problema.Hibernate: come ottenere un elenco di tutti gli oggetti attualmente nella sessione

La mia domanda è: c'è un modo per ottenere un elenco di tutti gli oggetti presenti nella sessione di Hibernate corrente?

Probabilmente avrò risolto il problema corrente nel momento in cui avrò una risposta a questa domanda, ma, comunque, essere in grado di elencare tutto ciò che è la sessione sarebbe di grande aiuto la prossima volta che succede.

risposta

12

Hibernate non espone i suoi interni al pubblico, quindi non troverai ciò che stai cercando nell'API pubblica. Tuttavia si può trovare la risposta nelle classi di implementazione delle interfacce Hibernate: Questo metodo (tratto da http://code.google.com/p/bo2/source/browse/trunk/Bo2ImplHibernate/main/gr/interamerican/bo2/impl/open/hibernate/HibernateBo2Utils.java) ci dirà se un oggetto esiste nella sessione:

public static Object getFromSession 
     (Serializable identifier, Class<?> clazz, Session s) {    
    String entityName = clazz.getName(); 
    if(identifier == null) { 
     return null; 
    }  
    SessionImplementor sessionImpl = (SessionImplementor) s; 
    EntityPersister entityPersister = sessionImpl.getFactory().getEntityPersister(entityName); 
    PersistenceContext persistenceContext = sessionImpl.getPersistenceContext(); 
    EntityKey entityKey = new EntityKey(identifier, entityPersister, EntityMode.POJO); 
    Object entity = persistenceContext.getEntity(entityKey); 
    return entity; 
    } 

Se si drill-down un po 'di più, si vuole vedere che l'unica implementazione di PersistenceContext è org.hibernate.engine.StatefulPersistenceContext. Questa classe ha le seguenti collezioni:

// Loaded entity instances, by EntityKey 
private Map entitiesByKey; 

// Loaded entity instances, by EntityUniqueKey 
private Map entitiesByUniqueKey; 

// Identity map of EntityEntry instances, by the entity instance 
private Map entityEntries; 

// Entity proxies, by EntityKey 
private Map proxiesByKey; 

// Snapshots of current database state for entities 
// that have *not* been loaded 
private Map entitySnapshotsByKey; 

// Identity map of array holder ArrayHolder instances, by the array instance 
private Map arrayHolders; 

// Identity map of CollectionEntry instances, by the collection wrapper 
private Map collectionEntries; 

// Collection wrappers, by the CollectionKey 
private Map collectionsByKey; //key=CollectionKey, value=PersistentCollection 

// Set of EntityKeys of deleted objects 
private HashSet nullifiableEntityKeys; 

// properties that we have tried to load, and not found in the database 
private HashSet nullAssociations; 

// A list of collection wrappers that were instantiating during result set 
// processing, that we will need to initialize at the end of the query 
private List nonlazyCollections; 

// A container for collections we load up when the owning entity is not 
// yet loaded ... for now, this is purely transient! 
private Map unownedCollections; 

// Parent entities cache by their child for cascading 
// May be empty or not contains all relation 
private Map parentsByChild; 

Allora, che cosa dovete fare è lanciare i PersistenceContext ad uno StatefulPersistenceContext, quindi utilizzare la reflection per ottenere la collezione privata che si desidera e poi iterare su di esso.

Suggerisco caldamente di farlo solo sul codice di debug. Questa non è API pubblica e potrebbe frenare con le nuove versioni di Hibernate.

+0

Grazie; questo aiuterà molto la prossima volta che si verificherà il problema. ;) –

9

Trovato post @nakosspy molto utile. Ispirato dal suo post, ho aggiunto questo semplicissimo metodo di utilità che emette i contenuti di Hibernate Session.

Come nakosspy ha detto che questo è SOLO per scopi di debug in quanto è un HACK.

public static void dumpHibernateSession(Session s) { 
    try { 
     SessionImplementor sessionImpl = (SessionImplementor) s; 
     PersistenceContext persistenceContext = sessionImpl.getPersistenceContext(); 
     Field entityEntriesField = StatefulPersistenceContext.class.getDeclaredField("entityEntries"); 
     entityEntriesField.setAccessible(true); 
     IdentityMap map = (IdentityMap) entityEntriesField.get(persistenceContext); 
     log.info(map); 
    } catch (Exception e) 
    { 
     log.error(e); 
    } 

} 
+1

Per ibernare 4.3.11 è necessario utilizzare 'StatefulPersistenceContext.class.getDeclaredField (" entitiesByKey ");' e memorizzarlo come 'Mappa' (o qualche altro campo, dato che' entityEntries' non esiste) - ma a parte questo il concetto è solido. – jlb

Problemi correlati