我正在尝试使用DataJpaTest测试我的Spring Boot存储库。我正在使用MySQL,所以我所有的模型都使用IDENTITY来生成ID:
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
但是从下面的屏幕快照中可以看到,当我运行测试时,Hibernate会为除用户和属性外的所有模型的ID设置“默认情况下作为身份生成”:
这使得我无法在测试中创建用户(或属性),因为GenerationType.IDENTITY设置始终将id设置为null,然后再将其发送到db,这会导致以下错误:
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
有人知道为什么会这样吗?而且,当然,比为什么更重要的是我该怎么做才能解决它? :)
更新 为了简化问题并针对我尝试过的不同事情提供不同的错误...
我的DataJpaTests使用的是H2,我猜它是根据代码自动生成db结构的。我真正的数据库是MYSQL,它是在一个单独的项目中生成的。
场景1:
当我将GenerationType设置为IDENTITY时,实时数据库可以工作,但测试数据库却给了我could not execute statement; SQL [n/a]; constraint [null]
。
方案2:
当我将GenerationType设置为AUTO时,测试数据库可以工作,但实时数据库却给了我Table 'tablename.hibernate_sequence' doesn't exist
。
方案3: 试图使MYSQL与GenerationType AUTO一起使用。在关于如何告诉Hibernate默认MYSQL标识而不是表的大量搜索中,我没有发现任何东西。我发现有很多说法是永远不要使用表,并且不更改Hibernate源代码就无法覆盖它。这是一堆BS,使我想知道Hibernate开发人员正在吸烟。
方案4: 试图使H2与GenerationType IDENTITY一起使用。我在以下方面很幸运:
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;MODE=MYSQL
放入test.properties文件中。@TestPropertySource(locations= "classpath:test.properties")
和@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
注释我的Test类这摆脱了空约束错误,但是我现在得到了The database returned no natively generated identity value
。据推测,这是因为,尽管实际的SQL代码具有id的auto_increment值,但是用于生成H2表的任何魔术手段都无法达到目的。
附录:令所有这些感到沮丧的是,它对于大多数表来说都可以正常工作。在我的数据库中的20多个表中,除了两个以外的所有表都可以使用IDENTITY自动生成并递增其ID。它们中的一些会起作用,而有些则不会起作用,这根本没有道理。
答案 0 :(得分:1)
问题是另一个带有@Table(name = "user")
作为注释的模型。该模型还定义了Id列,但没有生成值。由于冲突,Hibernate选择了那个来定义ID。
答案 1 :(得分:-1)
MySql与
搭配使用效果更好@GeneratedValue(strategy = GenerationType.AUTO)
它也更好,因为它在大多数RDBMS中都会产生自动递增的主键