我正在使用Java Hibernate。

用例:

我有2张桌子:A和B
现在,如果B不包含状态为true的accId x的任何行,则必须将表A中的accId x的状态更改为ACTIVE,否则应保持INACTIVE。

表A和B的当前状态:
B包含2行(id = 1、2),每行包含accId作为X,状态为True。
A包含1行,accId为X,状态为INACTIVE。

现在,对于每个行(id = 1、2),同时有2个调用同时出现,试图使accId X的状态对于各个行为false。

每当有任何呼叫使任何acId的状态为假时,我都会在表B中将对应行ID的状态设为false,并从表B本身检查是否存在任何其他行,且该帐户ID的状态为true。如果不存在此类行,则将accId的状态更改为ACTIVE。

现在,在我的情况下,如果同时有2个调用,它们都检查是否存在状态为true的行,因为该事务到目前为止尚未提交,并且仍保留在内存中,因此每个人都发现其中有一行真实状态仍然存在。因此,他们在各自行的表中都将其状态标记为false。但是在表A中accId的状态不会更改为ACTIVE。

如何解决这个问题。

最佳答案

您有并发问题:
您需要在一个呼叫到达(第一个)时锁定访问权限。当第二个呼叫到达时,它将不得不等待直到第一个呼叫完成并且问题得以解决。
我相信您可以指定在事务期间锁定整个表,但是我从未使用过Java休眠。

来自: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(),并且会话尚未加载请求的对象,则使用SELECT ... FOR UPDATE加载该对象。如果为一个已经加载了比请求的限制更少的锁定的对象调用load(),则Hibernate对该对象调用lock()。

如果指定的锁定模式为READ,UPGRADE或UPGRADE_NOWAIT,则Session.lock()执行版本号检查。对于UPGRADE或UPGRADE_NOWAIT,则使用SELECT ... FOR UPDATE。

如果数据库不支持请求的锁定模式,则Hibernate将使用适当的替代模式,而不是引发异常。这样可以确保应用程序是可移植的。

07-24 18:40