java - 当两个事务同时发生并相互影响时,根据另一个表的数据更新一行表的方法是什么

标签 java mysql hibernate locks

我正在使用 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/

相关文章:

java - Java 中的 MVC

mysql - 转换不在子查询中加入

java - 在jpa中调用序列的下一个值

java - 使用 merge() 删除 JPA 中的多对一关系

java - jOOQ - 如何使用具有多个条件的 WHERE 创建 SQL 查询

java - 如何从抽象类中强制子类实现静态方法

java - 如何测试我的 Java 应用程序是否可以成功处理 Tomcat 服务器上的低内存/CPU 资源?

mysql:用与前一行相同的数字更新增量序列号

mysql - 更新 mysql 中的日期(phpMyAdmin)

hibernate - MS SQL Server 2008 R2 IDENTITY 列的 JPA 注释