2011-11-07 48 views
1

虽然试图对延迟加载做一些测试,为了检查我是否理解得很好,我完全困惑。混淆懒惰加载

下面是我使用我的测试实体:

@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后,通过分离的Family列表访问懒惰成员属性时,上述测试也没有任何问题! ...这是正常的吗?我是否理解懒惰加载概念?

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

由于提前
乔治

回答

2

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

+0

非常感谢您的帮助,我已经在[这里](http: //www.eclipse.org/forums/index.php/mv/msg/261691/755570/#msg_755570):-) –

0

这可能是因为使用延迟初始化JPA提供者不需要。对于JPA供应商来说这不是必须的要求,但是a hint

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

+0

感谢您的回答。我忘记说我的JPA提供者是EclipseLink,它支持延迟加载AFAIK。 –

2

确保您使用eclipselink代理或使用静态编织。如果你不使用,那么LAZY不会被编织,而且你会拥有EAGER。

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

+0

我在[这里](http://www.eclipse.org/forums/index.php/mv/tree/160098/#page_top)发现了一个类似的问题,并且有一个答案(作为巧合发布一个叫詹姆斯的成员也说:-)),他说:“实际上,编织只需要懒惰的OneToOne/ManyToOne懒惰会在OneToMany中无需编织就能工作。”,这在[here](http://wiki.eclipse.org/Using_EclipseLink_JPA_Extensions_%28ELUG%29#What_You_May_Need_to_Know_About_EclipseLink_JPA_Lazy_Loading)。 –

+0

关于在EntityManegr关闭后访问LAZY关系的支持,我对此没有任何问题,因为我把这个理解为一个优点...我只想确保如果我不访问一个懒惰的关系它不会被加载到内存中,并且显然这不会发生,因为即使在关闭工厂之后(这在我的示例中尝试它时是唯一的),但是家庭实例仍然能够访问他们的成员,并且如上所述,我在关闭工厂之前没有访问他们中的任何一个:( –