我倾向于将Hibernate与Spring框架结合使用,并使用声明式事务划分功能(例如@Transactional)。
众所周知,hibernate尝试尽可能非侵入性和透明,但这证明更具挑战性使用 lazy-loaded
关系时。
我看到了许多具有不同透明度的设计方案。
fetchType=FetchType.EAGER)
Hibernate.initialize(proxyObj);
初始化集合
initialize
定义接口,但不保证其他实现提供任何等效的接口。 Model
对象本身(使用dynamic proxy或@Transactional
)
loadData()
和loadDataWithDeps()
loadDataWithA()
,....,loadDataWithX()
byId()
个操作
findZzzById(zid)
,然后getYyyIds(zid)
而不是z.getY()
loadData(id, fetchProfile);
我错过了任何选项吗?
在尝试最小化lazy-loaded
关系对应用程序设计的影响时,您首选的方法是什么?
(哦,抱歉WoT)
答案 0 :(得分:26)
众所周知,hibernate试图尽可能地非侵入性和透明性
我会说最初的假设是错误的。转换持久性是一个神话,因为应用程序总是应该关注实体生命周期和被加载的对象图的大小。
请注意,Hibernate无法读取想法,因此如果您知道某个特定操作需要一组特定的依赖关系,那么您需要以某种方式表达您对Hibernate的意图。
从这个角度来看,明确表达这些意图的解决方案(即2,4和7)看起来是合理的,并且不会因缺乏透明度而受到影响。
答案 1 :(得分:7)
我不确定你暗示哪个问题(由懒惰引起),但对我来说最大的痛苦是避免在我自己的应用程序缓存中丢失会话上下文。典型案例:
foo
已加载并放入地图中; foo.getBar()
(以前从未调用过并且延迟评估的内容); 因此,为了解决这个问题,我们有许多规则:
OpenSessionInViewFilter
); try/finally
中),因此子类不必考虑它; 正如您所看到的,这确实无法接近非侵入性和透明。但是成本仍然可以忍受,与我为急切装载所需支付的价格相比。后者的问题是,有时它会在加载单个引用对象时导致蝴蝶效应,更不用说实体集合了。内存消耗,CPU使用率和提到的延迟也差得多,所以我想我可以忍受它。
答案 2 :(得分:3)
如果您正在构建Web应用程序,则非常常见的模式是使用OpenEntityManagerInViewFilter。
如果您正在构建服务,我会在服务的公共方法上打开TX,而不是在DAO上打开TX,因为通常需要获取或更新多个实体。
这将解决任何“延迟加载异常”。如果您需要更高级的性能调优,我认为获取配置文件是可行的方法。