Hibernate 为 @ManyToOne JPA 注解属性创建 N+1 查询

2023-11-24

我有这些课程:

@Entity
public class Invoice implements Serializable {
    @Id
    @Basic(optional = false)
    private Integer number;

    private BigDecimal value;

    //Getters and setters
}

@Entity
public class InvoiceItem implements Serializable {
    @EmbeddedId
    protected InvoiceItemPK invoiceItemPk;

    @ManyToOne
    @JoinColumn(name = "invoice_number", insertable = false, updatable = false)
    private Invoice invoice;

    //Getters and setters
}

当我运行这个查询时:

session.createQuery("select i from InvoiceItem i").list();

它执行一个查询来从 InvoiceItem 中选择记录,如果我有 10000 个发票项目,它会生成 10000 个附加查询来从每个 InvoiceItem 中选择发票。

我认为如果所有的记录都可以在一个sql中获取的话会好很多。实际上,我觉得很奇怪为什么它不是默认行为。

那么,我该怎么做呢?


这里的问题与Hibernate无关,而是与JPA有关。

在 JPA 1.0 之前,Hibernate 3 对所有关联都使用延迟加载。

然而,JPA 1.0 规范使用FetchType.LAZY仅适用于收藏协会:

  • @OneToMany,
  • @ManyToMany
  • @ElementCollection)

The @ManyToOne and @OneToOne协会使用FetchType.EAGER默认情况下,从性能角度来看这非常糟糕。

这里描述的行为称为 [N+1 查询问题][5],发生这种情况是因为 Hibernate 需要确保@ManyToOne关联在将结果返回给用户之前初始化。

现在,如果您使用直接获取entityManager.find,Hibernate可以使用LEFT JOIN来初始化FetchTYpe.EAGER协会。

但是,当执行未显式使用 JOIN FETCH 子句的查询时,Hibernate 将不会使用 JOIN 来获取FetchTYpe.EAGER关联,因为它不能改变您已经指定如何构建的查询。所以,只能使用二次查询。

修复方法很简单。只需使用FetchType.LAZY对于所有协会:

   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "invoice_number", insertable = false, updatable = false)
   private Invoice invoice;

更多,您应该使用超坚持实用程序断言 JPA 和 Hibernate 执行的语句数。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Hibernate 为 @ManyToOne JPA 注解属性创建 N+1 查询 的相关文章

随机推荐

  • 如何从 Git 存储库中删除工作树

    我想将我的 Git 存储库转换为裸存储库 我清楚地记得类似 git remove tree 之类的东西以前完成过这项工作 但我在 1 7 上找不到它 你能帮我一下吗 谢谢大家 这是通过将存储库移动到另一个地方然后设置 bare true 选
  • 在 VS2010 中调试期间排除某些项目单步执行?

    我正在一个大型 VS2010 解决方案 全部用 C 编写 中处理几个项目 A 和 B 在很多情况下 项目 A 中的方法会调用解决方案中我不负责的一个或多个项目 而这些项目又会调用项目 B 当使用项目 A 中的调试器单步执行时 我被迫在我最终
  • Mysema Querydsl:没有 JPAQuery#list() 方法

    一些在线示例Mysema 查询DSL使用依赖于JPAQuery list 方法 例如这个 stackoverflow 答案包含 GROUP BY COUNT 聚合示例 整篇文章中也提到了官方文档 但是 我在网上没有看到这种方法JPAQuer
  • 在 Objective-C 中通过引用传递数组

    我想通过引用传递 NSMutableArray 以便可以通过另一种方法更改它 正确的语法是什么 Thanks Objective C 对象始终通过引用 使用指针 传递 您不能通过值传递它们 IE 以下是好的 void mutateArray
  • Spring JPA ExampleMatcher 比较日期条件

    我正在使用 Spring JPA 并使用示例匹配器获取数据列表 源代码如下 public Page
  • 如果表达式的中间结果溢出,是否属于未定义行为?

    这个问题是另一个问题的结果那么问题 示例代码 include
  • 杀死java中正在运行的线程?

    java中如何杀死正在运行的线程 您可以通过调用来要求线程中断Thread interrupt 请注意 存在一些具有类似语义的其他方法 stop and destroy 但他们是已弃用 因为他们是unsafe 不要试图使用它们
  • Angular 中的货币格式化指令

    我需要一个指令来过滤货币字段 因此用户只需键入并隐含小数点 Needs 将十进制字段格式化为用户类型 从用户键入的百分之位开始 因此 他们会输入 4 并看到 0 04 输入 42 并看到 0 42 输入298023并看到 2980 23 字
  • Rails:带有索引的 fields_for?

    有没有一种方法 或实现类似功能的方法 来执行fields for with index 例子 正在渲染的部分需要知道当前索引在fields for loop 答案很简单 因为 Rails 中提供了解决方案 您可以使用f options参数
  • Delphi XE3 DataSnap Server 中的访问请求标头

    我正在 Delphi XE3 中实现 REST 服务器 API 大约十年来第一次使用 Delphi 所以有点生疏 目前它使用 Indy 服务器进行调试 但最终它将成为一个 ISAPI dll 现在我已经实现了许多 TDSServerClas
  • Android 操作栏 Sherlock 带选项卡

    我正在尝试实现 ActionBar Sherlock 其下方带有选项卡 如上面的线框所示 我应该使用 TabActivity 吗 因为我看到它已被弃用 这是实现相同目标的最佳方法 我用一个实现了这个功能SherlockFragmentAct
  • 用于调试和错误的不同 log4j 布局?

    在 log4j 中 有没有办法让 logger error 和 logger debug 包含不同的输出布局 我希望错误包含方法名称和行号 这两者都会降低应用程序性能 EDIT 添加 apache log4j extras 后 以下配置文件
  • 无法验证回调 URL 或验证令牌。请验证所提供的信息或稍后重试

    我一直在遵循 facebook 机器人设置指南 并设置了一个在 EC2 实例上运行的回调 URL 我在尝试验证回调 url 并验证令牌时收到错误 请参阅此标题 https 360 finance 1337 webhook是我的 webhoo
  • 如何防止多次附加事件处理程序?

    我有一个函数 它将附加click我的元素的事件处理程序 function attachClickToElem elem on click function alert Hello World 问题是每当我调用这个函数时 nclick处理程序
  • 使用 R 中的 stringr 提取特定单词周围的单词样本

    我在 SO 上看到了一些关于这个主题的类似问题 但它们的措辞似乎不正确 example 或用不同的语言 example 在我的场景中 我认为所有被空白包围的东西都是一个单词 表情符号 数字 不是真正单词的字母串 我不在乎 我只想获取找到的字
  • 下拉并按住时 UIRefreshcontrol 抖动

    我在 tableviewcontroller 中创建了一个 UIRefreshcontrol 如下所示 refresh UIRefreshControl alloc init refresh attributedTitle NSAttrib
  • 提高具有大量连接的视图的性能[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 我有一个使用 11 个外部
  • 比较 Spark 中当前行和前一行的值

    我正在尝试比较下面当前行和上一行的记录DataFrame 我想计算金额列 scala gt val dataset sc parallelize Seq 1 123 50 2 456 30 3 456 70 4 789 80 toDF SL
  • R 命名空间访问和 match.fun

    我正在开发一个 R 包 其中一个函数包含match fun调用导入到包命名空间的包中的函数 但是在加载包时 match funcall 找不到函数名 从哈德利 威克姆的描述我认为我做的一切都是正确的 但事实显然并非如此 Example in
  • Hibernate 为 @ManyToOne JPA 注解属性创建 N+1 查询

    我有这些课程 Entity public class Invoice implements Serializable Id Basic optional false private Integer number private BigDec