【问题标题】:Hibernate - Transactions : Consistency between two AccountsHibernate - 交易:两个帐户之间的一致性
【发布时间】:2018-10-12 06:00:26
【问题描述】:
Hibernate中如何保持事务之间的一致性,比如我有这种场景-
我有两个交易,T1 & T2,
两者同时在同一个帐户上操作A(初始值=500),
T1 想要添加 200 和 T2 想要从 A 中减去 100。
如果交易发生这样 -
1. T1 reads value of A as 500, T2 reads value of A as 500.
2. T1 does A = 500 + 200.
3. T2 does A = 500 -100.
4. T2 commits value of A as 400.
5. T1 commits Value of A as 700.
A 的最终值将是700,这是不正确。 A 的正确值应该是600。
如何解决这个问题?
- A = Account,表示元组,即 RDBMS 表中的行。在这里,它代表一个由帐号唯一标识的银行账户。
【问题讨论】:
标签:
java
spring
hibernate
【解决方案1】:
你可以有两种策略。
第一个是乐观锁定。它允许您检测这种情况并通过第二个事务失败来解决它们。这意味着
T1 将 A 的值提交为 700。
结果为@987654321@。要实施此策略,您应该在A 实体中创建表示当前元组版本的特殊列,并用javax.persistence.Version 对其进行注释。每次提交后,Jpa 提供程序将自动增加版本列,并在每次提交时检查它的值,如下所示:
1. T1 reads value of A (v1) as 500, T2 reads value of A (v1) as 500 .
2. T1 does A = 500 + 200.
3. T2 does A = 500 -100.
4. T2 commits value of A as 400 - db and entity versions are the same
5. T1 commits Value of A (v1) as 700 - version mismatch: db version is v2 and current version is v1 -> OptimisticLockException
第二种策略是悲观锁定(排他锁定):
它允许第一个事务(您的示例中的 T1)锁定 Tuple 从不同的事务读取\写入它,直到它释放对提交\回滚的锁定。您可以通过使用javax.persistence.LockModeType#WRITE 作为第二个参数调用javax.persistence.EntityManager#lock 来实现此目的。