Java JPA Hibernate MySQL无级联插入实体死锁
我有以下代码以及所有必要的详细信息:Java JPA Hibernate MySQL无级联插入实体死锁,java,hibernate,jpa,jakarta-ee,locking,Java,Hibernate,Jpa,Jakarta Ee,Locking,我有以下代码以及所有必要的详细信息: // This method is in UserService, marked with @Transactional // Called when we insert a new user into the application. // MySQL DB tables are: `user` and `user_attempt` // ISOLATION LEVEL = READ-COMMITTED @Override public void inse
// This method is in UserService, marked with @Transactional
// Called when we insert a new user into the application.
// MySQL DB tables are: `user` and `user_attempt`
// ISOLATION LEVEL = READ-COMMITTED
@Override
public void insert(User entity) {
// user_attempt has no knowledge of user
UserAttempt uA = instanceNewUserAttempt();
userAttemptDao.insertEntity(uA); // uA is assigned an AUTO_INCREMENT from MySql
// Unidirectional
// @OneToOne(fetch = FetchType.LAZY, optional = false)
// @JoinColumn(name = "user_attempt_id", nullable = false)
// private UserAttempt userAttempt;
entity.setUserAttempt(uA);
// No locks until here
super.insert(entity); // Now here 2 locks are generated in the DB, why?
// Code blocks and does not go further. super just calls em.persist(...)
}
p.S.Cascades对我来说不是一个解决方案
编辑1
添加了新的屏幕信息
编辑2
已尝试调试Hibernate,但块确实发生在org.Hibernate.dialent.identity.GetGeneratedKeysDelegate中的这行代码处:
session.getJdbcCoordinator().getResultSetReturn().executeUpdate( insert );
编辑3
将代码更改为如下所示,现在它可以工作了,但现在的区别是,在DB for User中,我必须将User_trunt_id设置为allow NULL,这在概念上不能发生,因为User和usertrunt必须组合存在:
// This method is in UserService, marked with @Transactional
// Called when we insert a new user into the application.
// MySQL DB tables are: `user` and `user_attempt`
// ISOLATION LEVEL = READ-COMMITTED
@Override
public void insert(User entity) {
UserAttempt uA = instanceNewUserAttempt();
userAttemptDao.insertEntity(uA);
super.insert(entity);
// Unidirectional
// @OneToOne(fetch = FetchType.LAZY)
// @JoinColumn(name = "user_attempt_id", nullable = true)
// private UserAttempt userAttempt;
entity.setUserAttempt(uA);
}
结论:
这是否适用于
entity.getusertrunt()的情况
返回null
,不是null,或者两者都返回?两者都返回,没关系,问题不存在。我将删除该部分以避免造成混淆,因为您的第二个屏幕截图包含关于键约束失败的备注,这似乎表明uA
实体在当时没有持久化(只是一个猜测,以前从未见过这种类型的日志记录-可能都是正常的)我有一个强烈的印象,就是super.insert()
正在自己的事务中运行,与您显示的insert()
不同。我之所以得出这样的结论,是因为只要两行都在同一事务中,行的切换(在编辑3中)就不会有什么区别:实体的“提交”只会在方法返回时发生,并且usertrunt
属性将以任何方式设置。您能否显示super.insert()
及其事务注释的代码?不是切换本身,而是添加了null=true和删除了optional=false,因为现在用户允许null usertrunt。此外,super只调用em.persist(entity),并且当前事务被加入(已调试,找到单个事务,或者调试器错误)返回null
,不是null,或者两者都返回?两者都返回,没关系,问题不存在。我将删除该部分以避免造成混淆,因为您的第二个屏幕截图包含关于键约束失败的备注,这似乎表明uA
实体在当时没有持久化(只是一个猜测,以前从未见过这种类型的日志记录-可能都是正常的)我有一个强烈的印象,就是super.insert()
正在自己的事务中运行,与您显示的insert()
不同。我之所以得出这样的结论,是因为只要两行都在同一事务中,行的切换(在编辑3中)就不会有什么区别:实体的“提交”只会在方法返回时发生,并且usertrunt
属性将以任何方式设置。您能否显示super.insert()
及其事务注释的代码?不是切换本身,而是添加了null=true和删除了optional=false,因为现在用户允许null usertrunt。此外,super只调用em.persist(entity),并且当前事务被加入(已调试,找到单个事务,或者调试器错误)。