java - 应该在 equals/hashCode/toString 中使用 @Transient 属性吗?

标签 java orm jpa transient

我有 JPA 实体,其中一些属性用 @Transient 注释。

我应该在 equals/hashCode/toString 方法中使用这些属性吗?

我的第一个想法是,但我不知道为什么。

  • 提示?
  • 想法?
  • 解释?

最佳答案

toString() 的情况不同,你可以用 toString() 做任何你想做的事所以我只介绍 equals()(和 hashCode())。

首先,规则:如果您想将对象存储在ListMapSet 那么需要实现equalshashCode,以便它们遵守文档中指定的标准契约

现在,如何实现equals()hashCode()?一个“自然”的想法是使用映射为 Id 的属性作为 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 的契约>.

因此,推荐的方法是使用作为业务键一部分的属性,即对于具有相同数据库身份的每个实例而言唯一的属性组合。例如,对于 User 类,这可能是用户名:

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 引用文档总结如下:

"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

"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()

那么,回到最初的问题:

  • 如果可能,请使用企业 key 。 @Transient 属性很可能不是此类 key 的一部分。
  • 如果不可能,请使用标识符属性,但要确保获取之前分配的值,以便将实体添加到 ListMapSet.

另见

关于java - 应该在 equals/hashCode/toString 中使用 @Transient 属性吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2951454/

相关文章:

java - 使用 Java 内置库的简单 RSA 加密

java - 如何调整 GridLayout 中 JComponent 的大小?

.net - .NET ORM 数据访问方法的优点 Entity Framework vs. NHibernate vs. Subsonic vs. ADO.NET Datasets

java - JPA @MapsId 插入不正确的列名

java - 当有人单击硬件按钮菜单设置时如何创建新 Activity

java - 重载的构造函数

java - myBatis 中如何映射一对多关系?

java - @OneToOne 与 Hibernate 共享主键用户 - 帐户的映射

java - JPA删除不执行

javax.persistence 不包含在 spring 数据 jpa 中?