对于延迟加载的字段,Hibernate为“isInitialized”

时间:2014-01-31 09:34:33

标签: hibernate jpa

美好的一天。我需要检查字段的初始化(加载)。对于此任务,我尝试使用Hibernate.isInitialized。我有以下实体:

@Entity
public class Contractor {
    /* ... */

    @OneToMany(mappedBy = "contractor", fetch = FetchType.LAZY)
    private List<Work> works = new ArrayList<Work>();

    /* ... */
}

@Entity
public class Work {
    /* ... */

    @ManyToOne(fetch = FetchType.LAZY)
    private Contractor contractor;

    @ManyToOne(fetch = FetchType.LAZY)
    private Project project;

    /* ... */
}

@Entity
public class Project {
    /* ... */

    @OneToMany(mappedBy = "project", fetch = FetchType.LAZY)
    private List<Work> works = new ArrayList<Work>();

    /* ... */
}

然后我尝试按照以下方法获取实体:

List<Contractor> list = em.createQuery("SELECT c FROM Contractor c").getResultList();
    for (Contractor contractor : list) {
        Hibernate.initialize(contractor.getComments());
        Hibernate.initialize(contractor.getWorks());
        for (Work work : contractor.getWorks()) {
            Hibernate.initialize(work.getProject());
        }
    }
return list;

之后,我通过两种方式检查字段的初始化符号(用于序列化):

Project p = contractor.getWorks().get(0).getProject();
Field f = Hibernate.getClass(p).getDeclaredField("works");
f.setAccessible(true);
System.out.println(Hibernate.isInitialized(f.get(p)));

System.out.println(Hibernate.isInitialized(contractor.getWorks().get(0).getProject().getWorks()));

集合的结果不同(true,false),但单个对象的结果相同。可能有人知道为什么吗?

2 个答案:

答案 0 :(得分:0)

您可以确保在查询本身中提取您的惰性关系,并避免检查它们是否已初始化:

SELECT c FROM Contractor c JOIN FETCH c.comments JOIN FETCH c.works

JOIN FETCH是一种特殊类型的连接,它只是确保加载相关实体。这仍将只返回承包商对象,但它将确保已加载相关的注释和工作(即使它们被声明为惰性)。

<强> - 编辑 -

也许您可以使用标准JPA API进行验证。 PersistenceUnitUtils类和PersistenceUtil都有两种有用的方法:

boolean isLoaded(java.lang.Object entity) 

确定属于持久性单元的实体的加载状态。

boolean isLoaded(java.lang.Object entity, java.lang.String attributeName) 

确定属于持久性单元的实体的给定持久属性的加载状态。

这些方法也应该为你做好准备,希望以一致的方式。

答案 1 :(得分:0)

Hibernate persisting ArrayList - Issues

我有类似的问题。需要注释我的班级

@OneToMany(mappedBy="tournament")
private List<String> registered;

更改为此

@ElementCollection
@CollectionTable (name = "tournament_eligible", joinColumns=@JoinColumn(name="id"))
private List<String> username; // Contains a list of eligible members 

这解决了我的问题,虽然我的列表中只有String对象,我无法想象它会有太大的不同。