Java 在@Transactional块末尾引发的唯一约束错误
假设我有一个用户类:Java 在@Transactional块末尾引发的唯一约束错误,java,spring,hibernate,jpa,transactions,Java,Spring,Hibernate,Jpa,Transactions,假设我有一个用户类: @Entity @Data @Builder public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) Long userKey; @Column(unique = true) String someId; String name; } 这是相应的服务 @Component @Slf4j public class UserServic
@Entity
@Data
@Builder
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long userKey;
@Column(unique = true)
String someId;
String name;
}
这是相应的服务
@Component
@Slf4j
public class UserService {
@Autowired
UserRepository repository;
@Transactional
public User createUserWithId(String name, String id) {
User userToAdd = User.builder()
.name(name)
.someId(id)
.build();
repository.save(userToAdd);
log.info("No issue in saving");
//some more code
return userToAdd;
}
}
正如您所看到的,我在User类中的someId字段上有一个唯一的约束,但是当我使用someId中的值执行方法createUserWithId时,该值已经存在于DB中,我希望在包含repository.save()的行上得到一个错误,并且不执行它后面的代码。但是代码在执行之后,我在事务块的末尾得到一个异常。我的问题是为什么会发生这种情况,在与repository对象(如本例中的repository.save)交互时通常会遇到哪些异常,以及在事务块结束时会遇到哪些类型的异常
PS我从一个简单的控制器中调用UserService,我创建了一个空的UserRepository,它只是扩展了Crudepository。为了简洁起见,我在问题中遗漏了这两个方面,但请让我知道在这里添加它们是否有意义
编辑1:根据注释中的请求添加用户存储库
@Repository
public interface UserRepository extends CrudRepository<User, Long> {
}
@存储库
公共接口UserRepository扩展了Crudepository{
}
复制时发生Uniqe错误。
spring具有数据库错误帮助器类,您可以捕获@transactional传递给控制器的控制器层上的db异常
} catch (DataAccessException ex) {
或
如果数据库连接器具有标准异常抛出支持
就你而言,我想你错过了
@Transactional(readOnly = false)
该错误发生在拦截器中,因为在提交事务之前,Hibernate需要刷新对数据库的挂起更改。在刷新期间,会发生数据库异常。您可以通过调用存储库上的
saveAndFlush
手动刷新。当我们调用
repository.save(obj);
hibernate将该实体保存在内存中,该实体将在事务中方法的末尾持久化
执行此类操作的另一种方法是,首先应尝试获取id上的结果
repository.findById(id)
并检查它是否为null,并相应地执行保存操作。共享
UserRepository
代码。当会话状态(来自ORM映射器)与数据库同步时,会引发异常。通常是在事务提交时。如果要强制执行,您需要在JPAEntityManager
上调用'flush'(或者扩展JpaRepository
而不是crudepository
并调用saveAndFlush
).Thank@M.Deinum当我在事务块内调用save/delete/insert时,我是否应该期望忽略所有类型的约束,或者是否存在仅在事务块末尾检查的这些约束的特定子集?
repository.findById(id)