Hibernate事实:有利于双向集vs列表

Hibernate是一个很棒的ORM工具,它极大地简化了开发,但是如果您想正确地使用它,则有很多陷阱。

在大中型项目中,双向父子关联非常常见,这使我们能够浏览给定关系的两端。

在控制关联的持久/合并部分时,有两个可用选项。 其中将有负责同步收集变化的@OneToMany结束,但是这是一个低效率的做法,这是很好的描述在这里 。

最常见的方法是@ManyToOne端控制关联并且@OneToMany端使用“ mappedBy”选项时。

我将讨论后一种方法,因为就执行的查询数量而言,这是最常见,最有效的方法。

因此,对于双向集合,我们可以使用java.util.List或java.util.Set。

根据Hibernate docs的说法,列表和文件包比集合更有效。

但是当我看到以下代码时,我仍然感到焦虑:

@Entity
public class Parent {...@OneToMany(cascade = CascadeType.ALL, mappedBy = "parent", orphanRemoval = true)
private List children = new ArrayList()public List getChildren() {
return children;
}public void addChild(Child child) {
children.add(child);
child.setParent(this);
}public void removeChild(Child child) {
children.remove(child);
child.setParent(null);
}
}@Entity
public class Child {...@ManyToOne
private Parent parent;public Parent getParent() {
return parent;
}public void setParent(Parent parent) {
this.parent = parent;
}
}Parent parent = loadParent(parentId);
Child child1 = new Child();
child1.setName("child1");
Child child2 = new Child();
child2.setName("child2");
parent.addChild(child1);
parent.addChild(child2);
entityManager.merge(parent);

这是因为在最近五年中,当在父关联上调用合并操作时,我一直在插入重复的子代。 发生这种情况是由于以下问题: HHH-3332和HHH-5855 。

我最近一直在测试一些Hibernate版本,并且仍然在3.5.6、3.6.10和4.2.6版本上进行复制。 因此,经过5年在许多项目上看到这一点后,您了解了为什么我对使用列表与集合持怀疑态度。

这是在运行复制此问题的测试用例时得到的结果,因此添加两个子级,我们得到:

select parent0_.id as id1_2_0_ from Parent parent0_ where parent0_.id=?
insert into Child (id, name, parent_id) values (default, ?, ?)
insert into Child (id, name, parent_id) values (default, ?, ?)
insert into Child (id, name, parent_id) values (default, ?, ?)
insert into Child (id, name, parent_id) values (default, ?, ?)

仅当合并操作从父级到子级联时,才会出现此问题,并且存在以下变通办法:

  • 合并孩子而不是父母
  • 在合并父母之前先让孩子坚持
  • 从父级删除Cascade.ALL或Cascade.MERGE,因为它只影响合并操作,而不影响持久化操作。

但是所有这些都是黑客,在大型项目中很难遵循,因为许多开发人员都在相同的代码库上工作。

因此,我的首选方式是使用Set,即使有时它们的效率不如Lists更好,但是由于我一直偏爱正确性与性能优化,因此最好使用Set。

当涉及到这类问题时,最好具有代码约定,因为它们易于添加到项目开发指南中,并且易于记忆和采用。

使用集合的一个优点是,它迫使您定义适当的equals / hashCode策略(该策略应始终包括实体的业务密钥。业务密钥是一种字段组合,该字段组合在父级的子级中是唯一的或唯一的,并且甚至在之前也是一致的)以及将实体持久保存到数据库中之后)。

如果您担心会失去以添加孩子的相同顺序保存孩子的“列表”功能,那么您仍然可以为Sets模仿。

默认情况下,集合是无序的和未排序的,但是即使您不能对它们进行排序,也可以通过使用@OrderBy JPA注释按给定的列对它们进行排序,如下所示:

@Entity
public class LinkedParent {...@OneToMany(cascade = CascadeType.ALL, mappedBy = "parent", orphanRemoval = true)
@OrderBy("id")
private Set children = new LinkedHashSet();...public Set getChildren() {
return children;
}public void addChild(LinkedChild child) {
children.add(child);
child.setParent(this);
}public void removeChild(LinkedChild child) {
children.remove(child);
child.setParent(null);
}
}

加载父级的子级时,生成SQL类似于:

select children0_.parent_id as parent_i3_3_1_, children0_.id as id1_2_1_, children0_.id as id1_2_0_, children0_.name as name2_2_0_, children0_.parent_id as parent_i3_2_0_ from LinkedChild children0_ where children0_.parent_id=? order by children0_.id

结论:

如果您的领域模型要求使用列表而不是集合,则将打破您的约束,不允许重复。 但是,如果您需要重复项,则仍然可以使用索引列表。 据说Bag是未排序且“无序的”(即使它按照在数据库表中添加子的顺序来检索子)。 因此,索引列表也将是一个不错的选择,对吗?

我还想提请注意一个5年的bug,它影响了多个Hibernate版本,并且是我在多个项目中复制的一个版本。 当然,有一些解决方法,例如删除Cascade.Merge或合并Children vs the Parent,但是有许多开发人员不知道此问题及其解决方法。

根据Hibernate docs:集是“ 表示多值关联的推荐方法 ”,而且我已经看到很多情况下使用Bags作为默认双向集合,即使无论如何集都是更好的选择。

因此,我仍然对Bags保持谨慎,如果我的领域模型强加使用List,我总是会选择索引的。

  • 代码可在GitHub上获得 。

参考: Hibernate Facts:来自Vlad Mihalcea博客博客的JCG合作伙伴 Vlad Mihalcea偏爱双向集合与列表 。

翻译自: https://www.javacodegeeks.com/2013/10/hibernate-facts-favoring-bidirectional-sets-vs-lists.html

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

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

相关文章

创建二级索引_Mysql创建索引

零:文章概要这篇文章,主要是和大家一起去了解 索引,然后一起使用CREATE INDEX语法给数据库中的表创建一个索引。一:先拿电话薄做个类比假如,一个电话薄里面包含了一个城市的所有人的姓名和电话号码。那么,想找到Bob Ca…

转hdmi_苹果本轻松接大屏,毕亚兹雷电接口转HDMI/VGA转换器评测

作为上班族,日常开会加出差,经常需要用到笔记本连接投影仪投屏。很多小伙伴为了高效办公,使用的都是性能强劲但是设计轻薄的笔记本产品,最常见的就是苹果笔记本。但是比较尴尬的是,目前可以使用的绝大部分苹果笔记本电…

计算机专业教学工作小结,计算机专业教学的工作总结

本人在教育教学上,爱岗敬业,严谨治教,热爱学生,努力做到把学生教好,让学生成功成才,优秀教师应有的职责。因此我在教育教学方面注意了以下几个问题,现作工作总结如下:一、思想方面本…

使用Java流查询数据库

在本文中,您将学习如何编写纯Java应用程序,这些应用程序能够处理现有数据库中的数据,而无需编写单行SQL(或类似的语言,例如HQL),也无需花费数小时将所有内容放在一起。 准备好应用程序之后&…

2017计算机信息技术,2017年一级计算机信息技术及应用考试试题级答案[权威资料]...

2017年一级计算机信息技术及应用考试试题级答案 本文档格式为WORD,感谢你的阅读。最新最全的 学术论文 期刊文献 年终总结 年终报告 工作总结 个人总结 述职报告 实习报告 单位总结 演讲稿2017年一级计算机信息技术及应用考试试题级答案一、基础知识题(共45分,每题1…

sigquit信号默认忽略吗_linux下的信号列表

我们运行如下命令,可看到Linux支持的信号列表:$ kill -l1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR213) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD18) SIGC…

恐鬼症不显示服务器区域,恐鬼症 steam版【简体中文】【4.34GB】

游戏介绍《恐鬼症(Phasmophobia)》是一款玩法十分精彩的冒险解谜类游戏,这款游戏支持4人联机对战,共同寻找隐藏的秘密,游戏的过程比较惊悚,需要玩家拥有强大的心里承受能力,气氛和渲染都十分的优质,游戏由K…

进程比线程更多资源_为什么我们不应该使用比我们需要更多的线程

进程比线程更多资源总览 有一个普遍的论点,因为我们有很多核心,并且将来还会有更多核心,所以我们必须使用它们。 我们只是需要找到使用它们的最佳方法,而仅仅是因为我们不能意味着我们应该这样做。 我们的目标是什么?…

ajax默认什么方法,ajax设置默认值ajaxSetup()方法

$(function(){//设置全局 jQuery Ajax全局参数$.ajaxSetup({type:"POST",async:false,cache:false,dataType:"JSON",error:function(jqXHR,textStatus,errorThrown){switch(jqXHR.status){case(500):alert(服务器系统内部错误);break;case(401):alert(未登…

Java谓词的延迟执行

在先前的文章“ 用Java的供应商延迟执行 ”和“ Java的消费者延迟执行 “,我看着很容易地通过推迟标准Java API接受,分别在Java执行供应商 S和消费者秒。 在本文中,我将对标准JDK提供的API如何通过标准功能接口Predicate允许延迟执行进行类似…

android实现评论列表_【Android视图效果】分组列表实现吸顶效果

效果图效果图分析先来分析一下,可以看到这是一个按月份分组的2行图片列表,列表顶部一个悬浮栏,会随着列表滑动而刷新,点击顶部栏,弹出了一个筛选框。思路1.列表部分可以用RecyclerViewGridLayoutManager,月…

用ajax写无限循环,ajax无限循环

// 猜你喜欢的无限加载(function(){var content document.getElementsByClassName("content")[0];var footer document.getElementsByTagName("footer")[0];var winh window.innerHeight - footer.offsetHeight;var ul document.getElementById("…

JDK 11:发行候选更新和OpenJDK JDK 11 LTS

JDK 11是预定被释放的一般可用性上周二,9月25日2018年2018年8月16日马克莱因霍尔德消息上OpenJDK的JDK-dev邮件列表宣布“ JDK 11现在在候选发布版阶段 。” 但是,Reinhold在2018年8月17日同一封邮件列表中的消息中提供了更新的详细信息,他在…

lr监控虚拟服务器,lr监控服务器 教程

lr监控服务器 教程 内容精选换一换本教程旨在演示使用GDS(General Data Service)工具将远端服务器上的数据导入GaussDB(DWS)中的办法,帮助您学习如何通过GDS进行数据导入的方法。在本教程中,您将:生成本教程需要使用的CSV格式的数据源文件。将…

mysql-5.5密码是多少_关于mysql-5.5数据库密码的设置和重置

一、mysql-5.5数据库的密码长什么样?直接打开给你看:[rootlnmp1 ~]# mysql -uroot -p#在已知密码的情况想打开数据库Enter password:Welcome to the MariaDB monitor. Commands end with ; or \g.Your MariaDB connection id is 4Server version: 5.5.64…

华为OD机试真题-停车场车辆统计-2023年OD统一考试(C卷)

题目描述: 特定大小的停车场,数组cars[]表示,其中1表示有车,0表示没车。车辆大小不一,小车占一个车位(长度1),货车占两个车位(长度2),卡车占三个车位(长度3),统计停车场最少可以停多少辆车,返回具体的数目。 输入描述: 整型字符串数组cars[],其中1表示有车,0…

vc mysql 图片_VC连接MySQL

一、MySQL的安装可以考虑安装mysql-5.0.41-win32(可到http://www.newhua.com/soft/3573.htm处下载),当然你有更新的版本更好,注意选择“完全安装”(只有这样才会安装VC编译时需要的头文件等)。安装后期会进行服务器配置,你可以设置你的服务器…

魔兽巨龙追猎者服务器微信群,魔兽世界:难怪现在“龙脊”价格低,掉落率提升,群里一天出几个...

祥子哥最近几天一直在练猎人号,目前已经67级了,再过两三天差不多就能满级了。知道祥子哥为什么练猎人吗?不全是因为猎人伤害高玩着爽,还有另一个原因,那就是“龙脊奖章”现在价格很便宜,祥子哥使把劲应该能…

mysql group原理_MySQL Group By 实现原理分析

【IT168 专稿】由于 GROUP BY 实际上也同样会进行排序操作,而且与 ORDER BY 相比,GROUP BY 主要只是多了排序之后的分组操作。当然,如果在分组的时候还使用了其他的一些聚合函数,那么还需要一些聚合函数的计算。所以,在…

使用AWS Lambda的CloudWatch事件通知

CloudWatchEvents的主要用例是跟踪整个AWS基础架构中的更改。 当前,它支持在Auto Scaling组,EC2,EBS和其他各种事件中发出的事件。 为了对这些事件进行有意义的处理,我们需要一种消耗它们的方法。 AWS使用术语“ targets来指代任何…