美好的一天。我需要检查字段的初始化(加载)。对于此任务,我尝试使用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),但单个对象的结果相同。可能有人知道为什么吗?
答案 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对象,我无法想象它会有太大的不同。