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

Spring Boot查询方法重复调用无法获取数据库最新数据问题咨询

问题原因与解决方案

核心原因

  • JPA一级缓存(EntityManager缓存)拦截了数据库查询:Spring Data JPA底层的EntityManager会在当前事务上下文内缓存已查询到的实体。首次调用getByRegNumber时,MessageLog实体被存入一级缓存,后续同事务内的查询直接返回缓存中的旧数据,不会触发新的数据库查询——这就是你用外部工具修改数据库后,查询结果依然不变的原因。

可行解决方案

1. 手动清除EntityManager缓存

在需要获取最新数据的查询前,调用EntityManager的clear()方法清空缓存,强制后续查询去数据库拉取最新数据:

@Autowired
private EntityManager entityManager;

// 清除缓存后再查询
entityManager.clear();
MessageLogDto byRegNumber2 = messageLogReadService.getByRegNumber(regNumber);

2. 刷新指定实体

如果能定位到要更新的实体,查询后调用refresh()方法强制从数据库加载最新状态:

public MessageLogDto getByRegNumber(String regNumber) {
    MessageLog entity = messagesLogRepository.findFirstByRegNumberAndTypeDoc(regNumber, BCM_01.ZVT.getName())
            .orElse(new MessageLog());
    entityManager.refresh(entity); // 从数据库刷新实体数据
    return mapper.toDto(entity);
}

3. 开启独立事务

给getByRegNumber方法设置事务传播属性为REQUIRES_NEW,每次调用都会启动新事务,事务结束后一级缓存自动失效:

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Transactional(propagation = Propagation.REQUIRES_NEW)
public MessageLogDto getByRegNumber(String regNumber) {
    MessageLog entity = messagesLogRepository.findFirstByRegNumberAndTypeDoc(regNumber, BCM_01.ZVT.getName())
            .orElse(new MessageLog());
    return mapper.toDto(entity);
}

4. 查询时禁用一级缓存

在Repository的查询方法上添加@QueryHints注解,直接禁用该查询的缓存:

import org.hibernate.annotations.QueryHints;
import javax.persistence.QueryHint;
import java.util.Optional;

public interface MessagesLogRepository extends JpaRepository<MessageLog, Long> {
    @QueryHints(value = { @QueryHint(name = QueryHints.CACHEABLE, value = "false") })
    Optional<MessageLog> findFirstByRegNumberAndTypeDoc(String regNumber, String typeDoc);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 07:45:19