You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JPA实体equals()/hashCode()的又一种实现方案及探讨

JPA自增主键实体的equals()与hashCode()实现方案

JPA实体的equals()与hashCode()方法一直是开发者热议的话题,搜索相关关键词能找到不少优质内容,包括Vlad Mihalcea的深度分析文章、JPA Buddy团队对现有方案不足的探讨,以及Stack Overflow上的大量讨论帖。本文聚焦无业务键可用、只能依赖自动生成序列主键的场景。

我一直有两个疑问:一是Hibernate为何没有给出官方的实现指导;二是Lombok至今没推出类似@EqualsAndHashCodeOfSyntheticId的注解——毕竟现在多数文章都指出,给实体使用常规的@EqualsAndHashCode是糟糕的做法,实际情况也确实如此。

结合Vlad与JPA Buddy的方案,我整理出另一种实现方案供大家参考:

public abstract class AbstractSyntheticIdEntity {
    public abstract Long getId();

    @Override
    public final boolean equals(Object o) {
        if (this == o) return true;
        if (o == null) return false;

        if (effectiveClass(this) != effectiveClass(o)) return false;
        AbstractSyntheticIdEntity that = (AbstractSyntheticIdEntity) o;
        return getId() != null && getId().equals(that.getId());
    }

    @Override
    public final int hashCode() {
        return effectiveClass(this).hashCode();
    }

    @Override
    public String toString() {
        return String.format(
                "%s(id=%d)",
                effectiveClass(this).getSimpleName(),
                getId()
        );
    }

    private static Class<?> effectiveClass(Object obj) {
        return obj instanceof HibernateProxy
                ? ((HibernateProxy) obj).getHibernateLazyInitializer().getPersistentClass()
                : obj.getClass();
    }
}

缺点:

  • 依赖Hibernate(不过提到JPA时通常默认使用Hibernate,影响不大)
  • 采用继承方式实现
  • 默认假设ID为Long类型,若混用Long和Integer可以轻松通过参数化适配

优点:

  • 无需在每个实体中重复编写equals()和hashCode(),只需继承该抽象类即可
  • 通过了Vlad的IdEqualityTest测试,覆盖了不同实体状态、代理对象、引用对比、集合存储等多种场景
  • 提供了基础的toString实现(非必需,实体可自行重写,注意避免触发隐式的额外数据加载)

欢迎大家给出宝贵反馈。

补充:如果上述方案的缺点对你造成了阻碍,推荐使用Vlad的方案,为每个实体添加以下代码片段:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof CLASS_NAME)) return false;
    CLASS_NAME that = (CLASS_NAME) o;
    return id != null && id.equals(that.getId());
}

@Override
public int hashCode() {
    return getClass().hashCode();
}

内容的提问来源于stack exchange,提问作者Andriy Slobodyanyk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 13:05:13