Hibernate中实体ID存在但equals方法内显示为null问题求解
根本原因
你的问题是Hibernate懒加载代理对象的字段直接访问特性导致的:
WorkPosition类的defaultCode字段配置了fetch = FetchType.LAZY,所以从数据库查询得到的relatedWorkPosition.getDefaultCode()返回的是Hibernate生成的字节码代理对象,不是实际的EmployeeCodePOJO实例。- Hibernate的代理对象只会缓存主键值,所有普通字段默认都是未赋值的null状态,只有调用对应属性的getter方法时,才会触发代理初始化,从数据库加载完整字段值。
- 你在filter代码里直接调用
relatedWorkPosition.getDefaultCode().getId()时,Hibernate会直接返回代理中缓存的主键值,不需要初始化整个代理,所以能拿到正确的id。但你在EmployeeCode的equals方法中直接访问的是入参对象的id字段,而不是调用getId()getter,代理对象的id字段本身就是null,自然会判断失败。 - 你打印的实体状态也佐证了这一点:
relatedWorkPosition.getDefaultCode()是被EntityManager管理的代理对象,而savedWorkPosition.getEmployeeCodes()里的是游离态的普通POJO,字段都已赋值。
解决方案
修改EmployeeCode类的equals和hashCode方法,将直接字段访问改为调用getter方法即可:
@Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof EmployeeCode)) return false; EmployeeCode that = (EmployeeCode) o; // 用getId()而不是直接访问id字段 return getId() != null && getId().equals(that.getId()); } @Override public int hashCode() { // hashCode同步用getId(),保证和equals逻辑一致 return getClass().hashCode(); }
修改后你的原有filter代码即可正常运行,符合JPA实体equals的实现规范。
内容的提问来源于stack exchange,提问作者syydi
相关产品推荐
相关产品推荐

