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
相关产品推荐
相关产品推荐

