Java 在equals/hashCode/toString中是否应使用@Transient属性?
我有JPA实体,其中一些属性用Java 在equals/hashCode/toString中是否应使用@Transient属性?,java,orm,jpa,transient,Java,Orm,Jpa,Transient,我有JPA实体,其中一些属性用@Transient注释 我应该在equals/hashCode/toString方法中使用这些属性吗 我的第一个想法是不,但我不知道为什么 小费 想法 解释 据我所知,@Transient和Transient的两种典型用法是将它们用于无法序列化/持久化的内容(例如远程资源句柄)或可以从其他内容重建的计算属性 对于计算数据,在相等关系(equals/hashCode)中使用它们是没有意义的,因为这是多余的。该值是从等式中已使用的其他值中计算出来的。但是,在toSt
@Transient
注释
我应该在equals/hashCode/toString
方法中使用这些属性吗
我的第一个想法是不,但我不知道为什么
- 小费
- 想法
- 解释
@Transient
和Transient
的两种典型用法是将它们用于无法序列化/持久化的内容(例如远程资源句柄)或可以从其他内容重建的计算属性
对于计算数据,在相等关系(equals/hashCode
)中使用它们是没有意义的,因为这是多余的。该值是从等式中已使用的其他值中计算出来的。但是,在toString
中打印它们仍然是有意义的(例如,基本价格和比率用于计算实际价格)
对于不可序列化/可扩展的数据,这取决于。我可以想象一个不可序列化的资源句柄,但是您仍然可以比较句柄所表示的资源名称。对于toString
,可能打印句柄资源名称很有用
这是我的2美分,但是如果你解释一下你对@Transient
的特殊用法,也许有人能给你一个更好的建议。toString()的情况不同,你可以用toString()
做任何你想做的事,所以我只讨论equals()
(和hashCode()
)
首先,规则是:如果要将对象存储在列表
、映射
或集合
中,则需要实现等于
和哈希代码
,以便它们遵守文档中指定的标准约定
现在,如何实现equals()
和hashCode()
?“自然”的想法是使用映射为Id
的属性作为equals()
的一部分:
不幸的是,此解决方案存在一个主要问题:当使用生成的标识符时,在实体变得持久之前,不会分配值,因此如果在保存前将临时实体添加到集合
,当它在集合
中时,它的哈希代码将发生变化,这将打破集合
的契约
因此,建议的方法是使用作为业务密钥一部分的属性,即具有相同数据库标识的每个实例的唯一属性组合。例如,对于用户类,这可能是用户名:
public class User {
...
public boolean equals(Object other) {
if (this==other) return true;
if ( !(other instanceof User) ) return false;
final User that = (User) other;
return this.username.equals( that.getUsername() );
}
public int hashCode() {
return username.hashCode();
}
}
Hibernate参考文档将其总结如下:
“切勿使用数据库标识符来实现相等;请使用业务密钥,即唯一的、通常不可变的属性组合。如果临时对象成为持久对象,则数据库标识符将更改。如果临时实例(通常与分离的实例一起)在集合
中保存,更改哈希代码
会破坏集合
的契约。业务键的属性不必像数据库主键那样稳定,只要对象在同一集合中,您就只需保证稳定性。“-
“建议您使用业务密钥相等来实现equals()
和hashCode()
。业务密钥相等意味着equals()
方法只比较构成业务密钥的属性。它是一个在现实世界中标识实例的密钥(自然候选密钥)”-
那么,回到最初的问题:
- 如果可能,请使用业务密钥
属性很可能不是此类密钥的一部分@Transient
- 如果不可能,请使用标识符属性,但确保在将实体添加到
,列表
,映射
之前获得分配的值集
- 使用Hibernate理解Java持久化中的equals()和hashCode()(第396页)
瞬态
,同时提供writeObject()
和readObject()
处理它的位置
public class User {
...
public boolean equals(Object other) {
if (this==other) return true;
if ( !(other instanceof User) ) return false;
final User that = (User) other;
return this.username.equals( that.getUsername() );
}
public int hashCode() {
return username.hashCode();
}
}