我在資料庫中有一個復合唯一約束,我希望在事務中違反它,但在我呼叫 commit 后它將被維護。
這是非常基本的資料庫事務,但我不知道如何使用 JPA 來實作它。
我已經嘗試過@org.springframework.transaction.annotation.Transactional我的@org.springframework.stereotype.Service課程以及方法級別。
但是當我稱之為userRepository.save(userEntity)拋出的那一刻
java.sql.SQLIntegrityConstraintViolationException: (conn=380) Duplicate entry ...'
控制器
@PostMapping("/save")
@Transactional
fun createUser(
@RequestHeader("token", required = true) subject: String,
): ResponseEntity<*> {
val id = extractId(subject)
return userService.save(id)
}
服務
@Transactional
fun save(id: String): ResponseEntity<*> {
val validatedUser = getValidatedUser(id)
return ResponseEntity<User>(validatedUser, HttpStatus.CREATED)
}
@Transactional
fun getValidatedUser(id: String): User? {
var list = listOf(User(id))
val newUser = //some logic to generate user
userRepository.saveAll(list.plus(newUser)) // <--- where error happens
}
uj5u.com熱心網友回復:
您正在尋找DEFERRED 約束。
模仿您的操作的簡化示例(postgresql):
create table users (
id int primary key,
name varchar(255) unique
);
start transaction;
insert into users(id, name) values(1, 'max');
insert into users(id, name) values(2, 'max'); -- fails here, despite the transaction
insert into users(id, name) values(3, 'paul');
commit;
使用deferrable和set constraints deferred:
create table users (
id int primary key,
name varchar(255) unique deferrable
);
start transaction;
set constraints all deferred;
insert into users(id, name) values(1, 'max');
insert into users(id, name) values(2, 'max'); -- no fail here
insert into users(id, name) values(3, 'paul');
commit; -- fails here ("deferred")
使用deferrable initially deferred你可以跳過set constraints deferred:
create table users (
id int primary key,
name varchar(255) unique deferrable initially deferred
);
start transaction;
-- no 'set constraints deferred' necessary
insert into users(id, name) values(1, 'max');
insert into users(id, name) values(2, 'max'); -- no fail here
insert into users(id, name) values(3, 'paul');
update users set name = 'bob' where id = 2; -- fixes constraint violation
commit; -- succeeds
因此,最簡單的解決方案是添加deferrable initially deferred到您的約束定義中。
uj5u.com熱心網友回復:
您的資料庫具有復合唯一約束。所以你不能插入相同的資料。
這個錯誤意味著程式在運行時插入了相同的資料。這是不允許的。
我認為這里可能存在重復 ID 的問題。
var list = listOf(用戶(id))
由于3,在代碼的下一步中創建了兩個具有相同ID的用戶物件。因此插入資料庫時??出錯。
您可以在控制臺輸出用戶物件,并找出是否存在相同的 userId 物件。
uj5u.com熱心網友回復:
// RollbackFor=Exception.class needs to be specified
@Transactional(rollbackFor = Exception.class)
fun save(id: String): ResponseEntity<*> {
val validatedUser = getValidatedUser(id)
return ResponseEntity<User>(validatedUser, HttpStatus.CREATED)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/521170.html
