JPA实体类equals与hashCode实现最佳实践及自动化测试方案
JPA实体类equals与hashCode的最佳实现及自动化验证
一、JPA实体实现equals/hashCode的核心要求
JPA实体的equals和hashCode得保证持久化前后状态一致,毕竟实体可能有未存库(ID为null)和已存库(ID非null)两种状态,还得避开Hibernate懒加载代理带来的类型判断坑。
二、你给出的实现完全可行,而且是最佳实践之一
咱们拆解下为什么这个写法没问题:
- equals方法:
- 先判断是不是同一个对象引用,能快速返回结果,省性能
- 用
Hibernate.getClass()代替普通的getClass()或者instanceof,能解决Hibernate懒加载代理类和实体类类型不匹配的问题(代理类是实体的子类,直接用getClass会判断为不相等) - 只靠
id字段做判断,还先检查当前对象的id不为null,避免未存库的实体因为id为null出现错误的相等判断
- hashCode方法:
- 返回固定的类哈希值,不管实体是新建状态还是已持久化状态,hashCode都不变,这样放进HashSet、HashMap这类集合里就不会出现实体丢失或者重复的问题
三、手动实现后的自动化测试方案
手动写equals/hashCode确实得全覆盖测试,EqualsVerifier就是专门干这个的工具,它能自动校验equals和hashCode是否符合Java约定:
- 自动验证对称性、自反性、传递性这些equals的核心规则
- 能检测出新增字段没加到equals里这类问题
- 还支持处理JPA实体的特殊场景,比如代理类、未持久化状态
给个JUnit 5的使用例子:
import org.junit.jupiter.api.Test; import nl.jqno.equalsverifier.EqualsVerifier; public class UserTest { @Test public void verifyEqualsAndHashCodeContract() { EqualsVerifier.forClass(User.class) .suppress(nl.jqno.equalsverifier.Warning.NULL_FIELDS) // 允许id之外的字段为null .verify(); } }
内容的提问来源于stack exchange,提问作者ColdDeath
相关产品推荐
相关产品推荐

