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

Spring Boot+Gradle+H2测试报错:主键/唯一索引冲突求助

主键冲突问题排查与解决

以下是针对你遇到的主键冲突问题的具体排查方向和解决办法:

1. 避免data.sql重复执行

@DataJpaTest注解默认会自动加载并执行src/test/resources下的schema.sql和data.sql脚本,而你又通过@Sql注解显式引入了data.sql,这会导致脚本被执行两次,直接触发主键重复插入的错误。

  • 解决方式:
    • 移除测试类上的@Sql注解,依赖@DataJpaTest的自动初始化逻辑;
    • 或者在测试配置文件(如application-test.properties)中禁用自动数据初始化:
      spring.sql.init.mode=never
      
      保留@Sql注解来手动控制脚本执行时机。

2. 对齐主键生成策略与插入数据

如果你的Product实体类中ID_PRODUCT字段使用了自增主键策略(比如@GeneratedValue(strategy = GenerationType.IDENTITY)),H2数据库的自增序列可能已经有初始值,和你data.sql中手动插入的ID值冲突。

  • 解决方式:
    • 在data.sql末尾添加重置序列的语句,确保自增起始值大于你插入的最大ID:
      ALTER SEQUENCE product_id_product_seq RESTART WITH 3;
      
    • 或者修改data.sql中的插入ID,避开自增序列的默认起始范围。

3. 隔离测试上下文,防止数据残留

Spring Boot测试默认会复用应用上下文,如果有其他测试类也操作了product表,可能导致数据残留到当前测试中,引发主键冲突。

  • 解决方式:
    在测试类上添加@DirtiesContext注解,确保每个测试方法执行后重置上下文:
    @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
    @DataJpaTest
    @Sql("classpath:data.sql")
    public class ClientRepositoryTest {
        // 测试代码
    }
    

4. 确认Schema与表名匹配

你在data.sql中使用了public.product的全限定表名,但H2数据库默认的Schema可能不是public,或者测试环境的JPA配置指定了其他Schema,导致实际插入的表和实体映射的表不一致,但主键序列共用引发冲突。

  • 解决方式:
    • 检查测试配置中的spring.jpa.properties.hibernate.default_schema是否设置为public;
    • 或者将data.sql中的表名简化为product,去掉Schema前缀。

5. 直观验证H2数据库状态

开启H2控制台,直接查看测试执行前后product表的数据,就能明确数据来源:

  • 在application-test.properties中添加配置:
    spring.h2.console.enabled=true
    spring.h2.console.path=/h2-console
    
  • 启动测试后,访问http://localhost:8080/h2-console,使用测试环境的H2连接参数登录,查看product表的初始数据和插入记录,定位重复插入的原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 22:40:07