是否应该在equals/hashCode/toString中使用@Transient属性? [英] Should @Transient property be used in equals/hashCode/toString?

查看:131
本文介绍了是否应该在equals/hashCode/toString中使用@Transient属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有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()).

首先,规则:如果要将对象存储在ListMapSet 中,则要求实现equalshashCode ,因此他们遵守文档中指定的标准合同.

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 the hashcode breaks the contract of the Set. 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属性很可能不是此类键的一部分.
  • 如果不可能,请使用标识符属性,但请确保获取分配给实体ListMapSet的实体之前的值.
  • 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.
  • 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆