【问题标题】:How should I override equals/hashCode in entities with composite primary keys?我应该如何在具有复合主键的实体中覆盖 equals/hashCode?
【发布时间】:2020-06-19 08:54:24
【问题描述】:

我有一个包含复合主键的表,包括它自己的和来自其他表的 FK。

我决定不使用@IdClass@EmbeddedId

class SomeEntity {

    @Id
    private String someId;

    @Id
    @ManyToOne(optional = false)
    @JoinColumn(name = ...)
    private Other other

    // other mappings here
}

Hibernate 会警告这些。

WARN 69752 ... : HHH000038: Composite-id class does not override equals(): ....Some
WARN 69752 ... : HHH000039: Composite-id class does not override hashCode(): ....Some

我如何(应该)实现这两种方法?

我可以(应该)只包括这两个字段吗?其他领域呢?

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Some that = (Some) o;
        return Objects.equals(someId, that.someId) &&
                Objects.equals(other, that.other);
    }

    @Override
    public int hashCode() {
        return Objects.hash(someId, other);
    }

【问题讨论】:

标签: hibernate jpa equals hashcode composite-primary-key


【解决方案1】:

我决定不使用@IdClass@EmbeddedId

不得不说,这个决定有两个缺点:

  1. JPA 规范不允许这种方法,因此它是特定于休眠的解决方案。 (见this
  2. 实体实例和实际标识符之间没有分离。要查询此实体,必须将实体本身的实例提供给持久化上下文。 (见this

想象一下,你有以下实体:

@Entity
@Table(name = "TST_FIRST_ENTITY_EHC")
public class FirstEntity implements Serializable 
{
   @Id
   @Column(name = "fst_id")
   private Long id;
   
   @NaturalId
   @Column(name = "fst_code")
   private String code;
   
   @Id
   @ManyToOne(optional = false)
   @JoinColumn(name = "fst_sec_id")
   private SecondEntity secondEntity;
   
   public FirstEntity()
   {
   }
   
   public FirstEntity(Long id, Long secId)
   {
      this.id = id;
      secondEntity = new SecondEntity();
      secondEntity.setId(secId);
   }
   // ...
}

要通过 PK 找到这个实体,你应该这样写:

FirstEntity item = session.find(FirstEntity.class, new FirstEntity(1L, 2L));

对我来说,这看起来很尴尬。

至于您的主要问题,您可以使用任何一组标识您的实体的字段。 想象一下,对于上述实体,您有以下 DDL SQL:

create table TST_FIRST_ENTITY_EHC
(
   fst_id bigint,
   fst_sec_id bigint,
   fst_code varchar(25),
   fst_value varchar(500),
   
   primary key (fst_id, fst_sec_id),
   unique(fst_code),
   foreign key (fst_sec_id) REFERENCES TST_SECOND_ENTITY_EHC(sec_id)
);

您可以基于idsecondEntity.id 字段或基于code 字段实现实体的equalshashCode。基于 natural-id 或 business-key 的方法更可取,因为如果您使用数据库 id 生成,则在提交 JPA 事务之前您无法知道实际的 id 值。 (见this)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-23
    • 2011-07-11
    • 1970-01-01
    • 2011-07-08
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    • 1970-01-01
    相关资源
    最近更新 更多