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

使用@MappedSuperclass后查询Moviment触发EntityNotFoundException问题

问题分析与解决方案

看起来你遇到的问题大概率和@Version注解的意外引入有关,另外hashCode方法的变化也可能埋下隐患,我来帮你拆解分析:

1. 最可能的根源:@Version注解的意外引入

对比修改前后的代码能发现关键差异:

  • 原Espai类中的version只是普通字段,没有@Version注解
  • 抽取到BaseEntity后,version被添加了@Version注解,成为JPA的乐观锁版本字段

JPA对@Version字段有严格要求:

  • 字段值不能为null(数据库对应列不能存在null值)
  • 每次实体更新时,JPA会自动递增该字段值

如果你的a_espai表中原本存在version为null的记录,当JPA加载这些记录时,会因为@Version字段不符合规范,导致实体无法正确实例化,进而触发EntityNotFoundException(关联的Moviment自然找不到有效的Espai实体)。

解决方法:

  • 如果你不需要乐观锁功能,直接移除BaseEntity中version字段的@Version注解,保持和原代码逻辑一致:
@MappedSuperclass
public class BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    protected Integer version; // 去掉@Version注解
    public Integer getId() {
        return id;
    }
}
  • 如果确实需要乐观锁,先将数据库中a_espai表的version列所有null值更新为默认值(比如1),确保所有记录都有有效的版本号。

2. hashCode方法的潜在问题

原Espai类中,当servei为null时hashCode返回1;修改后返回0。虽然这不会直接触发EntityNotFoundException,但可能影响JPA一级缓存的实体识别:

  • 多个servei为null的Espai实体hashCode相同(都是0),会被放到缓存的同一个哈希桶中
  • 虽然equals方法会通过id区分不同实体,但可能导致缓存查找效率下降,极端情况引发实体匹配混乱

优化建议:

hashCode方法应该基于稳定且唯一的属性,优先用实体的id(主键唯一且不可变),避免依赖关联实体的属性(比如servei.getId())——关联实体可能是懒加载代理,调用其方法可能触发额外查询,甚至引发LazyInitializationException。

修改后的hashCode方法示例:

@Override
public int hashCode() {
    return getId() != null ? getId().hashCode() : super.hashCode();
}

3. equals方法的兼容性优化

当前的equals方法逻辑是正确的,但要注意JPA代理实体的情况:如果Espai被懒加载代理(比如其他关联中使用懒加载),obj instanceof Espai依然会返回true(代理类是Espai的子类),所以当前逻辑没问题。不过可以进一步优化,确保代理对象也能正确比较:

@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    // 处理Hibernate代理对象,获取真实实体类
    Class<?> objClass = obj.getClass();
    if (objClass.getName().contains("HibernateProxy")) {
        objClass = org.hibernate.Hibernate.getClass(obj);
    }
    if (!Espai.class.equals(objClass)) return false;
    Espai other = (Espai) obj;
    return getId() != null && getId().equals(other.getId());
}

(注:如果使用其他JPA实现,需要对应调整代理类的处理方式)

总结

优先检查@Version注解的问题,这是最可能导致EntityNotFoundException的原因。调整后再验证hashCode和equals方法的优化,确保实体的标识逻辑稳定可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:44:38