confused about Lazy loading

2019-08-11 02:58发布

问题:

While trying to do some tests on lazy loading, to check if i'm understanding it well, i got totally confused.

Here's the entities i'm using on my test:

@Entity
public class Family {
@Id
private int id;


@OneToMany(mappedBy="family", fetch=FetchType.LAZY)
private Set<Person> members;

//getters & setters

public String toString(){
    String s="";
    for(Person p:getMembers()){
        s+=p.getFirstName();
    }
    return s;
}
}

@Entity
public class Person implements Comparable<Person>{
@Id
private int id;

private String firstName;
private String lastName;

@ManyToOne
private Family family;

//getters &setters
}

here's my main method:

public static void main(String[] args) {
    factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
    em = factory.createEntityManager();

    Query q = em.createQuery("select f from Family f");
    List<Family> families= q.getResultList();

    em.clear();
    em.close();
    factory.close();

    for(Family f:families){
        System.out.println(f);
    }
}

What i understood from lazy loading, is that if an attribute is marked to be fetched lazily, and doesn't get accessed while it's managed, it won't be loaded in memory and any attempt to access it later won't work. Now what confuses me is that the test described above doesn't have any problem when accessing the lazy members attribute through the detached Family list, even after closing the EM and the EMF ! ... Is that normal? Am-i miss-understanding the lazy loading concept?

Note : I'm using a J2SE environment with an embedded DB. My provider is EclipseLink

Thanks in Advance
George

回答1:

Check that your toString method is not triggered before the factory is closed, such as if the entity is being logged. I would not recommend triggering relationship in a toString method as this is error prone and can be triggered unexpectedly. Turning on EclipseLink logging will help show you where it gets accessed in the factory's lifecycle, assuming it is not part of the problem.



回答2:

Ensure that you are using the eclipselink agent, or using static weaving. If you are using neither, then LAZY will not be weaved, and you will have EAGER.

Also EclipseLink supports access to LAZY relationships after the EntityManager is closed. Although not after the factory is closed. However if the object was in the cache, then it may work after being closed as well. Also, if you have another factory open on the same persistence unit, then the persistence unit is still open.



回答3:

It might be because the JPA provider is not required to use lazy initialization. It is not a must requirement for a JPA provider but a hint.

The JPA is required to eagerly fetch data when FetchType.EAGER is specified, but is not required to lazily fetch data when FetchType.LAZY is specified.