in letzter Zeit experimentierte ich ein wenig mit JPA zu versuchen, das gesamte Framework ein wenig mehr zu verstehen. Ich benutze Eclipselink als JPA-Anbieter.JPA-Aufruf-Methode auf lazy (nicht geladen) Sammlung, wenn gelöst nicht funktioniert wie erwartet in Eclipselink
Ich habe zwei Entitäten mit einer Beziehung (eine Person hat viele Adressen), die faul geladen ist.
Wenn ich eine Personenentität lade, entferne sie und versuche dann auf die (nicht geladenen) Adressen zuzugreifen ... es wirkt wie ein Zauber. Beim Debuggen kann ich sehen, dass eine Datenbankabfrage ausgeführt wird, wenn die size()
Methode der Adressliste ausgeführt wird.
Ich verstehe nicht, warum das funktioniert. Ich würde eine Art Ausnahme erwarten. Ich habe in den letzten Tagen einiges über jpa und Ähnliches gelesen (ich z. B. this link), aber alles wies mich auf die Schlussfolgerung hin, dass es nicht funktionieren sollte.
Kann jemand bitte erklären, warum das funktioniert?
@Stateless
public class Test {
@PersistenceContext(unitName="TestPU") EntityManager em;
public void test() {
Person person = em.find(Person.class, 1);
System.out.println(person);
System.out.println("em.contains(person): " + em.contains(person);
em.detach(person);
System.out.println("em.contains(person): " + em.contains(person);
person.getAddresses().size();
System.out.println("em.contains(person): " + em.contains(person);
System.out.println(person);
}
}
Das resultierende Protokoll
DEBUG: SELECT ... from PERSON WHERE (id = ?)
Person{id=1, name=Test, addresses={IndirectList: not instantiated}}
em.contains(person): true
em.contains(person): false
DEBUG: SELECT ... FROM ADDRESSES where (address_fk = ?)
em.contains(person): false
Person{id=1, name=Test, addresses={[Address{id=10, city=Testcity}]}}
weil sie mit EclipseLink die Objekte nicht wirklich "loslösen", wie es die JPA-Spezifikation beabsichtigt (dh die Verbindung zur DB trennt), so dass sie die Verbindungsinformationen behalten ... daher ruft sie das Feld ab (obwohl es nicht sollte) wenn wirklich "abgelöst"). Wenn Sie dieselbe Operation für andere JPA-Anbieter ausgeführt haben, würden sie normalerweise eine Ausnahme auslösen, wenn ein Feld nicht getrennt wurde. –
Sie können überprüfen, ob die Entität durch Aufrufen von [em.contains] (http://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#contains%28java.lang.Object) ordnungsgemäß getrennt wurde % 29) –