JUnit测试PostgreSQL主键重复问题:如何实现首次运行正常?
addCategory方法主键重复问题 问题根源很明确:你每次插入的预制测试数据占用了ID 1、2、3,但数据库的主键序列(PostgreSQL用来自动生成ID的序列)没同步更新,还是从1开始生成ID,导致前三次调用addCategory时生成的ID和预制数据重复,第四次序列走到4才避开冲突。以下是几种直接解决的方案:
同步序列到预制数据的最大ID
每次插入完预制数据后,执行SQL把序列的当前值设置为预制数据里最大的ID。假设你的category表主键序列叫category_id_seq,执行这条SQL:SELECT setval('category_id_seq', (SELECT MAX(id) FROM category));如果是Spring项目,可以用
@Sql注解在测试类/方法上指定执行这条SQL,或者在@BeforeEach方法里通过JdbcTemplate执行。别手动指定预制数据的ID
如果预制数据不需要固定ID,完全可以去掉手动赋值的id字段,让数据库序列自动生成。这样插入的预制数据ID会顺着序列走,后续addCategory生成的ID自然不会冲突。比如JPA实体用@GeneratedValue的话,预制数据的id设为null或者直接不写。测试前重置表和序列
在每次测试开始前,先清空category表并重置序列到初始值,再插入预制数据。用PostgreSQL的TRUNCATE语句可以一步搞定:TRUNCATE TABLE category RESTART IDENTITY;这条语句会清空表,同时把关联的主键序列重置为初始值,之后插入预制数据(不管是自动生成还是手动指定ID),后续
addCategory生成的ID都会和预制数据不重叠。检查ORM的ID生成配置
确认实体类的ID生成策略是基于数据库序列的(比如JPA用@GeneratedValue(strategy = GenerationType.SEQUENCE)),如果用的是IDENTITY类型,也要确保PostgreSQL的identity列和序列是关联同步的,避免ORM自己生成ID导致和数据库序列脱节。
内容的提问来源于stack exchange,提问作者v4d1k

