2013-05-09 15 views
13

Dostaję dobre, stare i przerażające TransientObjectException, a jak to często bywa w takich przypadkach, mam problem z lokalizowaniem jakiego rodzaju subtelnego błędu w kodzie powoduje problem.Hibernate: jak uzyskać listę wszystkich obiektów aktualnie w sesji

Moje pytanie brzmi: czy istnieje sposób na uzyskanie listy wszystkich obiektów znajdujących się w bieżącej sesji Hibernate?

Prawdopodobnie rozwiązałem obecny problem do czasu uzyskania odpowiedzi na to pytanie, ale w każdym razie, możliwość wyświetlenia wszystkiego, co jest sesją, bardzo pomogłoby w następnym momencie.

Odpowiedz

12

Hibernate nie udostępnia publicznie swoich wewnętrznych elementów, więc nie znajdziesz tego, czego szukasz w publicznym interfejsie API. Jednak można znaleźć odpowiedzi w klasach implementacji interfejsów Hibernate: tę metodę (wzięte z http://code.google.com/p/bo2/source/browse/trunk/Bo2ImplHibernate/main/gr/interamerican/bo2/impl/open/hibernate/HibernateBo2Utils.java) pokaże, czy obiekt istnieje w sesji:

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; 
    } 

Jeśli drążyć trochę więcej, będziesz zobacz, że jedyną implementacją PersistenceContext jest org.hibernate.engine.StatefulPersistenceContext. Ta klasa ma następujące kolekcje:

// 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; 

Więc co trzeba zrobić, to rzucić się PersistenceContext do StatefulPersistenceContext, a następnie użyć refleksji uzyskać prywatną kolekcję, którą chcesz i następnie iteracyjne na nim.

Sugeruję, aby zrobić to tylko podczas debugowania kodu. To nie jest publiczny interfejs API i może zostać zahamowany przez nowsze wersje oprogramowania Hibernate.

+0

Dzięki; to bardzo pomoże, gdy następnym razem zdarzy się problem. ;) –

9

Znaleziono @nakosspy post bardzo przydatny. Zainspirowany jego postem, dodałem tę bardzo prostą metodę narzędzia, która wyprowadza zawartość Hibernate Session.

Jak nakosspy powiedział, że jest to TYLKO do celów debugowania, ponieważ jest to 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

Dla hibernacji 4.3.11 musisz użyć 'StatefulPersistenceContext.class.getDeclaredField (" entityByKey ");' i zapisać go jako 'Mapę' (lub inne pole, ponieważ' entityEntries' nie istnieje) - but poza tym koncepcja jest solidna. – jlb

Powiązane problemy