What I have:
@Entity
public class MyEntity {
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
@JoinColumn(name = "myentiy_id")
private List<Address> addreses;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
@JoinColumn(name = "myentiy_id")
private List<Person> persons;
//....
}
public void handle() {
Session session = createNewSession();
MyEntity entity = (MyEntity) session.get(MyEntity.class, entityId);
proceed(session); // FLUSH, COMMIT, CLOSE session!
Utils.objectToJson(entity); //TROUBLES, because it can't convert to json lazy collections
}
What a problem:
问题是我无法在proceed方法中关闭会话 .
What a solution (coarse solution):
a)在会话关闭之前,强制hibernate拉取惰性集合
entity.getAddresses().size();
entity.getPersons().size();
....
b)也许更优雅的方式是使用 @Fetch(FetchMode.SUBSELECT)
注释
Question:
什么是最佳实践/常用方式/更优雅的方式来做到这一点?意味着将我的对象转换为JSON .
8 回答
使用Hibernate 4.1.6,引入了一个新功能来处理这些惰性关联问题 . 在hibernate.properties或hibernate.cfg.xml中启用hibernate.enable_lazy_load_no_trans属性时,将不再有LazyInitializationException .
更多参考:https://stackoverflow.com/a/11913404/286588
必须获取多个集合时,您需要:
JOIN FETCH一个集合
将Hibernate.initialize用于其余集合 .
因此,在您的情况下,您需要像这样的第一个JPQL查询:
这样,您就可以通过2个SQL查询实现目标,并避免使用笛卡尔积 .
放置Utils.objectToJson(实体);会话结束前致电 .
或者你可以尝试设置获取模式并使用这样的代码
它可能不是接近最佳实践的任何地方,但我通常在集合上调用
SIZE
以在同一事务中加载子项,就像您建议的那样 . 它很干净,不受子元素结构的任何变化的影响,并且产生的SQL开销很低 .尝试使用
Gson
库将对象转换为Jsonservlet示例:
您可以在同一事务中遍历Hibernate对象的Getters,以确保使用以下通用帮助程序类急切地获取所有延迟子对象:
不是最好的解决方案,但这是我得到的:
1)使用此批注对要初始化的getter进行批注:
2)在从数据库中读取对象后,使用此方法(可以放在泛型类中,或者可以使用Object类更改T):
在
@Transactional
中使用Hibernate.initialize()
来初始化延迟对象 .现在,在事务的一侧,您可以获得惰性对象 .