休眠事实:访存策略的重要性

在使用ORM工具时,每个人都承认数据库设计和实体到表映射的重要性。 这些方面引起了很多关注,而诸如获取策略之类的事情可能只是推迟了。

我认为,不应将实体获取策略与实体映射设计分开,因为除非经过适当设计,否则它可能会影响整体应用程序性能。

在Hibernate和JPA如此流行之前,设计每个查询需要付出大量的努力,因为您必须明确选择要从中选择的所有联接以及所有您感兴趣的列。足够,DBA可以优化运行缓慢的查询。

在JPA时代,JPA-QL或HQL查询正在获取实体及其一些关联关系。 这使开发变得容易,因为它使我们免于手动选择我们感兴趣的所有表字段的麻烦,有时会自动生成联接或其他查询来满足我们的需求。

这是一把双刃剑。 一方面,您可以更快地交付功能,但如果自动生成的SQL查询效率不高,则应用程序的整体性能可能会受到严重影响。

那么,实体获取策略是什么?

当JPA加载实体时,它也会同时加载所有EAGER或“ join fetch”关联。 只要打开持久性上下文,在LAZY关联中导航也将通过其他已执行的查询来获取这些关联。

默认情况下,将更容易地自动获取JPA @ManyToOne和@OneToOne批注,而将@OneToMany和@ManyToMany关系视为LAZY。 这是默认策略,并且Hibernate不会神奇地优化对象检索,它只会执行所指示的操作。

尽管小型项目不需要全面的实体获取计划,但中大型应用程序永远都不应忽略它。

从一开始就计划获取策略,并在整个开发周期中进行调整,这并不是“过早的优化”,而这只是任何ORM设计的自然组成部分。

默认的获取策略是您通过JPA映射定义的策略,而手动连接获取则是在使用JPA-QL查询时定义的策略。

我能给您的最佳建议是赞成手动获取策略(在使用获取操作符的JPA-QL查询中定义)。 尽管一定要急切地获取某些@ManyToOne或@OneToOne关联,但在大多数情况下,并不是每个获取操作都需要它们。

对于儿童协会,将它们标记为LAZY并仅在需要时才“联接提取”它们总是比较安全的,因为它们可以轻松地生成带有不需要联接的大型SQL结果集。

将大多数关联定义为LAZY要求我们使用“ join fetch” JPA-QL运算符,并且仅检索满足给定请求所需的关联。 如果您忘记正确地“联接获取”,则在浏览惰性关联时,持久性上下文将代表您运行查询,这可能会产生“ N + 1”问题,或者可能是通过简单联接检索到的其他SQL查询首先。

作为一个具体的例子,让我们从下图开始:

产品2

产品实体关联映射为:

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "company_id", nullable = false)
private Company company;@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "product", optional = false)
private WarehouseProductInfo warehouseProductInfo;@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "importer_id")
private Importer importer;@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "product", orphanRemoval = true)
@OrderBy("index")
private Set<Image> images = new LinkedHashSet<Image>();

大多数关联都标记为LAZY,因为每次加载产品时都不需要获取所有关联。 仅在显示库存信息时才需要仓库。 导入程序仅在某些显示中使用,我们将在必要时提取它。 图像是惰性的,因为并非所有视图都需要显示这些图像。

因为我们所有的观点都需要它,所以只有公司热切地被获取,并且在我们的应用程序中,始终必须在给定公司的背景下考虑产品。

即使@ManyToOne默认使用EAGER fetch选项,最好还是显式地设置默认的获取策略(这会使代码更具自描述性)。

用例1:通过id加载产品将生成以下SQL

SELECT product0_.id          AS id1_7_1_,product0_.code        AS code2_7_1_,product0_.company_id  AS company_4_7_1_,product0_.importer_id AS importer5_7_1_,product0_.name        AS name3_7_1_,company1_.id          AS id1_1_0_,company1_.name        AS name2_1_0_
FROM   product product0_
INNER JOIN company company1_ ON product0_.company_id = company1_.id
WHERE  product0_.id = ?

每次我们通过实体管理器加载时,都会使用默认的获取策略,这意味着公司将与我们选择的产品一起获取。

用例2:通过JPA-QL查询选择产品(绕过持久性上下文第一级缓存)

entityManager.createQuery("select p " +"from Product p " +"where p.id = :productId", Product.class)
.setParameter("productId", productId)
.getSingleResult();

这将执行以下SQL查询:

SELECT product0_.id          AS id1_7_,product0_.code        AS code2_7_,product0_.company_id  AS company_4_7_,product0_.importer_id AS importer5_7_,product0_.name        AS name3_7_
FROM   product product0_
WHERE  product0_.id = ?

因此,使用JPA-QL会覆盖默认的获取策略,但是如果我们要浏览惰性关联,它仍然使我们容易受到攻击。 如果Persistence Context关闭,则在访问惰性关系时会出现LazyInitializationException,但如果未关闭,则会生成其他选择查询,这可能会影响应用程序性能。

用例3:选择具有相关仓库和进口商关联的产品列表:

entityManager.createQuery("select p " +"from Product p " +"inner join fetch p.warehouseProductInfo " +"inner join fetch p.importer", Product.class)
.getResultList();

这将生成以下SQL:

SELECT product0_.id          AS id1_7_0_,warehousep1_.id       AS id1_11_1_,importer2_.id         AS id1_3_2_,product0_.code        AS code2_7_0_,product0_.company_id  AS company_4_7_0_,product0_.importer_id AS importer5_7_0_,product0_.name        AS name3_7_0_,warehousep1_.quantity AS quantity2_11_1_,importer2_.name       AS name2_3_2_
FROM   product product0_
INNER JOIN warehouseproductinfo warehousep1_ ON product0_.id = warehousep1_.id
INNER JOIN importer importer2_ ON product0_.importer_id = importer2_.id

在这里,您可以看到JPA-QL显式提取策略将覆盖默认策略。 因为我们尚未指定与Company的“ join fetch”,所以将忽略EAGER关联。

用例4:在显式加入获取产品的同时选择一系列图像,即使所选实体不是我们要覆盖其策略的实体,也将覆盖默认策略:

entityManager.createQuery("select i " +"from Image i " +"inner join fetch i.product p " +"where p.id = :productId", Image.class)
.setParameter("productId", productId)
.getResultList();

这将生成以下SQL:

SELECT image0_.id            AS id1_2_0_,product1_.id          AS id1_7_1_,image0_.index         AS index2_2_0_,image0_.name          AS name3_2_0_,image0_.product_id    AS product_4_2_0_,product1_.code        AS code2_7_1_,product1_.company_id  AS company_4_7_1_,product1_.importer_id AS importer5_7_1_,product1_.name        AS name3_7_1_
FROM   image image0_
INNER JOIN product product1_ ON image0_.product_id = product1_.id
WHERE  product1_.id = ?

我还需要添加一件事,这与WarehouseProductInfo的@oneToOne关系有关。 对于可选的@OnetoOne关联,将忽略LAZY属性,因为Hiberante必须知道它是否必须使用null或代理来填充您的Entity。 在我们的示例中,将其强制性是有意义的,因为无论如何每种产品都位于仓库中。 在其他情况下,您可以简单地使关联成为单向的,并仅保留控制链接的部分(外键所在的部分)。

  • 代码可在GitHub上获得 。

参考: Hibernate Facts:从JCG合作伙伴 Vlad Mihalcea的Vlad Mihalcea博客博客中获取策略的重要性 。

翻译自: https://www.javacodegeeks.com/2013/11/hibernate-facts-the-importance-of-fetch-strategy.html

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

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

相关文章

自定义checkbox样式

通过选中时添加背景图片自定义CheckBox样式 效果&#xff1a; CSS样式&#xff1a; <style type"text/css>label {width: 10%;display: flex;display: -webkit-flex;display: -moz-flex;flex-direction: row;justify-content: center;align-items: center;}label i…

安装步骤

1、安装node&#xff0c;安装全局webpack&#xff0c;npm init 生成package.json文件全局打包命令webpack b.js -o bundle.js旧版本的是webpack b.js bundle.js2、npm install webpack --save-dev 引入本项目webpack&#xff0c;package.json文件中会生成对应的webpack版本号…

fpu测试_I510400性能及温度测试详解

5月20号&#xff0c;INTEL将正式销售十代民用桌面级处理器&#xff0c;此次上市的型号相对9代与8代来说要多了很多型号&#xff0c;仅I9系列就有4个型号&#xff0c;下图有此次INTEL更新所有型号的参数&#xff1a;从上图参数可知&#xff0c;Intel有史以来I3~I9全部支持超线程…

ADFLogger的SLF4J绑定–缺少的部分

由于最好的原因&#xff0c;在我的日常工作中&#xff0c;我希望为ADF Logger Oracle ADF提供一个SLF4J适配器。 毫不奇怪&#xff0c;slf4j没有用于ADFLogger的适配器&#xff0c;但是由于ADFLogger只是Java Util Logging的轻巧包装&#xff0c;因此花了一个多小时来填补这一空…

c语言int 转bool_C++代码实现逆波兰式_C 语言

100行以内C代码实现逆波兰式逆波兰式(Reverse Polish notation&#xff0c;RPN&#xff0c;或逆波兰记法)&#xff0c;也叫后缀表达式(将运算符写在操作数之后)。算术表达式转逆波兰式例子&#xff1a;逆波兰式整体的算法流程图如下&#xff1a;下面给出我基于C 语言对逆波兰式…

css的再深入9(更新中···)

一 单位 1.px 就是一个基本的单位 像素 2.em 也是一个单位 用父级元素的字体大小乘以em前面的数字。如果父级没有就继承上一个父级直到body&#xff0c;如果body没有那就默认是16px。 3.rem 也是一个单位&#xff0c;只跟根节点<html>的字体大小有关&#xff0c;如果没…

指令的存储与执行初探

前言导读&#xff1a;从零开始构造一台二进制加法器 假设一个处理器与存储器相连&#xff0c;存储器中存放着一些指令。这些指令通过处理器发出的寻址信号被加载到处理器中&#xff0c;这个过程称为取指令。 下面通过简单的加法运算&#xff0c;来看一下指令和数据是怎么存储在…

java 中的流_Java中的流(IO

Java中的流(IO流.java.io包中定义了多个流类型(类或抽象类)来实现 输入 / 输出功能&#xff0c;可以从不同的角度对其进行分类&#xff1a;按单位可分为&#xff1a; 字节流 (一个字节一个字节的读取) 字符流 (一个字符一个字符的读取『一个字符是两个字节』)按…

python基础学习_35岁零基础学习Python编程是否能学得会并用得上

首先&#xff0c;学习编程语言并没有年龄上的限制&#xff0c;在当前的工业互联网时代&#xff0c;不论是初级职场人还是资深职场人&#xff0c;学习一门编程语言都是有必要的&#xff0c;从这个角度来看&#xff0c;35岁开始学习编程语言是完全可以的。虽然说学习Python语言并…

css的再深入7(更新中···)

1.transparent 透明的 2.placeholder 提示语 写页面 搞清结构层次&#xff0c;保证模块化&#xff0c;让他们之间不能受到影响 (1) 元素性质 (2) 标准流 浮动带来的脱离文档流撑不起父级的高度的问题可以采用清除浮动的方式消除影响&#xff0c;absolute和fixed带来的脱…

窥探JBoss Fuse 6.1的新功能

我对即将发布的Fuse 6.1版本感到非常兴奋&#xff0c;因为有很多很棒的新功能是我真正想要的&#xff0c;而且已经有一段时间了。 HAWT工具。 因此&#xff0c;这是一个快速的先睹为快&#xff0c;主要关注于新版本的Fuse Management Console&#xff08;现已由hawtio开源项目…

[C语言] 选择排序之直接选择排序的特性及实现

[C语言] 选择排序之直接选择排序的特性及实现 1、算法特性 直接选择是一种简单、不稳定的选择排序方法&#xff0c;属于最为基础的排序方法之一。 其时间复杂度最好情况为O&#xff08;n&#xff09;、最差为O&#xff08;n&#xff09;、平均为O&#xff08;n&#xff09;&…

电脑测速软件_联通你我【宽带提速】让网速飞!超实用的宽带测速提速攻略来啦!...

宅在家里&#xff0c;在家娱乐、在家办公、在家上课&#xff0c;都需要畅快的宽带网络&#xff0c;所以很多小伙伴都办理了联通宽带怎样才是正确的宽带测速姿势&#xff1f;小沃给大家介绍两种简便的测速方法&#xff0c;同时说说怎样才能完全释放宽带网速、让咱享受到真正的提…

MyEclipse - 查询使用的JDK版本

查询 MyEclipse 使用的 JDK 版本 MyEclipse 菜单->Windows->Proferences->java->Installs Jres重新设置JDK路径&#xff0c;改为开发程序时的JDK版本&#xff08;如上图&#xff09;&#xff08;我做到这一步就可以了&#xff01;我的eclipse是7.0&#xff0c;jdk…

解析什么是绝对定位,相对定位与浮动

在理解定位之前&#xff0c;先说一个概念&#xff0c;文档普通流&#xff0c;就是元素标签正常在HTML里的顺序&#xff0c;块级元素从上至下排列&#xff0c;行内元素从左到右排列。 绝对定位 绝对定位&#xff1a;absolute&#xff0c;元素相对于离它最近的已定位祖先元素进…

具有多个查询参数的Camel CXF服务

出色的Apache Camel团队忙于解决查询中多个参数的处理问题&#xff0c;这是一种解决方法。 希望该帖子将在下一版本的Camel中变得过时。 &#xff08;当前&#xff0c;我使用2.7.5&#xff09; 问题 大于1的查询参数作为null值传递给Camel-CXF服务。 假设网址中有四个查询参数…

《JavaScript高级程序设计》读书笔记(三)基本概念第四小节 操作符

内容---语法 上一小节---数据类型 本小节 操作符---流程控制语句---理解函数 操作符--操作数据值的操作符--算术&#xff08;如加减&#xff09;、位操作符、关系、相等--ECMAScript操作符可以适用于很多类型的值--在用于对象时&#xff0c;会先调用对象的valueOf()和&#xff…

el-table数据不显示_数据透视表,一篇就够了

| 函数部分告一段落&#xff0c;这一篇文章助你学懂数据透视表目录&#xff1a;一、创建数据透视表二、数据透视表字段列表值的显示方式三、分析1、切片器2、计算字段3、计算项4、组合四、设计1、分类汇总2、报表布局首先&#xff0c;我们要知道应用数据透视表的前提&#xff1…

app vue 真机运行_使用 HBuilder 将 Vue 项目打包成手机 App

在开发移动端 app 时可以选择原生 app 和 webapp&#xff0c; 原生 app 体验好&#xff0c;开发成本高&#xff0c;相对的 webapp 体验要差&#xff0c;开发成本低。webapp 要求很低&#xff0c;可以说只要会开发web 站就能开发 webapp&#xff0c;这里不讨论怎么选择&#xff…

解决安卓字体偏移:页面整体缩放

在h5中实现一些小标签、按钮的时候&#xff0c;很容易发现部分安卓机型上的字体显示有问题&#xff0c;总会向上偏移2px左右。这是设置padding或line-height无法修复的&#xff0c;与rem也无关&#xff0c;即使在字体大于12px时依然存在。下图来自于网友的分享&#xff0c;从左…