Java Hibernate延迟加载应用程序设计
我倾向于与框架及其声明性事务划分功能(例如,)结合使用 众所周知,hibernate尽可能做到非侵入性和透明性,但在使用Java Hibernate延迟加载应用程序设计,java,hibernate,spring,lazy-loading,application-design,Java,Hibernate,Spring,Lazy Loading,Application Design,我倾向于与框架及其声明性事务划分功能(例如,)结合使用 众所周知,hibernate尽可能做到非侵入性和透明性,但在使用延迟加载关系时,这证明更具挑战性 我看到许多具有不同透明度的设计方案 使关系不延迟加载(例如,fetchType=fetchType.EAGER) 这就是延迟加载的整个概念 使用Hibernate.Initialize(proxyObj)初始化集合 这意味着与DAO的耦合度相对较高 尽管我们可以使用initialize定义接口,但其他实现不保证提供任何等效的接口 将事
延迟加载关系时,这证明更具挑战性
我看到许多具有不同透明度的设计方案
使关系不延迟加载(例如,fetchType=fetchType.EAGER)
- 这就是延迟加载的整个概念李>
使用Hibernate.Initialize(proxyObj)初始化集合代码>
- 这意味着与DAO的耦合度相对较高
- 尽管我们可以使用
initialize
定义接口,但其他实现不保证提供任何等效的接口李>
将事务行为添加到持久的模型
对象本身(使用或@Transactional
)
- 我没有尝试过动态代理方法,尽管我似乎从未让@Transactional处理持久对象本身。可能是因为hibernate在代理服务器上运行李>
- 交易实际发生时失去控制
提供惰性/非惰性API,例如,loadData()
和loadDataWithDeps()
- 强制应用程序知道何时使用哪个例程,同样是紧密耦合
- 方法溢出,
loadDataWithA()
,…,loadDataWithX()
强制查找依赖项,例如,仅提供byId()
操作
- 需要大量非面向对象的例程,例如,
findzzbyid(zid)
,然后getYyyIds(zid)
而不是z.getY()
- 如果事务之间存在较大的处理开销,则逐个获取集合中的每个对象可能很有用李>
使应用程序成为@Transactional的一部分,而不仅仅是
- 嵌套事务的可能考虑事项
- 需要适应事务管理的例程(例如,足够小)
- 编程影响小,但可能导致大型事务
为DAO提供动态的,例如,loadData(id,fetchProfile)代码>
- 应用程序必须知道何时使用哪个配置文件
AoP类型的事务,例如,在必要时拦截操作并执行事务
- 需要字节码操作或代理使用
- 执行交易时失去控制
- 黑魔法,一如既往:)
我错过了任何选择吗
在您的应用程序设计中尝试最小化延迟加载关系的影响时,您首选哪种方法
(哦,很抱歉)一种非常常见的模式是在构建web应用程序时使用
如果您正在构建一个服务,我会在服务的公共方法上打开TX,而不是在DAO上,因为一个方法通常需要获取或更新多个实体
这将解决任何“延迟加载异常”。如果您需要更高级的性能调优工具,我认为获取配置文件是一个不错的选择
众所周知,hibernate尽可能做到非侵入性和透明
我认为最初的假设是错误的。父持久性是一个神话,因为应用程序始终应该考虑实体生命周期和加载的对象图的大小
请注意,Hibernate无法读取想法,因此,如果您知道特定操作需要一组特定的依赖项,则需要以某种方式表达您的休眠意图
从这个角度来看,明确表达这些意图(即2、4和7)的解决方案看起来是合理的,并且不会因缺乏透明度而受损。我不确定您指的是哪个问题(由懒散引起),但对我来说,最大的痛苦是避免在我自己的应用程序缓存中丢失会话上下文。典型案例:
- 对象
foo
加载并放入地图李>
- 另一个线程从映射中获取这个对象,并调用
foo.getBar()
(以前从未调用过并且是惰性计算的)李>
- 轰李>
因此,为了解决这个问题,我们有一些规则:
- 尽可能透明地包装会话(例如,对于Web应用程序,
OpenSessionInViewFilter
)李>
- 为线程/线程池提供公共API,其中db会话绑定/取消绑定在层次结构的某个较高位置(包装在
try/finally
中),这样子类就不必考虑它李>
- 在线程之间传递对象时,传递ID而不是对象本身。如果需要,接收线程可以加载对象李>
- 缓存对象时,绝不缓存对象,而是缓存其ID。在您的DAO或manager类中有一个抽象方法,在您知道ID的情况下从二级Hibernate缓存加载对象。从二级Hibernate缓存检索对象的成本仍然比到DB便宜得多
正如你所看到的,这确实远不及非侵入性和透明性。但是,与我为迫不及待的装载而付出的代价相比,成本仍然可以承受。后者的问题是,在加载单个引用对象时,有时会导致蝴蝶效应,更不用说实体集合了。内存消耗、CPU使用率和延迟也要差得多,所以我想我可以接受。你说得对,当然,尽可能透明的方法目前为止只能起作用。这些都是你想要的不错的选择。伊莫:答案完全正确。事实上,这是一个神话。顺便说一句:我会投票支持选项4和7(或者完全不使用ORM)