# Wie prüfen, ob Hibernate Collection initialisiert?



## byte (5. Feb 2009)

Hallo,

ich teste meine DAOs via _@TransactionConfiguration(defaultRollback = true)_, was auch soweit gut klappt. Nun habe ich mir einen Mechanismus geschrieben, der bestimmte Teile des Objektgraphen automatisch per Join oder Select vorlädt. Ich möchte diesen Mechanismus nun gerne unittesten, weiss jedoch nicht so genau wie. Um zu prüfen, welche Daten im Objektgraph schon geladen sind und welche nicht (als noch lazy sind), müsste ich die Transaktion schließen. Das funktioniert dann natürlich nicht mehr mit dem _defaultRollback = true_. Besser wäre also, die Transaktion zu suspenden. Leider weiss ich nicht, ob und wie das möglich ist. Meine Unittests erben von _AbstractTransactionalTestNGSpringContextTests_. Ich habe versucht, in meiner Testklasse eine Methode mit _@Transactional(propagation = Propagation.NOT_SUPPORTED)_ zu deklarieren und in dieser Methode das Property aufzurufen. Aber offenbar werden diese Annotations in den Unittests ignoriert.

Gibts vielleicht noch eine andere Möglichkeit, bei Hibernate-Objekten zu prüfen, ob ein Property geladen oder noch lazy ist?

Wäre über Anregungen dankbar.

TIA byto


----------



## byte (5. Feb 2009)

Ich habe es nun mit _Hibernate.isInitialized(proxy)_ versucht, aber irgendwie scheint die Methode immer true zurückzuliefern, wenn die Hibernate Session noch offen ist. Wenn ich das Objekt hingegen zum Client weiterreiche (die Session ist dann geschlossen), liefert die Methode false (was dem gewünschten Verhalten entspricht). ???:L


----------



## KSG9|sebastian (25. Feb 2009)

Hi,

Problem ist dass Hibernate.isInitialized für Collections immer "true" zurückgibt. 
API-Doc: "...true if the argument is already initialized, or is not a proxy or *collection*.."

Die Methode liefert nur false wenn das Objekt ein Proxy ist. Im Javamagazin wurde das auch mal beschrieben (glaub für so n Preload-Pattern). Leider funktioniert das ganze nicht für Collections, da die immer "initialisiert" sind.

Du kannst prüfen ob die Elemente in der Collection ein Proxy (und somit lazy) sind. Das könte funktionieren.
Eine gute Möglichkeit um festzustellen ob das Objekt schon geladen ist oder nicht habe ich leider auch noch nicht gefunden. Abfragen auf isInstance o.ä. sind zwar machbar, allerdings auch sehr, sehr unschön


----------



## maki (25. Feb 2009)

>> Gibts vielleicht noch eine andere Möglichkeit, bei Hibernate-Objekten zu prüfen, ob ein Property geladen oder noch lazy ist?

Da fällt mir eben nur  die Sache mit der geschlossenen Session ein, dann weiss man ganz schnell ob es lazy war oder nicht *g*

Alledings würde so ein Unittest schnell zum Integrationstest mutieren, wenn dir das nix ausmacht, wäre das zB ein Weg.


----------



## byte (25. Feb 2009)

KSG9|sebastian hat gesagt.:


> Du kannst prüfen ob die Elemente in der Collection ein Proxy (und somit lazy) sind. Das könte funktionieren.


Das ist doch genau der Punkt. Wie prüfe ich das? Ich habe z.B. eine PersistentList, dessen Elemente noch nicht geladen sind. Die PersistentList ist ja ein Proxy, der bei Bedarf lazy die eigentliche Collection lädt. Ist nun noch eine Session an die PersistentList gebunden, dann liefert Hibernate.isInitialized() true, obwohl das Feld initialized false ist (sieht man im Debugger). Detached man die Collection (die Session der PersistentList ist null), dann liefert Hibernate.isInitialized() false.



> Abfragen auf isInstance o.ä. sind zwar machbar, allerdings auch sehr, sehr unschön


Verstehe nicht, wie mir das helfen soll? Die Collection ist immer eine PersistentList, egal ob attached oder detached, egal ob initialisiert oder nicht.

Ich sehe derzeit nur die Möglichkeit, per Reflection das private Feld initialized zu überprüfen, aber das ist ja ne Brechstangenmethode.


----------



## KSG9|sebastian (25. Feb 2009)

Ich meinte für jedes Element in der Collection Hibernate.isInitialized aufrufen


```
Query qry = em.createQuery("from Person p where p.id=1");
Person pers = qry.getSingleResult();
for(Account acc : pers.getAccounts){
   if(Hibernate.isInitialized(acc)){
       // collection element ist kein proxy
   }
}
```

- Collections sind immer initialisiert
- Objekte sind dann initialisiert wenn sie kein Proxy mehr sind

Falls das nicht passt ist es evtl. ein Bug in Hibernate. Welche Hibernate-Version verwendest du denn?


----------



## byte (25. Feb 2009)

Also nochmal: Es geht mir darum bei offener Session zu prüfen, ob die Elemente einer Collection schon geladen wurden. Dein Tipp macht keinen Sinn, denn wenn ich auf die Elemente der Collection zugreife, um sie per Hibernate.isInitialized() zu überprüfen, dann werden sie ja geladen.


----------

