非一致性访存系统_Hibernate事实:访存策略的重要性

非一致性访存系统

在使用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查询选择产品(绕过Persistence Context一级缓存)

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/346118.shtml

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

相关文章

应用新的JDK 11字符串方法

在“ 使用JDK 11的Java字符串上的新方法 ”和“ String&#xff03;repeat即将加入Java&#xff1f; ”&#xff0c;我讨论了JDK 11引入Java String的六个新方法。 可用的早期访问JDK 11构建已经包含了这些新方法&#xff0c;在这篇文章中&#xff0c;我将使用其中的一种早期访…

为什么需要切换到在线签署文档和合同

嘿&#xff0c;怪胎&#xff0c; 今天&#xff0c;我们为您带来一些不同。 无论您是开发人员&#xff0c;经理还是设计师&#xff0c;这都会提高您的生产力和效率。 对于公司和个人而言&#xff0c;良好地管理文书工作是强大基础的最重要部分之一。 将工作流程从纸质转移到数…

github怎么自动更新被人更新过的项目_GitHub 的这 8 个实用技巧,95%的人不知道...

知道的越多&#xff0c;不知道的就越多&#xff0c;业余的像一棵小草&#xff01;编辑&#xff1a;业余草来源&#xff1a;https://www.xttblog.com/?p49881、一秒钟把Github项目变成前端网站GitHub Pages大家可能都知道&#xff0c;常用的做法&#xff0c;是建立一个gh-pages…

java 注解 属性 类型_收藏!你一定要知道的Java8中的注解

全文共3002字&#xff0c;预计学习时长6分钟海中有大量的注解!JavaSE 1.5中首次引入了注解。Java注解的目的是允许程序员编写关于其程序的元数据。在OracleDocs中&#xff0c;注解的定义是:“注解是元数据的一种形式&#xff0c;它提供的数据与程序本身无关。”注解可以在代码的…

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

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

select * from where 三个条件_VBA学习笔记70: Select语句基础

学习资源:《Excel VBA从入门到进阶》第72集 by兰色幻想 这节课来详细讲解Select语句。 Select 字段 from 表 where 条件 例:从sheet1中筛选全部数据。 * 表示全部字符,无条件可以省略where。 Select * from [sheet1$] 如果是对表中特定单元格区域进行查找,可以在[sheet1$]的…

使用Servlet和Bootstrap上传Ajax文件

介绍 在本教程中&#xff0c;我们将检查Ajax文件上传如何与Servlet一起使用。 同样&#xff0c;我们将用Bootstrap装饰表单并通过jQuery Ajax上传ajaxify文件。 实作 基本的servlet实现是相同的。 因此&#xff0c;我们需要做的第一件事是更新我们的web.xml文件并为我们的应用…

linux文件系统dentry_Linux文件系统(四)---三大缓冲区之inode缓冲区 (内存inode映像 )...

在文件系统中&#xff0c;有三大缓冲为了提升效率&#xff1a;inode缓冲区、dentry缓冲区、块缓冲。(内核&#xff1a;2.4.37)一、inode缓冲区为了加快对索引节点的索引&#xff0c;引入inode缓冲区&#xff0c;下面我们看Linux/fs/inode.c代码。inode缓冲区代码1、一些数据结构…

使用这些先进的GC技术提高应用程序性能

应用程序性能是我们的首要考虑因素&#xff0c;垃圾收集优化是取得小而有意义的进步的好地方 自动化垃圾收集&#xff08;与JIT HotSpot编译器一起&#xff09;是JVM中最先进&#xff0c;最有价值的组件之一&#xff0c;但是许多开发人员和工程师对垃圾收集&#xff08;GC&a…

mysql中lead_SqlServer2012中LEAD函数简单分析_MySQL

LEAD函数简单点说&#xff0c;就是把下一行的某列数据提取到当前行来显示&#xff0c;看示例更能解释清楚&#xff0c;先看测试用脚本DECLARE TestData TABLE(ID INT IDENTITY(1,1),Department VARCHAR(20),LastName VARCHAR(20),Rate FLOAT)INSERT INTO TestData(Department,L…

堆栈溢出回答了我们不知道的Java首要问题

您不应该错过的堆栈溢出问题集合&#xff1a; 这不是秘密&#xff1b; 我们都使用堆栈溢出。 它掌握了生命&#xff0c;宇宙以及几乎所有与代码相关的内容的答案。 该平台为开发人员&#xff0c;工程师和其他人员提供了一个找到他们所面临问题的答案的地方&#xff0c;或者至少…

sequelize连接mysql_node.js通过Sequelize 连接MySQL

node.js通过Sequelize 连接MySQL一.通过koa2脚手架构建项目1.1 安装koa-generator在终端输入&#xff1a;$ npm install -g koa-generator11.2 使用koa-generator生成koa2项目$ koa2 HelloKoa21成功创建项目后&#xff0c;进入项目目录&#xff0c;并执行npm install命令$ cd H…

杀java_java怎么杀掉java进程

展开全部java中有调用外部程序的e69da5e887aa62616964757a686964616f31333337623431类&#xff0c;Runtime.getRuntime().exec("./**.exe");此函数返回的是一个Process 对象&#xff0c;该对象在创建后&#xff0c;可以对它进行 destroy () 杀掉子进程、 waitFor () …

高级java开发_我最喜欢的Java高级开发人员书籍

高级java开发我上一篇博客文章 &#xff08;我对高级Java开发人员的十个最喜欢的在线资源&#xff09;的想法&#xff0c;是由Xiaoran Wang发表的“面向高级Java开发人员的十大网站”的启发。 Wang还写了一篇名为“面向Java高级开发人员的十大书籍”的文章。 就像关于高级Java开…

camera.swf java_java调用摄像头保存图片上传功能

在项目中要用到jsp页面实现网页采集摄像头图像&#xff0c;并实现上传的功能&#xff0c;页面主要js调用的&#xff0c;所以可以使用多种语言php,asp等都可以使用&#xff0c;而且是跨浏览器的。可以整合的到SSH项目中和struts1或者struts2项目中使用方法1&#xff1a;下载 pri…

java 北理工 教材_北理工《Java技术与应用》在线作业

北理工《Java技术与应用》在线作业可以代做所有奥鹏平台的作业、小论文、毕业论文、离线作业、考核作业、在线作业、在线测试&#xff0c;有需要的请联系本人一、单选题(共 20 道试题&#xff0c;共 40 分。)V1. Socket对象中____函数获取远程端口。A. getPort( )B. getLocalPo…

Apache Spark Job的剖析

Apache Spark是通用的大规模数据处理框架。 了解spark如何执行作业对于获取大部分作业非常重要。 关于Spark评估范式的简短回顾&#xff1a;Spark使用的是惰性评估范式&#xff0c;在该范式中&#xff0c;Spark应用程序在驱动程序调用“ Action”之前不会执行任何操作。 惰性…

scala本地调试_如何编写自己的Java / Scala调试器

scala本地调试在本文中&#xff0c;我们将探讨Java / Scala调试器的编写和工作方式。 诸如Windows的WinDbg或Linux / Unix的gdb之类的本机调试器通过操作系统直接提供给它们的钩子来获取其功能&#xff0c;以监视和操纵外部进程的状态。 JVM充当OS之上的抽象层&#xff0c;它提…

java content()_Java contentEquals() 方法

全屏Java contentEquals() 方法contentEquals() 方法用于将将此字符串与指定的 StringBuffer 比较。语法public boolean contentEquals(StringBuffer sb)参数sb -- 要与字符串比较的 StringBuffer。返回值如字符串与指定 StringBuffer 表示相同的字符序列&#xff0c;则返回 tr…

通过这5个简单的技巧减少GC开销

编写代码的五种简单方法&#xff0c;可提高内存效率&#xff0c;而无需花费更多时间或降低代码可读性 垃圾回收会为您的应用程序增加多少开销&#xff1f; 您可能不知道确切的数字&#xff0c;但您确实知道总有改进的余地。 尽管自动GC是最有效的过程&#xff0c;但是如果它过…