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

Spring Boot 2.6.6升2.7.0后@DataJpaTest的findBy查询异常

问题根因

这不是业务代码逻辑错误,也不是Spring Data JPA的核心Bug,是Spring Boot 2.7.0升级时两个默认依赖的联动变更,只在@DataJpaTest切片测试场景触发:

  • Spring Boot 2.7.0将内嵌测试数据库H2从1.4.x大版本升级到2.x,H2 2.x对UUID类型的存储、等值比较逻辑做了不兼容变更
  • @DataJpaTest默认自动配置H2内存库作为测试数据源,不会加载生产环境使用的数据库(MySQL/PostgreSQL等)的配置,所以使用生产库的集成测试、手动测试都能正常运行
  • 你观察到的findAll()能返回正确实体、findBy*()衍生查询返回空的现象本质是缓存命中差异:findAll()执行全表查询后,Hibernate会将结果集和当前持久化上下文(一级缓存)中已persist的实体做匹配,直接返回缓存里的实体对象,所以你能看到正确的activationTokenId值;而findByActivationTokenId()生成的带WHERE条件的SQL是在H2数据库层面执行参数匹配,Hibernate自动生成的UUID列映射和H2 2.x的类型处理逻辑不兼容,导致条件匹配失败返回空结果。
修复方案

按优先级选择以下任意一种即可:

  • 方案1(推荐,侵入性最低):给实体类中所有UUID类型的字段显式声明JPA列映射类型,避免Hibernate自动生成的映射和H2 2.x不兼容,示例:
    // 列类型根据你生产使用的数据库调整,比如MySQL用BINARY(16),PostgreSQL直接用uuid
    @Column(columnDefinition = "BINARY(16)")
    var activationTokenId: UUID? = null
    
    改完后建议在persist、flush操作后加一句entityManager.clear()清空一级缓存再执行查询,确认查询真正走数据库执行,避免缓存掩盖问题。
  • 方案2(临时兼容):在测试依赖中强制将H2版本降级到1.4.200,和Spring Boot 2.6.x的默认依赖版本对齐,注意这只是临时方案,后续H2版本升级最终还是要做类型适配。
    Gradle配置示例:
    testImplementation("com.h2database:h2:1.4.200")
    
    Maven配置直接在test作用域的H2依赖中指定版本号为1.4.200即可。
  • 方案3(长期最稳妥):关闭@DataJpaTest默认使用H2内存库的自动配置,改用测试容器启动和生产环境同类型的数据库跑切片测试,从根源上消除测试数据库和生产数据库的类型、语法差异。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 21:21:39