我正在使用 Java Hibernate。
用例:
我有 2 个表:A 和 B 现在,如果 B 不包含状态为 true 的 accId x 的任何行,则表 A 中的 accId x 的状态必须更改为“Activity ”,否则它应保持“不活动”。
表 A 和 B 的当前状态: B 包含 2 行(id = 1, 2),每行包含 accId 为 X 且状态为 True。 A 包含 1 行,accId 为 X,状态为 INACTIVE。
现在,对于每一行 (id = 1, 2),同时有 2 个调用,试图将相应行的 accId X 状态设置为 false。
每当任何调用使任何 accId 的状态为 false 时,我都会在表 B 中将相应行 ID 的状态设置为 false,并从表 B 本身检查是否存在该帐户 ID 的状态为 true 的任何其他行。如果不存在这样的行,我会将 accId 的状态更改为 ACTIVE。
现在,在我的情况下,如果同时有 2 个调用,它们都会检查是否存在状态为 true 的任何行,因为事务到目前为止尚未提交并保留在内存中,每个调用都发现存在状态为 true 的行仍然存在。因此,他们都在表中将各自行的状态标记为 false。但表A中accId的状态并未变为ACTIVE。
如何解决这个问题。
最佳答案
您遇到并发问题: 当其中一个调用到达时(第一个调用),您需要锁定访问。当第二个调用到达时,必须等到第一个调用完成并且问题解决。 我相信你可以指定在事务期间锁定整个表,但我从未使用过java hibernate。
来自:https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/transactions.html
11.4。悲观锁定
我们无意让用户花太多时间担心锁定策略。通常为 JDBC 连接指定隔离级别就足够了,然后让数据库完成所有工作。然而,高级用户可能希望获得独占悲观锁或在新事务开始时重新获得锁。
Hibernate将始终使用数据库的锁定机制;它从不锁定内存中的对象。
LockMode 类定义了 Hibernate 可以获取的不同锁定级别。锁是通过以下机制获得的:
LockMode.WRITE is acquired automatically when Hibernate updates or inserts a row.
LockMode.UPGRADE can be acquired upon explicit user request using SELECT ... FOR UPDATE on databases which support that syntax.
LockMode.UPGRADE_NOWAIT can be acquired upon explicit user request using a SELECT ... FOR UPDATE NOWAIT under Oracle.
LockMode.READ is acquired automatically when Hibernate reads data under Repeatable Read or Serializable isolation level. It can be re-acquired by explicit user request.
LockMode.NONE represents the absence of a lock. All objects switch to this lock mode at the end of a Transaction. Objects associated with the session via a call to update() or saveOrUpdate() also start out in this lock mode.
“显式用户请求”以下列方式之一表示:
A call to Session.load(), specifying a LockMode.
A call to Session.lock().
A call to Query.setLockMode().
如果使用 UPGRADE 或 UPGRADE_NOWAIT 调用 Session.load(),并且 session 尚未加载请求的对象,则使用 SELECT ... FOR UPDATE 加载该对象。如果为一个已经加载了比所请求的限制性更小的锁的对象调用 load(),Hibernate 会为该对象调用 lock()。
如果指定的锁定模式是 READ、UPGRADE 或 UPGRADE_NOWAIT,Session.lock() 会执行版本号检查。在 UPGRADE 或 UPGRADE_NOWAIT 的情况下,使用 SELECT ... FOR UPDATE。
如果数据库不支持请求的锁定模式,Hibernate 将使用适当的替代模式而不是抛出异常。这确保了应用程序的可移植性。
关于java - 当两个事务同时发生并相互影响时,根据另一个表的数据更新一行表的方法是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36972094/