CRUD存储库不遵守UNIQUE约束条件。
CRUD存储库不遵守UNIQUE约束条件。
我有下面的JPA实体
@Entity class UserEntity { companion object { fun fromParameters(uuid: String, email: String, password: String, firstName: String, lastName: String) = UserEntity().apply { this.uuid = uuid this.email = email this.password = password this.firstName = firstName this.lastName = lastName } } @Id lateinit var uuid: String @Column(nullable = false, unique = true) lateinit var email: String @Column(nullable = false) lateinit var password: String @Column(nullable = false) lateinit var firstName: String @Column(nullable = false) lateinit var lastName: String }
这是用来检查唯一约束的测试,插入另一个使用相同电子邮件的用户。
@RunWith(SpringRunner::class) @DataJpaTest @AutoConfigureTestEntityManager class TestUserCrudRepository { @Autowired private lateinit var userCrudRepository: UserCrudRepository private val testUserEntity = UserEntity.fromParameters( UUID.randomUUID().toString(), "test@test.com", "password".toHash(), "Caetano", "Veloso" ) @Test fun `when email already exists it should throw error`() { with (userCrudRepository) { save(testUserEntity) val newUserEntity = with (testUserEntity) { UserEntity.fromParameters(UUID.randomUUID().toString(), email, password, firstName, lastName) } shouldThrow { save(newUserEntity) } } } }
新实体总是会被插入具有重复电子邮件,而不会抛出任何异常。
Expected exception java.sql.SQLException but no exception was thrown
从日志中可以看到表格正确地创建了给定的约束。
Hibernate: drop table user_entity if exists Hibernate: create table user_entity (uuid varchar(255) not null, email varchar(255) not null, first_name varchar(255) not null, last_name varchar(255) not null, password varchar(255) not null, primary key (uuid)) Hibernate: alter table user_entity add constraint UK_4xad1enskw4j1t2866f7sodrx unique (email)
提前谢谢!
admin 更改状态以发布 2023年5月22日
这是因为没有发出insert
语句。
只有在有充分理由时,Hibernate才会flush
会话。
@DataJpaTest
是@Transactional
,这意味着在@Test
方法中执行的事务在方法返回后将回滚。UserEntity
映射还鼓励Hibernate延迟insert
(尝试在id
属性上使用@GeneratedValue(strategy = IDENTITY)
来强制发出insert
)
不需要深入了解这些测试运行时发生了什么:
- Spring的测试基础设施
begin
事务 @Test
方法运行save(testUserEntity)
- Hibernate意识到没有理由与数据库交互并延迟insert
shouldThrow
- 与上述相同{save(newUserEntity)} @Test
方法返回- 回滚事务。Hibernate不执行
insert
,因为没有任何理由。
如何解决?
最简单的方法是使用JpaRepository#flush
:
with (userCrudRepository) { save(testUserEntity) val newUserEntity = with (testUserEntity) { UserEntity.fromParameters(UUID.randomUUID().toString(), email, password, firstName, lastName) } save(newUserEntity) assertThrows{ flush() } }
请注意,在CrudRepository
中没有flush
方法
我猜想您已经扩展了CrudRepository
...您可能希望改为扩展JpaRepository
。
请参见:Spring Data JPA中CrudRepository和JpaRepository接口之间的区别是什么?
关于异常的说明
您希望引发SQLException
。
但是请注意,实际上会引发DataIntegrityViolationException
。
请参见:一致的异常层次结构