jpa 查询集合_避免懒惰的JPA集合

jpa 查询集合

Hibernate(实际上是JPA)具有集合映射:@ OneToMany,@ ManyToMany,@ ElementCollection。 默认情况下,所有这些都是惰性的。 这意味着集合是List或Set接口的特定实现,其中包含对持久性会话的引用,并且只有在访问集合时才从数据库中加载值。 如果您仅偶尔使用集合,则可以节省不必要的数据库查询。

但是,这有一个问题。 在我看来,异常是第二个最常见的异常(在NullPointerException之后),即LazyInitializationException。 问题在于会话通常为您的服务层打开,并且在您将实体返回到视图层后立即关闭。 而且,当您尝试在视图中迭代未初始化的集合时(例如jsp),该集合将引发LazyInitializationException,因为它们所拥有的引用所在的会话已经关闭,并且无法获取项目。

如何解决? 所谓的OpenSessionInView / OpenEntityManagerInView“模式”。 简而言之:您可以创建一个过滤器,以在请求开始时打开会话,并在呈现视图后(而不是在服务层完成之后)关闭会话。 有人称其为反模式,因为它将持久性处理泄漏到视图层,并使设置复杂化。 我不会说那么糟糕:通常,它可以解决问题而不引入其他问题。 但是在我参与的所有最新项目中,我们没有使用OpenSessionInView,而且效果很好。

之所以能正常工作,是因为我们没有使用惰性集合。 但是,您会正确地指出,当您加载单个实体时,您将获取“整个世界”。 好吧,不。 * ToMany映射有两种类型:

  • 值类型映射,其中集合在逻辑上不包含十几个元素。 在大多数情况下,这是@ElementCollection,还有@ * ToMany,带有诸如“ Category”或“ Price”之类的项目,它们只是更复杂的值对象,但自身不包含任何其他映射。 这些类型的集合的另一个共同特征是它们通常与它们自己的实体一起显示在UI中。 例如,您最有可能要显示文章的类别。 对于这种类型的集合,EAGER是更好的选择。 无论如何,您都必须获取它们,为什么不让Hibernate(或任何jpa实现)想到一些巧妙的连接呢? 就像我说的那样-逻辑上集合不超过一打或十二个,因此获取它们不会对性能造成影响。 而且,从逻辑上讲,它们不会与它们一起获取大对象图。
  • 大型核心实体之间的映射。 可以是“用户下的所有订单”或“组织中的所有用户”,“供应商的所有项目”等。您当然不想急于获取它们。 因为如果您为一个组织获取2000个用户,那么每个组织又有1000个订单,而一个订单平均有3个项目,这反过来又包含所有购买该项目的人的集合。.您将最终拥有整个数据库在记忆中。 显然您需要惰性集合,对吗? 好吧,不。 在这种情况下,您根本不应该使用集合映射。 在99%的情况下,这些类型的关系都显示在UI的页面列表中。 或在搜索结果中。 它们永远不会(也永远不会)全部显示在一个屏幕上(或者,如果您的应用程序提供了类似REST API之类的东西,则很少应该在一个API调用中返回它们)。 您必须对其进行查询,并使用query.setMaxResults和query.setFirstResult()(或使用一些限制性条件来限制它们)。 此外,对集合进行映射意味着有人会在某个时候尝试使用它们,这可能会失败。 如果对象已序列化(xml,json等),则将获取集合内容。 您几乎肯定不想发生的事情。 (这里的想法草案:JPA可以有一个PagedList集合,该集合将允许分页的延迟提取,从而消除了查询的需要)

所以,我刚才说的是-永远不要使用惰性集合。 将eager集合用于非常简单的浅表映射,将分页查询用于较大的映射。

好吧,不完全是。 延迟集合在那里并且它们有应用,尽管它是相当有限的。 或者,至少它们比使用的方法适用性差。 这是我发现适用的示例场景。 在我的附带项目中,我有一个Message实体,它拥有一个Picture实体的集合。 用户上载图片时,它会存储在该图片集中。 一条消息的图片不得超过10张,因此该收藏非常渴望获得。 但是,Message是最常用的实体–实际上是在每个请求中获取的。 但是只有一些消息带有图片(您的信息流中有多少条推文有图片上传?)。 因此,我不想让Hibernate状态进行查询只是为了查找给定消息没有图片。 因此,我将图片数量存储在一个单独的字段中,使图片集合变得懒惰,只有在图片数量> 0时才手动对其进行Hibernate.initialize(..)。

因此,在某些情况下,当实体具有属于上述第一类的可选集合时(“小型浅表集合”)。 因此,如果它很小,很浅并且是可选的(例如,在不到20%的情况下使用),则应该使用Lazy来保存不必要的查询。

其他方面–懒惰的收藏会让您的生活更艰难。

参考:Bozho的技术博客上, 避免与我们的JCG合作伙伴 Bozho一起使用懒惰的JPA Collections

相关文章 :


翻译自: https://www.javacodegeeks.com/2011/10/avoid-lazy-jpa-collections.html

jpa 查询集合

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值