【发布时间】:2011-06-30 15:47:55
【问题描述】:
我在 JPA 中有一个简单的一对多关系。为了便于讨论,假设我的实体是 Person 和 Phone,其中一个 Person 可以有多个 Phone(数字)。
两个对象都可以独立更新,而且我的并发性很高。我需要对两个对象都实施悲观锁定(这是我的假设)。
所以,在我的代码中,我做了类似的事情,
em.getTransaction().begin();
Person p = em.find(Person.class, id, LockModeType.PESSIMISTIC_WRITE);
...
对于电话也是如此,
em.getTransaction().begin();
Phone ph = em.find(Phone.class, id, LockModeType.PESSIMISTIC_WRITE);
...
请注意,在 Person 事务中,依赖的 Phone 对象可能会更新,反之亦然。用例是一个 lastModified 标志。更新 Phone 会更新所属 Person 中的 lastModified 时间戳,相反,更新 Person 中的 lastModified 时间戳会更新 Phone 中的 lastModified 标志(这是通过实体侦听器完成的)。我意识到用例有点做作,但尽量忽略这一点。
上面的代码导致死锁。
INFO: [EL Warning]: 2011-06-30 08:41:52.65--ServerSession(122902)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLTransactionRollbackException: A lock could not be obtained within the time requested
Error Code: 30000
我此时的假设是,Person 事务为 Person A 抢了一个锁,然后试图为 Phone 1 获取一个锁。同时,Phone 事务为 Phone 1 抢了一个锁,击败了 Person 事务,然后尝试为人 A 获取锁。死锁。
这只是一个猜测,它基于对事务如何工作的幼稚理解,以及对 JPA 中对象锁定如何工作的基本零知识。我会认为该对象及其依赖项被原子锁定......这就是为此工作所需要的。
有什么想法吗?
我将尝试解决此问题的一个想法是忘记更新同一事务中的依赖对象。相反,在第一次完成更新依赖对象后打开一个新事务。
【问题讨论】:
标签: java jpa transactions eclipselink