是否应该在equals/hashCode/toString中使用@Transient属性? [英] Should @Transient property be used in equals/hashCode/toString?
问题描述
我有JPA实体,其中某些属性用@Transient
注释.
I have JPA entities where some properties are annotated with @Transient
.
我应该在equals/hashCode/toString
方法中使用这些属性吗?
Should I use these properties in equals/hashCode/toString
methods?
我的第一个想法是否,但我不知道为什么.
My first thought is NO but I don't know why.
- 提示?
- 想法?
- 说明?
推荐答案
toString()
的情况有所不同,您可以使用toString()
做任何您想做的事,所以我只介绍equals()
(和hashCode()
) .
The case of toString()
is different, you can do whatever you want with toString()
so I will only cover equals()
(and hashCode()
).
首先,规则:如果要将对象存储在List
,Map
或Set
中,则要求实现equals
和hashCode
,因此他们遵守文档中指定的标准合同.
First, the rule: if you want to store an object in a List
, Map
or a Set
then it is a requirement that equals
and hashCode
are implemented so they obey the standard contract as specified in the documentation.
现在,如何实现equals()
和hashCode()
? 自然"的想法是将映射为Id
的属性用作equals()
的一部分:
Now, how to implement equals()
and hashCode()
? A "natural" idea would be to use the properties mapped as Id
as part of the equals()
:
public class User {
...
public boolean equals(Object other) {
if (this==other) return true;
if (id==null) return false;
if ( !(other instanceof User) ) return false;
final User that = (User) other;
return this.id.equals( that.getId() );
}
public int hashCode() {
return id==null ? System.identityHashCode(this) : id.hashCode();
}
}
不幸的是,该解决方案存在一个主要问题:使用生成的标识符时,直到实体变为持久时才分配值,因此,如果 transient em>实体在保存前已添加到Set
中,其哈希码在Set
中时会发生变化,这会破坏Set
的协定.
Unfortunately, this solution has a major problem: when using generated identifiers, the values are not assigned until an entity becomes persistent so if a transient entity is added to a Set
before being saved, its hash code will change while it's in the Set
and this breaks the contract of the Set
.
因此,推荐的方法是使用属于业务密钥的属性,即,对于具有相同数据库身份的每个实例,唯一的属性组合.例如,对于User类,它可以是用户名:
The recommended approach is thus to use the attributes that are part of the business key i.e. a combination of attributes that is unique for each instance with the same database identity. For example, for the User class, this could be the username:
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参考文档总结如下:
The Hibernate Reference Documentation summarizes this as follow:
"请不要使用数据库标识符来实现相等性;请使用业务密钥,它是唯一的(通常是不可变的)属性的组合.如果使临时对象持久化,则数据库标识符将更改.临时实例(通常与分离的实例一起)保存在
Set
中,更改hashcode
会破坏Set
的协定.业务键的属性不必像数据库主键那样稳定.只要对象在同一个集合中就必须保证稳定性." - 12.1.3.考虑对象身份
"Never use the database identifier to implement equality; use a business key, a combination of unique, usually immutable, attributes. The database identifier will change if a transient object is made persistent. If the transient instance (usually together with detached instances) is held in a
Set
, changing thehashcode
breaks the contract of theSet
. Attributes for business keys don't have to be as stable as database primary keys, you only have to guarantee stability as long as the objects are in the same Set." - 12.1.3. Considering object identity
"建议您使用业务键等同性实现equals()
和hashCode()
.业务键等同性意味着equals()
方法仅比较构成业务键的属性.是可以在现实世界中标识我们实例的键(自然的候选键)"-
"It is recommended that you implement equals()
and hashCode()
using Business key equality. Business key equality means that the equals()
method compares only the properties that form the business key. It is a key that would identify our instance in the real world (a natural candidate key)" - 4.3. Implementing equals() and hashCode()
所以,回到最初的问题:
So, back to the initial question:
- 请尽可能使用公司密钥.
@Transient
属性很可能不是此类键的一部分. - 如果不可能,请使用标识符属性,但请确保获取分配给实体
List
,Map
,Set
的实体之前的值.
- Use a business key if possible.
@Transient
attributes are very likely not part of such a key. - If not possible, use identifier properties but make sure to get the values assigned before to add an entity to a
List
,Map
,Set
.
- 等于和HashCode
- Don不要让冬眠窃取您的身份
- Hibernate中的等于和哈希码
- 使用Hibernate在Java持久性中理解equals()和hashCode()(第396页)
- Equals and HashCode
- Don't Let Hibernate Steal Your Identity
- equals and hashcode in Hibernate
- Understanding equals() and hashCode() (p. 396) in Java Persistence with Hibernate
这篇关于是否应该在equals/hashCode/toString中使用@Transient属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!