Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA call method on lazy (not loaded) collection when detached not working as expected in Eclipselink

lately I experimented a little with JPA to try to understand the whole framework a little more. I am using Eclipselink as JPA provider.

I have two entities with a @OneToMany relationship (one person has many addresses) that is lazy loaded.

When I load a person entity, detach it and then try to access the (not loaded) addresses... it works as a charm. When debugging I can see that a database query is executed when executing the size() method of the address list.

I do not understand why that works. I would expect some kind of exception. I have read quite a few about jpa and the like in the last days (i. e. this link) but everything pointed me to the conclusion that it should not work.

Can anyone please explain why that works?

@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);

    }
}

The resulting log would be

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}]}}
like image 293
Filou Avatar asked Nov 09 '22 00:11

Filou


1 Answers

As described here detach removes the Entity from the context so that it is no longer managed. Since the context is still available though, untriggered lazy collections can still be fetched if needed, and EclipseLink felt this more valuable than throwing an exception. This is considered a feature of EclipseLink, and is allowed by the JPA spec despite other providers not enabling the behavior by default.

like image 111
Chris Avatar answered Nov 14 '22 22:11

Chris