jpa获取session_JPA 2 | 获取联接以及我们是否应该使用它们

jpa获取session

介绍

最近,我一直在与JPA 2中的FETCH JOINS一起使用,以期从数据库中急切地获取数据,并且我学到了很多关于为什么在日常操作中应避免使用Fetch Joins的知识。

今天的博客文章谈论了我在Fetch上的经历和学习(主要基于当我在查询中有很多FETCH JOINS时获得的评论)。

问题陈述

在我们的项目中,有一种情况是从定义了许多集合值关联的数据库(OneToMany,ManyToMany,也称为ToMany关联)中获取实体。 这是实体外观的概念图(为清楚起见,省略了getter和setter)。 这是实体的极其简化的示例。 在实际情况下,我们大约有11个关联。

public class ItemRecord {@Idprivate String itemId;@Column(name="author")private String author;@OneToMany(cascade = CascadeType.ALL, mappedBy = "item")private List costs;@OneToMany(cascade = CascadeType.ALL, mappedBy = "item")private List notes;@OneToMany(cascade = CascadeType.ALL, mappedBy = "item")private List stats;}

关于上述实体,有几件事需要注意:

  • 它具有3个收藏珍贵的协会。
  • 所有这些关联都被延迟获取,因为JPA中“集合有价值的关联”的默认获取策略是“惰性”。

在我们的业务实现中,我们有一个转换器,该转换器将DAO层返回的值转换为Business DTO。

因此,我们的业务方法的算法如下:

@TransactionAttribute
public List searchItemRecords (SearchCriteria sc) {List ir = itemRecordDao.search(sc);List convertedData = recordConverter.convert(ir);return convertedData;
}

请注意,整个方法都在Transaction内部运行。

每当我们从数据库中获取数据时,都不会急切地获取与成本,统计信息等相关的数据。 但是我们的ItemInformation DTO期望所有数据。 因此,当首次调用getCosts或getStatistics时,持久性提供程序(在本例中为Hibernate)向数据库激发查询以获取指定的数据。 这为我们创建了N + 1个选择查询问题。 如果您不熟悉N + 1选择或需要刷新,可以在DZone上查看此文章 。

我们大多数人,包括我在内,都会选择N + 1选择问题的最快,最简单的解决方案,即使用Fetch Join。 在Internet上发布的不同博客/文章中也有很多建议。

因此,我也采用了相同的方法。 就我而言,这至少是一种糟糕的方法。

首先让我们看看如何使用FETCH JOIN。

使用Fetch Join之前的查询如下:

SELECT item FROM ItemRecord item WHERE author=:author;

请注意,查询采用JPA形式。

该查询未获取集合值。 结果,在翻译器中,当我们对每个ItemRecord执行getCosts时,将触发类似于以下的查询:

SELECT cost FROM Cost where itemId = :itemId

因此,如果我们有3个ItemRecords,则激发到数据库的SELECT查询总数为:

  • 1用于获取所有ItemRecords
  • 3个用于获取每个ItemRecord的成本
  • 3用于获取每个ItemRecord的注释
  • 3个用于获取每个ItemRecord的统计信息

即(3乘3)+ 1

当将其转换为N乘以M +1时,

哪里,

  • N是找到的主要实体记录的数量
  • M是主要实体中Collection值关联的数量
  • 1个查询,用于获取所有主要实体

在实际情况下,我们有11个关联。 因此,对于每个主要ItemRecord实体,我们将触发11个SELECT查询。 激发的查询数量乘以找到的每个ItemRecord。

使得集合值关联成为EAGER是不可行的,因为在实体上运行的许多其他查询仅需要选定的数据。

这不是最佳解决方案。 必须做一些事情,很多互联网文章建议使用FETCH JOINS,因为它们最容易实现并解决了(N Time M +1)个查询问题。

因此,我决定在查询中使用FETCH Joins来针对给定场景急切地获取所有数据。

该查询类似于:

SELECT item FROM ItemRecordJOIN FETCH item.costs,
JOIN FETCH item.notes,
JOIN FETCHitem.stats;

跨栏1

我很快意识到该查询在我的情况下将无法使用,因为我可以拥有一个与之不相关的统计信息,而在这种情况下,上述查询不会向我返回那个ItemRecord(因为ORM的工作方式)因此我将获得不完整的数据。

因此,接下来我转到了LEFT JOIN FETCH,即使某些关联关系为空,它也将给我ItemRecord实体返回。 查询如下所示:

SELECT item FROM ItemRecordLEFT JOIN FETCH item.costs,
LEFT JOIN FETCH item.notes,
LEFT JOIN FETCH item.stats;

跨栏2

当我运行单元测试以测试上述查询时,出现了异常:

javax.persistence.PersistenceException: org.hibernate.HibernateException: cannot simultaneously fetch multiple bags

问题是什么?

问题是我在实体中使用列表作为集合类型。 使用列表会混淆JPA /Hibernate。 这篇文章很好地记录了这种困惑

为了解决此问题,我选择使用Set而不是List,主要是因为它是上述博客文章提供的三种解决方案中最简单的方法,并且也很有意义(至少在我实现时)。

因此,我将Entity更改为Set而不是List,并且修改后的实体如下所示:

public class ItemRecord {@Idprivate String itemId;@Column(name="author")private String author;@OneToMany(cascade = CascadeType.ALL, mappedBy = "item")private Set costs;@OneToMany(cascade = CascadeType.ALL, mappedBy = "item")private Set notes;@OneToMany(cascade = CascadeType.ALL, mappedBy = "item")private Set stats;}

我再次运行测试用例,并且测试查询的测试用例成功。 耶皮 但是,我的另一个测试用例正在测试注释部分中的条目失败。 看一下测试用例,我意识到我需要按照特定的顺序输入数据,并且我使用的是HashSet,但没有顺序。 解决方案很简单。 使用LinkedHashSet维护元素的顺序。

使用LinkedHashSet可以解决问题,并且我的测试用例通过了。

我很高兴,但我的幸福短暂。

跨栏3

我还有另一个测试用例,对于给定的ItemRecord来说,它需要3个成本对象。 我转到设置实现后,测试立即开始失败。 事实证明,我的哈希码不正确,并且我的“成本实体”的实现等于“实现”,“成本实体”为两个不同的实体返回相同的哈希码,结果,由于Set不允许重复值,因此仅持久保留了一个实体。

因此,我接下来要做的就是为我的所有实体使用适当的HashCode和Equals实现。

最终关卡

最终,当我所有的测试用例开始通过时,我进行了代码审查,并将其发送给团队。

第一个吓到我的是我的技术主管。 :)

他只是生气地看着FETCH JOINS。 原因? 原因是LEFT FETCH JOINs返回所有数据的笛卡尔积。 随着我们生产中的数据量的增加,甚至无法支持ItemRecord上的多个选择将成为一场噩梦。 整个问题可以在此博客文章中轻松理解


因此,我试图解决性能问题,事实证明我实际上是在制造更大的性能问题。 :)

删除了转移到FETCH JOIN的整个解决方案,因此决定进一步研究为什么我们需要UI上的全部数据,以及为什么不能将获取数据分成较小的专用事务。

摘要:

使用Fetch Joins的整个过程使我很好地了解了Joins的总体工作原理以及使用它们时的期望。

希望您喜欢这篇博客文章。 如果您想继续阅读有趣的帖子,可以关注我的博客。

参考: JPA 2 | 从JavaWorld Blog博客中获取Fetch Joins,以及是否应该从我们的JCG合作伙伴 Anuj Kumar 使用它们 。

翻译自: https://www.javacodegeeks.com/2013/07/jpa-2-fetch-joins-and-whether-we-should-use-them.html

jpa获取session

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

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

相关文章

CPU设计(单周期和流水线)

前些天发现了十分不错的人工智能学习网站,通俗易懂,风趣幽默,没有广告,分享给大家,大家可以自行看看。(点击跳转人工智能学习资料) 微信公众号:创享日记 发送关键词:cpu …

使用AWS Lambdas扩展技术堆栈

面对现实吧。 调试性能问题很困难,但更难解决。 假设您发现了令人反感的代码,这些代码正在拖慢您的应用的运行速度。 最终会有一段时间,您发现该代码减速是同步的或线性执行的。 解决这些有问题的代码段的最有效方法之一是将最重的工作负载委…

前馈-反馈控制系统设计(过程控制课程设计matlab/simulink)

前些天发现了十分不错的人工智能学习网站,通俗易懂,风趣幽默,没有广告,分享给大家,大家可以自行看看。(点击跳转人工智能学习资料) 微信公众号:创享日记 发送关键词:前馈…

感应电机直接转矩控制系统的设计与仿真(运动控制matlab/simulink)

前些天发现了十分不错的人工智能学习网站,通俗易懂,风趣幽默,没有广告,分享给大家,大家可以自行看看。(点击跳转人工智能学习资料) 微信公众号:创享日记 发送关键词:直接…

【2】C++语法与数据结构之MFC_CList学生管理系统_链表内排序_函数指针

MFC中CList类库的遍历 #include <iostream> #include "List.h" using namespace std; void main() {CList list;list.AddHead(33);list.AddHead(88);list.AddHead(99);POSITION pos list.GetHeadPosition();cout << "正向&#xff1a;" <…

neo4j cypher_neo4j / cypher:悬挂查询参数

neo4j cypher一直以来&#xff0c;我一直在使用neo4j的密码查询语言&#xff0c; 迈克尔一直在告诉我在查询中使用参数&#xff0c;但是查询的性能始终可以接受&#xff0c;因此我没有必要。 但是&#xff0c;最近我正在研究一个数据集&#xff0c;并使用类似于以下的代码创建了…

双容水箱液位模糊PID控制系统设计与仿真(Matlab/Simulink)

前些天发现了十分不错的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;没有广告&#xff0c;分享给大家&#xff0c;大家可以自行看看。&#xff08;点击跳转人工智能学习资料&#xff09; 微信公众号&#xff1a;创享日记 发送&#xff1a;双容模糊 获…

基于单片机步进电机控制器设计(正转反转指示灯挡位)

前些天发现了十分不错的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;没有广告&#xff0c;分享给大家&#xff0c;大家可以自行看看。&#xff08;点击跳转人工智能学习资料&#xff09; 微信公众号&#xff1a;创享日记 发送&#xff1a;单片机步进…

【3】C++语法与数据结构之MFC_CList学生管理系统_链表外排序_函数指针

注意&#xff1a;此时排序规则函数定义为全局函数 C中定义CStudent类 文件名&#xff1a;Student.h #pragma once #include <afxtempl.h> typedef struct SUser {int nNumb;char sName[20];float fMath; }DATA;typedef bool(*BY_FUNC)(DATA& q,DATA& m);class…

Java中Long到Int的精确转换

JDK 8附带所有令人眼前一亮的 东西 &#xff08; lambda表达式 &#xff0c; 流 &#xff0c; Optional &#xff0c;新的Date / Time API等&#xff09;来分散我的注意力 &#xff0c;我并没有过多注意添加方法Math.toIntExact&#xff08;&#xff09; 。 但是&#xff0c;这…

基于单片机的交通灯控制系统设计

前些天发现了十分不错的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;没有广告&#xff0c;分享给大家&#xff0c;大家可以自行看看。&#xff08;点击跳转人工智能学习资料&#xff09; 微信公众号&#xff1a;创享日记 发送&#xff1a;单片机交通…

【4】C++语法与数据结构之自己实现MFC的CList类库_学生管理系统

本文通过自己实现的CList双向链表数据结构来完成学生管理系统&#xff0c;同样采用链表外排序。 注意&#xff1a;此时排序规则函数仍然定义为全局函数 自己定义CList类 文件名&#xff1a;List.h -注意&#xff1a; POSITION不是VS默认的类型&#xff0c;而是重新定义为vo…

36个精美完整网站网页完整源码HTML+CSS+JS

以下列举前9个效果图&#xff0c;源码详见微信公众号下载 ①效果图 ②效果图 ③效果图 ④效果图 ⑤效果图 ⑥效果图 ⑦效果图 ⑧效果图 ⑨效果图 微信公众号&#xff1a;创享日记 发送&#xff1a;36 获取全部完整源码&#xff08;打开.html文件均即可用&…

【5】C++语法与数据结构之STL_list学生管理系统_链表内排序_函数指针

本文通过STL类库的list数据结构来完成学生管理系统&#xff0c;采用链表内排序&#xff0c;通过list类库自带sort函数进行排序。 注意&#xff1a;此时排序规则函数定义为类静态成员函数&#xff0c;等价于全局函数函数指针定义为 BY_FUNC ps[] { CStudent::byNumb,CStudent:…

ajax异步监控_监控整页(非AJAX),需要通知

ajax异步监控最近&#xff0c;在JSF中处理新图表和图表“导出服务”时&#xff0c;我遇到了一个非常普遍的问题。 当您执行长时间运行的任务&#xff08;操作&#xff09;时&#xff0c;您希望在开始时显示一个状态“请稍候……”对话框&#xff0c;并在响应到达时结束时关闭此…

公司产品移动端网页-前端网页设计技术精美网站源码HTML+CSS+JS

微信公众号&#xff1a;创享日记 发送&#xff1a;产品网页 获取完整源码&#xff08;打开即可用&#xff09; 效果①主页首页 /*页面重置*/ html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,f…

【6】C++语法与数据结构之STL_list学生管理系统_链表外排序_函数指针

本文通过STL类库的list数据结构来完成学生管理系统&#xff0c;采用链表外排序&#xff0c;通过函数指针实现。 注意&#xff1a;此时排序规则函数定义为类静态成员函数&#xff0c;等价于全局函数函数指针定义为 BY_FUNC ps[] { CStudent::byNumb,CStudent::byName,CStudent…

创建一个坚固的备份系统

在Foreach&#xff0c;我们拥有Synology RS815 来存储所有备份。 这些备份来自我们网络中的不同来源&#xff0c;例如路由器&#xff0c;交换机&#xff0c;数据库服务器&#xff0c;Web服务器&#xff0c;应用程序日志文件&#xff0c;邮件服务器等等。 Synology NAS使配置这…

班级网站-前端网页技术精美完整源码HTML+CSS+JS

微信公众号&#xff1a;创享日记 发送&#xff1a;班级网站 获取完整源码&#xff08;打开即可用&#xff09; 效果图①首页主页 效果图②关于页面 效果图③联系方式及留言 效果图④我们的画廊展示 其余及源码详见微信公众号下载&#xff01; <!DOCTYPE html> <html…

医药协会网站-前端网页技术设计HTML+CSS精美完整网页网站源码

微信公众号&#xff1a;创享日记 发送&#xff1a;医药协会网站 获取完整源码 效果图预览①主页首页 效果图预览②资源下载中心 效果图预览③登录/注册 效果图预览④文章资讯详情 效果图预览⑤文章资讯列表 效果图预览⑥留言板 效果图预览⑦图文列表 效果图预览⑧图文详情 源码…