ane*_*rgy 19 java jpa java-ee-6 jpa-2.0
考虑这种情况,在不同的无状态bean中存在两种方法
public class Bean_A {
Bean_B beanB; // Injected or whatever
public void methodA() {
Entity e1 = // get from db
e1.setName("Blah");
entityManager.persist(e1);
int age = beanB.methodB();
}
}
public class Bean_B {
//Note transaction
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void methodB() {
// complex calc to calculate age
}
}
Run Code Online (Sandbox Code Playgroud)
由BeanA.methodA启动的事务将被挂起,并且将在BeanB.methodB中启动新事务.如果methodB需要访问由methodA修改的同一实体,该怎么办?这会导致死锁.是否可以在不依赖隔离级别的情况下阻止它?
ewe*_*nli 23
嗯,让我们列出所有案例.
REQUIRES_NEW并没有真正嵌套交易,但正如你所提到的暂停当前交易.然后只有两个事务访问相同的信息.(这类似于两个常规并发事务,除了它们不是并发但在同一执行线程中).
T1 T2 T1 T2
? ?
| |
|
? | ?
| | |
| = | |
? | ?
|
| |
? ?
Run Code Online (Sandbox Code Playgroud)
然后我们需要考虑乐观与悲观锁定.
此外,我们需要考虑刷新由奥姆斯操作.对于ORM,我们在写入时没有明确的控制,因为它flush是由框架控制的.通常,在提交之前发生一次隐式刷新,但是如果修改了许多条目,框架也可以进行中间刷新.
1)让我们考虑乐观锁定,其中读取不获取锁定,但写入获取独占锁定.
T1的读取不会获得锁定.
1a)如果T1确实冲破了这些变化,那么它获得了一个排他锁.当T2提交时,它会尝试获取锁定但不能.系统被阻止.这可能是一种特殊的僵局.完成取决于事务或锁定超时的方式.
1b)如果T1没有预先冲洗更改,则不会获得锁定.当T2提交时,它获取并释放它并且成功.当T1尝试提交时,它会注意到冲突并失败.
2)让我们考虑悲观锁定,其中read获取共享锁并写独占锁.
T1读取获取共享锁.
2a)如果T1正常冲洗,它会将锁扣转为专用锁.情况类似于1a)
2b)如果T1没有冲洗,T1保持共享锁.当T2提交时,它会尝试获取独占锁并阻塞.系统再次被阻止.
结论:如果没有发生过早冲洗,那么乐观锁定很好,你无法严格控制.