JPA技巧:避免N + 1选择问题

介绍

诸如JPA的ORM框架通过帮助我们在对象<->关系数据映射期间避免了很多样板代码,从而简化了我们的开发过程。 但是,它们还会给表带来一些其他问题,N + 1是其中之一。 在本文中,我们将简短地探讨该问题以及避免这些问题的一些方法。

问题

作为示例,我将使用在线图书订购应用程序的简化版本。 在这样的应用程序中,我可能会创建一个如下所示的实体来代表采购订单–

@Entity
public class PurchaseOrder {@Idprivate String id;private String customerId;@OneToMany(cascade = ALL, fetch = EAGER)@JoinColumn(name = "purchase_order_id")private List<PurchaseOrderItem> purchaseOrderItems = new ArrayList<>();
}

采购订单由订单ID,客户ID和要购买的一个或多个项目组成。 PurchaseOrderItem实体可能具有以下结构–

@Entity
public class PurchaseOrderItem {@Idprivate String id;private String bookId;
}

这些实体已经简化了很多,但是出于本文的目的,这是可以做到的。

现在假设我们需要找到一个客户的订单以在他们的采购订单历史中显示它们。 以下查询将用于此目的–

SELECTP
FROMPurchaseOrder P
WHEREP.customerId = :customerId

转换为SQL后,其外观如下所示–

selectpurchaseor0_.id as id1_1_,purchaseor0_.customer_id as customer2_1_ 
frompurchase_order purchaseor0_ 
wherepurchaseor0_.customer_id = ?

此查询将返回客户拥有的所有采购订单。 但是,为了获取订单项,JPA将针对每个单独的订单发出单独的查询。 例如,如果客户有5个订单,那么JPA将发出5个附加查询以获取这些订单中包含的订单项。 这基本上被称为N + 1问题-1个查询以获取所有N个采购订单,N个查询以获取所有订单商品。

当我们的数据增长时,此行为为我们带来了可伸缩性问题。 即使适量的订单和物品也会造成严重的性能问题。

解决方案

避免渴望获取

这是问题背后的主要原因。 我们应该摆脱从映射中获取的所有渴望。 它们几乎没有任何好处可证明其可用于生产级应用程序。 我们应该将所有关系标记为“懒惰”。

需要注意的重要一点–将关系映射标记为“惰性”并不保证基础持久性提供程序也将其同样对待。 JPA规范不保证延迟获取。 充其量对持久性提供程序而言是一个提示。 但是,考虑到Hibernate,我从未见过这样做。

仅获取实际需要的数据

始终建议使用此方法,而不考虑是否要进行急切/懒惰的访存。

我记得我进行过一次N + 1优化,将REST端点的最大响应时间从17分钟提高到1.5秒 。 端点正在根据某些条件获取单个实体,对于我们当前的示例,该实体将遵循以下原则:

TypedQuery<PurchaseOrder> jpaQuery = entityManager.createQuery("SELECT P FROM PurchaseOrder P WHERE P.customerId = :customerId", PurchaseOrder.class);
jpaQuery.setParameter("customerId", "Sayem");
PurchaseOrder purchaseOrder = jpaQuery.getSingleResult();// after some calculation
anotherRepository.findSomeStuff(purchaseOrder.getId());

id是结果中唯一用于后续计算的数据。

有几个客户有超过一千个订单。 每个命令依次又有数千个其他几种不同类型的子级。 不用说,每当在此端点接收到针对这些订单的请求时,数据库中就会执行数千个查询。
为了提高性能,我所做的就是-

TypedQuery<String> jpaQuery = entityManager.createQuery("SELECT P.id FROM PurchaseOrder P WHERE P.customerId = :customerId", String.class);
jpaQuery.setParameter("customerId", "Sayem");
String orderId = jpaQuery.getSingleResult();// after some calculation
anotherRepository.findSomeStuff(orderId);

只是此更改导致680倍的改进
如果我们要获取多个属性,则可以利用JPA提供的Constructor表达式–

"SELECT " +
"NEW com.codesod.example.jpa.nplusone.dto.PurchaseOrderDTO(P.id, P.orderDate) " +
"FROM " +
"PurchaseOrder P " +
"WHERE " +
"P.customerId = :customerId",
PurchaseOrderDTO.class);
jpaQuery.setParameter("customerId", "Sayem");
List<PurchaseOrderDTO> orders = jpaQuery.getResultList();

使用构造函数表达式的一些注意事项–

  1. 目标DTO必须具有其参数列表与要选择的列匹配的构造函数
  2. 必须指定DTO类的完全限定名称

使用联接提取/实体图

每当我们需要同时获取带有所有子元素的实体时,就可以在查询中使用JOIN FETCH 。 这样可以减少数据库流量,从而提高性能。

JPA 2.1规范引入了实体图,它使我们可以创建静态/动态查询负载计划。
Thorben Janssen ( 这里和这里 )写了几篇文章,详细介绍了它们的用法,值得一看。
这篇文章的一些示例代码可以在Github上找到。

翻译自: https://www.javacodegeeks.com/2018/04/jpa-tips-avoiding-the-n-1-select-problem.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/346590.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python设计模式有哪些_设计模式教程

设计模式是软件设计中常见问题的典型解决方案。它们就像能根据需求进行调整的预制蓝图&#xff0c;可用于解决代码中反复出现的设计问题。 设计模式与方法或库的使用方式不同&#xff0c;你很难直接在自己的程序中套用某个设计模式。模式并不是一段特定的代码&#xff0c;而是解…

一建机电实务教材电子版_必背!一建《机电实务》高频考点,每日一背

本文部分来自学霸笔记&#xff0c;点击链接关注公众号下载【工业管道的施工程序】1.管道施工前应具备的开工条件&#xff1a;1.工程设计图纸及其他技术文件完整齐全&#xff0c;已按程序进行了工程交底和图纸会审。2.施工组织设计和施工方案已批准&#xff0c;并已进行了技术和…

鸿蒙开发者社区入口,鸿蒙OS 社区

OpenHarmony community欢迎来到OpenHarmony社区&#xff01;Community仓库用于管理OpenHarmony社区治理、开发者贡献指南、开发者贡献协议、社区交流等内容。社区治理组织架构社区交流OpenHarmony社区通过项目管理委员会( Project Management Committee)管理OpenHarmony社区。请…

python 数据去重_科学网—python学习——根据条件提取数据,并去重 - 李立的博文...

[Python字符串提取] 摘要&#xff1a;根据要求进行字符串的提取&#xff0c;并去重 导入分析所需的库import pandas as pd 构造数据集 as1 pd.DataFrame({a:[1,2,3,4], b:[adwdea,asdw;swa,des,swa,dwad;asdw;swa,se;dw,asd;erf,de,de]})编写分析函数 def trans(b): as1[c] b…

assertionerror python_Python成为专业人士笔记–内置模块Modules和函数Functions

“专业人士笔记”系列目录&#xff1a;创帆云&#xff1a;Python成为专业人士笔记--强烈建议收藏&#xff01;每日持续更新&#xff01;​zhuanlan.zhihu.com模块是一个包含Python定义和语句的文件&#xff0c;而函数是执行逻辑的一段代码 。要检查python中内置的函数&#xff…

android 7.0 禁止 imei,Android一些适配

# Android 版本适配重点其他细节请查看官网对应版本&#xff1a;https://developer.android.com/preview## 7.01. 后台优化- 移除了以下静态注册广播通知(动态注册可继续使用)&#xff1a;CONNECTIVITY_ACTION ACTION_NEW_PICTURE ACTION_NEW_VIDEO2. 系统权限更改- Android 7…

【Filament】纹理贴图

1 前言 本文主要介绍使用 Filament 实现纹理贴图&#xff0c;读者如果对 Filament 不太熟悉&#xff0c;请回顾以下内容。 Filament环境搭建绘制三角形绘制矩形绘制圆形绘制立方体 Filament 纹理坐标的 x、y 轴正方向分别朝右和朝上&#xff0c;其 y 轴正方向朝向与 OpenGL ES…

认识JSON绑定:概述系列

JSON绑定的Java API&#xff08;JSON-B&#xff09;1.0增强了Java EE平台对JSON数据交换格式的整体支持。 事实证明&#xff0c; 用于JSON处理的Java API&#xff08;JSON-P&#xff09;1.1十分流行&#xff0c;它们共同构成了完美的合作伙伴&#xff0c;填补了Java EE的JSON功…

c++可视化界面_新基建的福音:智慧楼宇可视化监控系统引领智能化新时代

前言智慧楼宇和人们的生活息息相关&#xff0c;楼宇智能化程度的提高&#xff0c;会极大程度的改善人们的生活品质&#xff0c;在当前 工业互联网 大背景下受到很大关注。目前 智慧楼宇可视化监控 的主要优点包括:智慧化 -- 智慧楼宇是一个生态系统&#xff0c;像人一样拥有感知…

table 多行 宽度不一致_“table”除了桌子,你还知道一些别的意思吗?

就比如"nine-nine table"这可是小学一年级必须要掌握的知识实际上&#xff0c;nine-nine table是九九乘法表&#xff0c;乘法表可以用times table表示&#xff0c;书面用语是multiplication table。table除了桌子的意思外&#xff0c;还有一些别的意思和表达&#xf…

android uri db,Android ContentProvider封装数据库和文件读写总结

本文是我各处东拼西凑加上自己实现一个ContentProvider的使用总结&#xff0c;留做后用&#xff0c;主要介绍ContentProvider的集成方法。一、综述ContentProvider是Android四大组件之一&#xff0c;其核心功能是提供应用间的统一的数据访问方式&#xff0c;当然也可以用于应用…

ddos攻击工具_简单有效的ddos攻击防御方法

做过网站的站长大多有被ddos攻击的经历&#xff0c;不少人面对竞争对手的网站就是直接雇人ddos攻击网站&#xff0c;导致对方网站长期打不开&#xff0c;最后无奈关闭网站&#xff0c;初尧今天就告诉大家一个最简单也是最有效的防御方法。高防服务器/高防IP对于游戏&#xff0c…

android gpio驱动实例,安卓gpio操作示例

GPIO值在RK3288中的计算方法为&#xff1a;bank32pin&#xff0c;如&#xff1a;GPIO7A3&#xff1a; 732 0*8 3227GPIO0B5: 032 1*8 5131. 导出/sys/class/gpio# echo 44 > export2. 设置方向/sys/class/gpio/gpio44# echo out > direction3. 查看方向/sys/class/gpio/…

回调函数中有回调函数吗_嗨,那里有回调!

回调函数中有回调函数吗因为是我的书包&#xff0c;所以我喜欢JavaScript 。 实际上&#xff0c;我已经开始喜欢JavaScritp的面向异步回调的编程风格 。 因此&#xff0c;当我发现自己处于非JavaScript环境中时&#xff08;例如Java&#xff09; &#xff0c;我往往会错过使用回…

python的django_django能用来做什么

Django是什么 Django是一个开放源代码的Web应用框架&#xff0c;由Python写成。采用了MT‘V的框架模式&#xff0c;即模型M&#xff0c;模板T和视图V。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的&#xff0c;即是CMS&#xff08;内容管理系统&am…

小程序确定取消弹窗_浅析微信小程序modal弹窗关闭默认会执行cancel问题

在我们使用小程序的modal组件时候&#xff0c;有的时候会碰到一个问题&#xff0c;那就是弹框的关闭&#xff0c;我们并没有选择取消或确定&#xff0c;而是点击弹框之外的部分&#xff0c;这个时候弹框会关闭&#xff0c;按理来说不会触发取消和确定的绑定事件&#xff0c;但是…

android n 发布时间,Android N 正式版将在9月发布

【环球科技综合报道】据外媒5月8日报道&#xff0c;谷歌预计将在9月份放出正式版Android N。三星、华为、LG、HTC和黑莓等品牌手机将获Android N升级。此前谷歌发出的路线图中的升级安排&#xff1a;3月: Android N 开发者预览版 1 (alpha)4月: Android N 开发者预览版 2 (beta…

ios realm 文件_关于ios:具有后台进程的Realm实例会丢失数据

我将Realm for Swift与仅内存配置一起使用。 由于在后台线程中更新数据库&#xff0c;因此每次使用时都会创建一个Realm实例。 在Realm文档中提到了此问题&#xff0c;这里还有另一个问题https://stackoverflow.com/a/45375608/613121。但是通过测试数据库&#xff0c;我注意到…

datatable如何生成级联数据_如何把Excel表数据批量生成条形码

条形码属于一维条码&#xff0c;是将宽度不等的多个黑条和空白&#xff0c;按照一定的编码规则排列&#xff0c;用以表达一组信息的图形标识符&#xff0c;条形码的种类比较多&#xff0c;比如常用的Code128码&#xff0c;Code39码&#xff0c;Code93码&#xff0c;EAN-13码&am…

android数字累加,Android自己设置View之数字自动增长

第一次写文&#xff0c;请多指教&#xff0c;有何问题及改进建议都可以告诉我-.-Idea来自金山词霸App的单词计数&#xff0c;下面先放图autoNumber.gif如上图&#xff0c;就是&#xff0c;下面开始进入自己设置View自己设置View步骤1. 自己设置属性2. 生成构造方法3. onMeasure…