Spring Boot中JPA原生Query更新后LocalDateTime查询无结果问题
问题解决:Spring Boot JPA操作MS SQL时Update后Select查不到数据
核心原因:时间精度不匹配
MS SQL的时间类型(如datetime/datetime2)和Java LocalDateTime的精度存在差异:
datetime类型精度仅到3.33毫秒,存入时会自动截断Java端的纳秒级时间;datetime2精度到100纳秒,但LocalDateTime.now()生成的是纳秒级时间,存入时仍会有微小截断。
你用原始的纳秒级LocalDateTime参数查询,自然匹配不到数据库中已被截断的时间值。
解决方案
方案1:用数据库端生成时间(最可靠)
直接在Update语句中使用MS SQL的时间函数,避免客户端和数据库的精度差异:
// 修改Update方法,不用传参数,直接用数据库时间 @Modifying @Transactional @Query(value = "UPDATE xy SET ts = SYSDATETIME()", nativeQuery = true) void update(); // 如果需要获取这个数据库生成的时间,可以改成返回值 @Modifying @Transactional @Query(value = "UPDATE xy SET ts = SYSDATETIME(); SELECT SYSDATETIME();", nativeQuery = true) LocalDateTime updateAndGetTimestamp();
调用示例:
LocalDateTime dbTimestamp = repository.updateAndGetTimestamp(); List<List<String>> list = repository.select(dbTimestamp);
方案2:统一Java端时间精度
手动截断LocalDateTime到和数据库字段匹配的精度:
- 若数据库用
datetime(毫秒级):
LocalDateTime now = LocalDateTime.now().truncatedTo(ChronoUnit.MILLIS); repository.update(now); List<List<String>> list = repository.select(now);
- 若数据库用
datetime2(百纳秒级):
LocalDateTime now = LocalDateTime.now(); // 截断到100纳秒精度,匹配datetime2 now = now.withNano((now.getNano() / 100_000) * 100_000); repository.update(now); List<List<String>> list = repository.select(now);
方案3:检查事务有效性
如果Update和Select是同一类内部调用,Spring的AOP代理可能不会触发@Transactional注解,导致Update的修改未提交到数据库。解决方式:
- 将Update和Select方法拆分到不同类;
- 在调用这两个方法的外层Service方法上添加
@Transactional:
@Service public class XyService { @Autowired private XyRepository repo; @Transactional public List<List<String>> updateAndQuery() { LocalDateTime now = LocalDateTime.now().truncatedTo(ChronoUnit.MILLIS); repo.update(now); return repo.select(now); } }
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

