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

使用@Cacheable与JPA二级缓存时出现EntityNotFoundException异常咨询

问题根因

该异常本质是Hibernate二级缓存中集合缓存与关联实体缓存不一致导致的:
当你直接删除Reservation实体时,Hibernate只会清空Reservation自身的实体缓存,不会主动更新所有关联到它的Desk实体的reservations集合缓存。后续你加载对应Desk时,Hibernate会先读取集合缓存中存储的Reservation ID列表,再拿着这些ID去查询实体缓存或数据库,此时已删除的ID对应的实体不存在,就会抛出EntityNotFoundException。

解决方案

根据你的业务场景可以选择以下任意一种方案:

  • 方案1:维护关联关系双向同步,删除关联实体时主动更新集合
    删除Reservation时先获取关联的Desk,将待删除的Reservation从Desk的reservations集合中移除,Hibernate会自动触发集合缓存更新,保证一致性,代码示例:
@Transactional
public void deleteReservation(Long reservationId) {
    Reservation reservation = reservationRepository.findById(reservationId)
            .orElseThrow(() -> new RuntimeException("Reservation not found"));
    // 主动更新关联集合,触发缓存同步
    Desk desk = reservation.getDesk();
    desk.getReservations().remove(reservation);
    reservationRepository.delete(reservation);
}
  • 方案2:删除关联实体后手动清除对应集合缓存
    如果你不想修改业务逻辑的关联关系维护流程,可以在删除Reservation后主动清除对应Desk的集合缓存,代码示例:
@PersistenceContext
private EntityManager entityManager;

@Transactional
public void deleteReservation(Long reservationId) {
    Reservation reservation = reservationRepository.findById(reservationId)
            .orElseThrow(() -> new RuntimeException("Reservation not found"));
    Long deskId = reservation.getDesk().getId();
    reservationRepository.delete(reservation);
    // 手动清除指定Desk的reservations集合缓存
    entityManager.getEntityManagerFactory().getCache()
            .evictCollection(Desk.class.getName() + ".reservations", deskId);
}
  • 方案3:调整集合缓存的并发策略
    如果你的业务允许短时间的数据不一致、并发修改频率低,可以将集合的缓存策略改为@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE),该策略不会抛出找不到实体的异常,会自动回源查询数据库同步缓存。
  • 方案4:关闭关联集合的二级缓存
    如果关联实体删除操作非常频繁、对一致性要求极高,可以直接去掉集合上的@Cache注解,牺牲少量读性能避免缓存一致性问题。
调试方法

你可以通过以下步骤定位缓存不一致的具体环节:

  • 开启Hibernate缓存日志和统计功能,确认缓存的命中、失效情况,Spring Boot配置示例如下:
spring:
  jpa:
    properties:
      hibernate:
        show_sql: true
        format_sql: true
        use_sql_comments: true
        generate_statistics: true
        cache:
          use_second_level_cache: true
        log:
          logger:
            org.hibernate.cache: TRACE
            org.hibernate.stat: DEBUG
  • 复现问题时观察日志输出,确认删除Reservation后,加载Desk时是否读取到了已删除的Reservation ID。
  • 测试手动清除集合缓存后异常是否消失,验证问题是否确实由缓存不一致导致。

内容的提问来源于stack exchange,提问作者Jose A. Matarán

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 01:24:04