有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Hibernate lazyload应用程序设计

我倾向于将HibernateSpring框架及其声明性事务划分功能(例如@Transactional)结合使用

众所周知,hibernate试图尽可能做到无创透明,然而,这证明在使用lazy-loaded关系时更具挑战性


我看到许多具有不同透明度的设计方案

  1. 使关系不延迟加载(例如,fetchType=FetchType.EAGER)
    • 这就是延迟加载的整个概念
  2. 使用Hibernate.initialize(proxyObj);初始化集合
    • 这意味着与DAO的耦合度相对较高
    • 尽管我们可以用initialize定义接口,但其他实现不保证提供任何等效的接口
  3. 将事务行为添加到持久Model对象本身(使用dynamic proxy@Transactional
    • 我没有尝试过动态代理方法,尽管我似乎从未让@Transactional处理持久对象本身。可能是因为hibernate在代理服务器上运行
    • 交易实际发生时失去控制
  4. 同时提供惰性/非惰性API,例如loadData()loadDataWithDeps()
    • 强制应用程序知道何时使用哪个例程,同样是紧密耦合
    • 方法溢出,loadDataWithA()loadDataWithX()
  5. 强制查找依赖项,例如,仅提供byId()操作
    • 需要大量非面向对象的例程,例如findZzzById(zid),然后getYyyIds(zid)而不是z.getY()
    • 如果事务之间存在较大的处理开销,则逐个获取集合中的每个对象可能很有用
  6. 使应用程序@成为事务的一部分,而不仅仅是DAO
    • 嵌套事务的可能考虑事项
    • 需要适应事务管理的例程(例如,足够小)
    • 编程影响小,但可能导致大型事务
  7. 为DAO提供动态fetch profiles,例如loadData(id, fetchProfile);
    • 应用程序必须知道何时使用哪个配置文件
  8. AoP类型的事务,例如,在必要时拦截操作并执行事务
    • 需要字节码操作或代理使用
    • 执行交易时失去控制
    • 黑魔法,一如既往:)

我错过了任何选择吗


在应用程序设计中尽量减少lazy-loaded关系的影响时,您首选哪种方法

(哦,对不起WoT


共 (3) 个答案

  1. # 1 楼答案

    我不确定你在暗示哪个问题(由懒散引起),但对我来说,最大的痛苦是避免在我自己的应用程序缓存中丢失会话上下文。典型案例:

    • 对象foo被加载并放入地图
    • 另一个线程从映射中获取这个对象,并调用foo.getBar()(以前从未调用过,而且是惰性的)

    因此,为了解决这个问题,我们有一些规则:

    • 尽可能透明地包装会话(例如OpenSessionInViewFilter用于网络应用程序)
    • 为线程/线程池提供公共API,其中db会话绑定/取消绑定在层次结构的某个较高位置(包装在try/finally)完成,这样子类就不必考虑它
    • 在线程之间传递对象时,传递ID而不是对象本身。如果需要,接收线程可以加载对象
    • 缓存对象时,绝不缓存对象,而是缓存其ID。在您的DAO或manager类中有一个抽象方法,在您知道ID的情况下从二级Hibernate缓存加载对象。从二级Hibernate缓存检索对象的成本仍然比去DB便宜得多

    正如你所看到的,这确实远不及非侵入性和透明的。但是,与我为迫不及待的装载而付出的代价相比,成本仍然可以承受。后者的问题是,在加载单个引用对象时,有时会导致蝴蝶效应,更不用说加载实体集合了。内存消耗、CPU使用率和延迟也是最糟糕的,所以我想我可以接受

  2. # 2 楼答案

    一种非常常见的模式是在构建web应用程序时使用OpenEntityManagerInViewFilter

    如果您正在构建一个服务,我会在该服务的公共方法上打开TX,而不是在DAO上,因为一个方法通常需要获取或更新多个实体

    这将解决任何“延迟加载异常”。如果您需要更高级的性能调优工具,我认为获取配置文件是一个不错的选择

  3. # 3 楼答案

    As we all known, hibernate tries to be as non-invasive and as transparent as possible

    我认为最初的假设是错误的。父持久性是一个神话,因为应用程序始终应该考虑实体生命周期和加载的对象图的大小

    请注意,Hibernate无法读取想法,因此,如果您知道特定操作需要一组特定的依赖项,则需要以某种方式表达您的休眠意图

    从这个角度来看,明确表达这些意图(即2、4和7)的解决方案看起来是合理的,并且不存在缺乏透明度的问题