定义Spring Boot JPA复合主键类时为什么需要实现equals和hashCode方法?
问题背景
你定义的是JPA规范下的复合主键类,用于映射数据库联合主键,代码如下:
public class CustomerOrderPK implements Serializable { @Column(name = "customer_id") private Long customerId; @Column(name = "order_id") private Long orderId; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; CustomerOrderPK that = (CustomerOrderPK) o; return Objects.equals(customerId, that.customerId) && Objects.equals(orderId, that.orderId); } @Override public int hashCode() { return Objects.hash(customerId, orderId); } }
调用主体
这两个方法的调用方是JPA实现框架,Spring Boot默认集成的Hibernate就是最常用的JPA实现,业务代码一般不会主动调用这两个方法。
两个方法的作用
equals方法作用
用来判断两个复合主键对象是否对应数据库中的同一条数据,而非判断是否为Java内存中的同一个对象实例。
常见触发场景:
- 调用
findById()等查询方法时,将传入的主键和持久化上下文缓存中的主键做相等比对,命中缓存就可以跳过数据库查询 - 执行实体合并(merge)、状态校验操作时,确认两个主键是否指向同一条数据
- 主键对象存入Set这类去重集合时,判断是否存在重复元素
hashCode方法作用
为复合主键生成稳定的、和业务字段绑定的哈希值,适配哈希结构的存储和查询逻辑。
常见触发场景:
- 主键作为HashMap的key、或者存入HashSet时,先通过哈希值快速定位分组,再用equals做精准比对,大幅提升查找效率
- 持久化上下文一级缓存、二级缓存的key计算需要用到哈希值,保证业务含义相同的主键可以命中同一个缓存项
注意事项
必须用所有主键字段共同计算equals和hashCode,如果漏字段会出现相同主键被判定为不同、不同主键被误判为相同的问题,直接导致缓存失效、数据重复插入、集合去重错误等异常。
内容的提问来源于stack exchange,提问作者kelsanity
相关产品推荐
相关产品推荐

