ultimamente ho sperimentato un po 'con JPA per cercare di capire un po' di più l'intero framework. Sto usando Eclipselink come provider JPA.Metodo di chiamata JPA su raccolta lenta (non caricata) in caso di distacco non funzionante come previsto in Eclipselink
Ho due entità con una relazione @OneToMany
(una persona ha molti indirizzi) che è pigro caricato.
Quando carico un'entità persona, lo scollego e quindi provo ad accedere agli indirizzi (non caricati) ... funziona come un incantesimo. Durante il debug posso vedere che una query di database viene eseguita quando si esegue il metodo size()
della lista di indirizzi.
Non capisco perché funzioni. Mi aspetterei un qualche tipo di eccezione. Ho letto un bel po 'su jpa e simili negli ultimi giorni (cioè this link) ma tutto mi ha portato alla conclusione che non dovrebbe funzionare.
Qualcuno può spiegare perché funziona?
@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);
}
}
Il registro risultante sarebbe
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}]}}
perché con EclipseLink non stanno realmente "staccando" gli oggetti nel modo in cui le specifiche JPA intendono (cioè disconnettendosi dal DB), quindi conservano le informazioni di connessione ... quindi recupera il campo (anche se non dovrebbe se veramente "distaccato"). Se hai effettuato la stessa operazione su altri fornitori JPA, genererebbe un'eccezione in genere se un campo non fosse stato rimosso. –
È possibile controllare, se l'entità è correttamente staccata, chiamando [em.contains] (http://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#contains%28java.lang.Object % 29) –