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

Hibernate Evict方法无法逐出一级缓存对象问题求助

Hibernate一级缓存逐出问题的解决方案

你的代码核心问题

  1. evict操作时机错误:你先查询出对象并拿到内存实例,再调用session.evict(pList.get(0))——这只是从Hibernate的一级缓存中移除该对象的引用,但你返回的依然是已经加载到内存的旧对象实例。
  2. 未强制查询从数据库拉取数据:即使逐出了缓存对象,若Session未关闭,第二次查询Hibernate仍会优先检查缓存,不会主动去数据库取最新数据。

修正后的实现方案

方案1:先逐出缓存再查询

先移除缓存中的目标对象,再执行查询,确保从数据库获取最新数据:

Person clearCache() {
    // 先获取缓存中的对象(如果存在)并逐出
    Person cachedPerson = session.createQuery("select p from Person p", Person.class).uniqueResult();
    if (cachedPerson != null) {
        session.evict(cachedPerson);
    }
    // 重新查询,此时会从数据库加载最新数据
    return session.createQuery("select p from Person p", Person.class).uniqueResult();
}

方案2:用refresh同步数据库最新状态

如果需要保留Session中的对象引用,但要同步数据库的最新修改,直接用refresh方法:

Person clearCache() {
    Person person = session.createQuery("select p from Person p", Person.class).uniqueResult();
    // 强制从数据库刷新对象的所有字段
    session.refresh(person);
    return person;
}

方案3:清空整个Session缓存

如果不需要保留Session中其他缓存的对象,可以直接清空整个一级缓存:

Person clearCache() {
    // 清空当前Session的所有缓存对象
    session.clear();
    return session.createQuery("select p from Person p", Person.class).uniqueResult();
}

方案4:查询时忽略缓存

在查询时设置CacheMode.IGNORE,强制Hibernate跳过缓存直接查询数据库:

Person clearCache() {
    List<Person> pList = session.createQuery("select p from Person p", Person.class)
        .setCacheMode(CacheMode.IGNORE)
        .getResultList();
    return pList.get(0);
}

关键知识点

  • Hibernate一级缓存是Session级别的缓存,只要Session未关闭,缓存的对象就会驻留。evict()移除单个对象,clear()清空整个Session缓存。
  • 默认查询会优先从一级缓存取对象,要强制获取最新数据,必须主动触发缓存逐出、对象刷新,或者让查询忽略缓存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 21:17:50