hash和hashcode_Hibernate事实:等于和HashCode

hash和hashcode

每个Java对象都继承了equals和hashCode方法,但它们仅对Value对象有用,对面向无状态行为的对象没有用。

尽管使用“ ==”运算符比较引用很简单,但是对于对象相等而言,事情要复杂一些。

由于您负责告诉平等性对于特定对象类型的含义,因此必须使equals和hashCode实现遵循java.lang.Object JavaDoc( equals()和hashCode() )指定的所有规则。

了解您的应用程序(及其使用的框架)如何利用这两种方法也很重要。

幸运的是,Hibernate不需要它们检查实体是否已更改,为此具有专用的脏检查机制。

浏览Hiberante文档后,我偶然发现了这两个链接: Equals和HashCode和Hiberante 4.3文档指出了需要两种方法的上下文:

  • 将实体添加到Set集合时
  • 将实体重新附加到新的持久性上下文时

这些要求源于Object.equals的“ consistent ”约束,使我们遵循以下原则:

在所有JPA对象状态下,实体必须等于其自身

  • 短暂的
  • 附上
  • 超脱
  • 移除(只要该对象被标记为要移除并且它仍然驻留在堆上)

因此,我们可以得出以下结论:

  1. 我们不能使用自动递增的数据库ID来比较对象,因为瞬态和附加的对象版本不会彼此相等。
  2. 我们不能依赖默认的Object equals / hashCode实现,因为在两个不同的持久性上下文中加载的两个实体最终将成为两个不同的Java对象,因此违反了全状态相等性规则。
  3. 因此,如果Hibernate使用相等性唯一地标识对象,则在整个生命周期中,我们都需要找到满足此要求的属性的正确组合。

具有在整个实体对象空间中唯一的属性的那些实体字段通常称为业务密钥。

与合成数据库自动递增的ID相对,业务密钥还独立于我们的项目体系结构中采用的任何持久性技术。

因此,必须从我们创建实体的那一刻起就设置业务密钥,然后再也不要更改它。

让我们以实体相关性为例,并选择适当的业务密钥。

  • 根实体用例(没有任何父依赖项的实体)

这是实现equals / hashCode的方式:

@Entity
public class Company {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Long id;@Column(unique = true, updatable = false)private String name;@Overridepublic int hashCode() {HashCodeBuilder hcb = new HashCodeBuilder();hcb.append(name);return hcb.toHashCode();}@Overridepublic boolean equals(Object obj) {if (this == obj) {return true;}if (!(obj instanceof Company)) {return false;}Company that = (Company) obj;EqualsBuilder eb = new EqualsBuilder();eb.append(name, that.name);return eb.isEquals();}
}

名称字段代表公司业务密钥,因此被声明为唯一且不可更新。 因此,如果两个Company对象具有相同的名称,则它们相等,而忽略了它可能包含的任何其他字段。

  • 拥有EAGER的父级的子实体
@Entity
public class Product {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Long id;@Column(updatable = false)private String code;@ManyToOne(fetch = FetchType.EAGER)@JoinColumn(name = "company_id", nullable = false, updatable = false)private Company company;@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "product", orphanRemoval = true)@OrderBy("index")private Set images = new LinkedHashSet();@Overridepublic int hashCode() {HashCodeBuilder hcb = new HashCodeBuilder();hcb.append(name);hcb.append(company);return hcb.toHashCode();}@Overridepublic boolean equals(Object obj) {if (this == obj) {return true;}if (!(obj instanceof Product)) {return false;}Product that = (Product) obj;EqualsBuilder eb = new EqualsBuilder();eb.append(name, that.name);eb.append(company, that.company);return eb.isEquals();}
}

在此示例中,我们始终为产品获取公司,并且由于产品代码在公司之间并非唯一,因此我们可以在业务密钥中包含父实体。 父引用被标记为不可更新,以防止违反equals / hashCode合同(将产品从一家公司转移到另一家公司毫无意义)。 但是,如果“父级”具有“一组子级”实体,则此模型将中断,并且您调用类似以下内容的方法:

public void removeChild(Child child) {children.remove(child);child.setParent(null);
}

由于将父级设置为null,因此这将破坏equals / hashCode合同,并且如果子级对象是Set,则不会在子级集合中找到子对象。 因此,在使用具有此类的equals / hashCode的Child实体的双向关联时要小心。

  • 拥有LAZY父级的子实体
@Entity
public class Image {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Long id;@Column(updatable = false)private String name;@ManyToOne(fetch = FetchType.LAZY)@JoinColumn(name = "product_id", nullable = false, updatable = false)private Product product;@Overridepublic int hashCode() {HashCodeBuilder hcb = new HashCodeBuilder();hcb.append(name);hcb.append(product);return hcb.toHashCode();}@Overridepublic boolean equals(Object obj) {if (this == obj) {return true;}if (!(obj instanceof Image)) {return false;}Image that = (Image) obj;EqualsBuilder eb = new EqualsBuilder();eb.append(name, that.name);eb.append(product, that.product);return eb.isEquals();}
}

如果在没有产品的情况下获取图像并且关闭了持久性上下文,并且将图像加载到集合中,则将得到LazyInitializationException,如以下代码示例所示:

List images = transactionTemplate.execute(new TransactionCallback<List>() {@Overridepublic List doInTransaction(TransactionStatus transactionStatus) {return entityManager.createQuery("select i from Image i ", Image.class).getResultList();}
});
try {assertTrue(new HashSet(images).contains(frontImage));fail("Should have thrown LazyInitializationException!");
} catch (LazyInitializationException expected) {}

因此,我不建议使用该用例,因为它容易出错,并且要正确使用equals和hashCode,我们始终需要始终初始化LAZY关联。

  • 子实体不理父母

在此用例中,我们只需从业务密钥中删除父级引用即可。 只要我们始终通过“父级子代”集合使用“子代”,我们就很安全。 如果我们从多个父级加载子级,并且业务键在这些父级中不唯一,则不应将其添加到Set集合中,因为Set可能会丢弃来自不同父级的具有相同业务键的Child对象。

结论

为实体选择正确的业务密钥并不是一件容易的事,因为它反映了您在Hibernate范围内外的实体使用情况。 使用实体之间唯一的字段组合可能是实现equals和hashCode方法的最佳选择。

使用EqualsBuilder和HashCodeBuilder可以帮助我们编写简洁的equals和hashCode实现,并且似乎也可以与Hibernate Proxies一起使用。

参考: Hibernate Fact:来自我们JCG合作伙伴 Vlad Mihalcea的Equals和HashCode ,位于Vlad Mihalcea的Blog博客中。

翻译自: https://www.javacodegeeks.com/2013/11/hibernate-facts-equals-and-hashcode.html

hash和hashcode

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

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

相关文章

4代hiv检测50元_别瞧不起国货!这4个姥姥辈的护肤品,真心好用,还不到50元

在护肤这件事情上&#xff0c;其实最适合我们肤质的护肤品还是我们自己国家的生产的&#xff0c;但是国货这几年的确没有欧美的一些大牌&#xff0c;或者是日韩的护肤品更受到欢迎&#xff0c;国货被淹没的一个主要原&#xff0c;就是因为它的价格太过便宜了&#xff0c;可能老…

了解自定义De / Serializer:JSON绑定概述系列

自定义JSON绑定的最高级方法是使用自定义序列化程序和反序列化程序。 JSON-B序列化器和反序列化器是可用的最低级别的自定义&#xff0c;并且可以访问JSON处理解析器和生成器。 定制的序列化程序必须实现JsonbSerializer接口&#xff0c;并为serialise&#xff08;&#xff0…

墙面有几种装修方法_新房装修除甲醛 用这几种方法就足够

新房装修后会散发出刺鼻的有害物质&#xff0c;其中甲醛是含量最高&#xff0c;危害最大的有害气体。那怎么才能有效的去除甲醛呢?下面小编就为大家带来新房装修除甲醛的四大方法&#xff0c;希望能给大家带来帮助。新房装修除甲醛方法一&#xff1a;开窗通风法将新房的窗户打…

Parallel Parking of Truck-Trailer Using Multistage Nonlinear MPC之MATLAB simulink编译转换C++代码(内附下载地址)

引言 这个例子展示了如何使用多级非线性模型预测控制(NLMPC)来并行停放卡车-挂车系统。 在本例的应用场景中,卡车-拖车系统(EGO车辆)在停车场行驶。当停车点被定位时,非线性预测控制规划器生成停车路径。然后,自行车使用另一个非线性MPC控制器,沿着规划的路径到达目标姿态…

lambda 加和_流畅和稳定的API的Lambda

lambda 加和几周前&#xff0c;我写了关于Java 8 lambda的介绍 。 在本简介中&#xff0c;我解释了什么是lambda以及如何将它们与Java 8中也引入的新Stream API结合使用。 Stream API为集合提供了更实用的接口。 此接口在很大程度上取决于lambda。 但是&#xff0c;lambda不仅…

攻防世界 适合做桌面_空间“狭小”的二人世界,适合情侣们做浪漫的事情

在最浪漫的11月与它邂逅&#xff0c;有着深秋的枫红、累累的苹果红、还有童话绘本中的苹果屋红&#xff0c;充满着热情活力的色彩&#xff0c;让人感到雀跃。眼瞧见银河的感动。那晚入住于福寿山农场的露营区&#xff0c;位在深山中的它空气轻透又鲜少光害&#xff0c;是观赏星…

使用混合多云每个人都应避免的3个陷阱(第1部分)

每天都在肆意宣传云&#xff0c;但每个人都应避免三个陷阱。 从云&#xff0c;混合云到混合多云&#xff0c;您被告知这是确保业务数字化未来的一种方式。 您必须做出的这些选择不会排除提高客户体验和敏捷交付这些应用程序的日常工作。 让我们开始一段旅程&#xff0c;仔细研…

jquery开关灯案例_全屋开关插座布局讲解,自己规划怕遗漏,手把手教你,很详细...

开关插座是装修内重要的一环&#xff0c;然而也最容易被忽视。装修完住进来后才发现插口不够用&#xff0c;插座被家具挡住&#xff0c;想改还得砸墙&#xff0c;没办法只能用拖线板。然而&#xff0c;满屋都是拖线板&#xff0c;乱糟糟的&#xff0c;看着就惹人烦&#xff0c;…

富贵不压重发_为什么老人常说“贵人不顶重发”,“重发”是什么意思? ?...

"先&#xff0c;""贵人""在我国一般是指有身份有地位有财富的人&#xff0c;而""重发""顾名思义是指头发多的人&#xff0c;那么&#xff0c;老人们为什么会说""贵人不顶重发""呢?有书君认为&#xff0c;可…

java六大原则_六大Java功能

java六大原则我花了无数小时来对不同的应用程序进行故障排除。 通过经验&#xff0c;我可以得出关于大多数开发人员应该远离的几个Java SE功能/ API的结论。 当我提到大多数开发人员时&#xff0c;我会想到常规的Java EE开发人员&#xff0c;而不是库设计人员/基础结构工程师。…

打开虚拟机磁盘类型无效_[图文]VMWARE虚拟机如何打开.VMDK格式的磁盘映像

最近在折腾安卓虚拟机时使用Android x86项目组提供的镜像&#xff0c;架构问题本身无法直接在电脑安装安卓系统。而Android x86项目则是国外团队通过源代码进行移植的版本&#xff0c;虽然不能同步更新但现在也倒是已经 8.1 版。至于折腾安卓虚拟机的原因则是手头的安卓机还是4…

Apache Ivy 2.5.0-rc1发布–现在允许解析器超时

几周前&#xff0c;我们发布了Apache Ivy的2.5.0-rc1版本。 Apache Ivy是一个依赖项管理构建工具&#xff0c;通常与Apache Ant结合使用。 可在项目下载页面上下载 自Apache Ivy的上一版本于2014年12月发布以来&#xff0c;此版本具有重要意义。距上一个正式年份已超过3年。 在…

感量越大抑制频率约低_脉冲信号是什么?它与频率,占空比,正、负逻辑间是什么关系?...

在数字电子系统中&#xff0c;所有传送的信号均为开关量&#xff0c;即只有两种状态的电信号&#xff0c;这种电信号&#xff0c;我们称作做脉冲信号&#xff0c;这是所有数字电路中的基本电信号一个标准的脉冲信号如下图所示。我们把脉冲信号由低电压跳变至高电压的脉冲信号边…

datagrid 小数点_EasyUI 解决 datagrid 中 NumberBox 限制小数位数后不能输入小数点问题...

初始化界面&#xff0c;发现编辑datagrid&#xff0c;不能输入小数点。var arrColumnsCNT [[{title: 毛重,field: GrossWeight,halign: center,width: 60,sortable: true,frozen: true,editor: {type: numberbox,options:{precision:2}}}]];function DefDataGridCNT() {objDat…

【OFDM系列9】OFDM采用正交区分不同子载波的,但是子载波通过调相后携带了基带信号后,如何还能继续保证两者正交

不经意间在知乎看到这样一个问题&#xff0c;在此记录一下我的看法 OFDM采用正交区分不同子载波的&#xff0c;但是子载波通过调相后携带了基带信号后&#xff0c;如何还能继续保证两者正交&#xff1f; 补充内容是&#xff1a;OFDM是指通过2组正交载波传递信息&#xff0c;但…

使用threadlocal_何时以及如何使用ThreadLocal

使用threadlocal正如我们的读者可能已经猜到的那样&#xff0c;我每天都会处理内存泄漏。 最近&#xff0c;一种特殊类型的OutOfMemoryError消息开始引起我的注意-滥用ThreadLocals引发的问题变得越来越频繁。 在查看此类泄漏的原因时&#xff0c;我开始相信其中一半以上是由于…

企业为什么要开通银企直联_企业为什么要做网站推广

随着现代社会的发展&#xff0c;如果企业不做网站推广&#xff0c;那么可以说是寸步难行&#xff0c;今天就来为大家说说企业为什么一 定要做网站推广的详情&#xff01;1 、网络品牌推广做网络营销的结果就是在互联网要有自己的品牌&#xff0c;并且可以再网络上得到无限性的延…

在Java错误产生之前对其进行处理的新方法

我们如何认识到解决预生产错误的旧方法还不够&#xff0c;以及我们如何能够改变这种情况 第一次尝试时就没有完美的代码&#xff0c;我们所有人都可以证明我们已经学到了很难的方法。 不管我们使用多少测试周期&#xff0c;代码审查或工具&#xff0c;总有至少一个偷偷摸摸的错…

学术诚信的重要性_申论作文开头之诚信

本段是经典开头或过渡段落写作&#xff0c;通过反面论证引出总论点重要性&#xff0c;结构清晰&#xff0c;层次感强&#xff0c;本段可以适用于公民道德与诚信建设问题、食品安全问题、环境污染等等&#xff0c;其中影响及重要性分析语句可以用于申论作文的开头部分&#xff0…

curl 访问不到html_嵌入式工程师入门前后端系列1:访问一个网页

做为嵌入式行业的从业者&#xff0c;最近经常听到PAAS&#xff0c;SAAS等和”云”相关的概念&#xff0c;被整的一头雾水。很多时候咱们的物联网硬件设备都会有一个云平台&#xff0c;用于设备管理或者UI应用展示等功能&#xff0c;这通常是由专门的前后端工程师配合美工一起完…