混淆懒惰加载

时间:2011-11-07 23:51:15

标签: jpa lazy-loading eclipselink

在尝试对延迟加载进行一些测试时,为了检查我是否理解它,我完全感到困惑。

这是我在测试中使用的实体:

@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
}

这是我的主要方法:

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

我从延迟加载中理解的是,如果属性被标记为懒惰地获取,并且在管理时不被访问,则它将不会被加载到内存中,并且以后任何尝试访问它都将无法工作。现在令我困惑的是,即使在关闭EM和EMF之后,通过分离的族列表访问惰性成员属性时,上述测试也没有任何问题! ......那是正常的吗?我错过了解懒惰的装载概念吗?

注意:我正在使用带有嵌入式数据库的J2SE环境。我的提供者是EclipseLink

先谢谢你 乔治

3 个答案:

答案 0 :(得分:2)

确保您使用的是eclipselink代理,或使用静态编织。如果你两个都不使用,那么LAZY将不会被编织,你将拥有EAGER。

此外,EclipseLink支持在EntityManager关闭后访问LAZY关系。 虽然工厂关闭后没有。但是,如果对象在缓存中,那么它也可以在关闭后工作。此外,如果您在同一个持久性单元上打开了另一个工厂,则持久性单元仍处于打开状态。

答案 1 :(得分:2)

检查在关闭工厂之前是否未触发toString方法,例如是否正在记录实体。我不建议在toString方法中触发关系,因为这容易出错并且可能会意外触发。打开EclipseLink日志记录将有助于向您展示在工厂生命周期中访问它的位置,假设它不是问题的一部分。

答案 2 :(得分:0)

这可能是因为JPA提供程序不需要使用延迟初始化。它不是JPA提供者的必需条件,而是a hint

当指定FetchType.EAGER时,JPA需要急切地获取数据,但在指定FetchType.LAZY时不需要懒惰地获取数据。