JPA持久化后对象hashCode变更,HashMap为何仍能正确获取对应元素?
原因说明
你能成功取到元素的核心原因是:你调用get方法的Map并非JDK原生的普通HashMap,而是Hibernate提供的特殊持久化集合实现,二者的查询逻辑完全不同:
- 对于JPA实体中用注解声明的关联集合属性,Hibernate在加载实体时会用自定义的
PersistentMap实现类替换原生HashMap,用于支持懒加载、自动持久化同步等特性。 PersistentMap的get方法不会像普通HashMap一样,先计算传入key的哈希值再去对应哈希桶中匹配:它会直接提取你传入的f1实例的主键值,和Map内所有条目的key的主键做等值匹配,只要主键一致就返回对应结果,完全不受f1实例本身哈希值变化的影响。- 如果是你自己手动创建的普通HashMap,存入key之后修改了key的哈希值,确实会因为寻址到错误的哈希桶而找不到元素,但这个规则不适用于Hibernate的持久化集合。
补充说明
你修改后的equals和hashCode实现符合JPA实体的通用最佳实践:
- 主键未生成时使用
System.identityHashCode保证哈希值稳定 - 主键生成后固定使用主键计算哈希,避免业务字段变更导致哈希值波动
后续如果将实体存入你自己手动创建的普通HashMap/HashSet中,只要保证实体存入集合后不再修改主键(主键生成后通常也不会修改),就不会出现找不到元素的问题。
内容的提问来源于stack exchange,提问作者milanHrabos
相关产品推荐
相关产品推荐

