[英]How to isolate transactions with hibernate
我已经阅读了有关isolation levels
的hibernate
文档,并在使用PostgreSql
的示例中尝试了它们,以检查在并发执行同一数据集上的事务时它们是否保证线程安全。 我使用最强的isolation level
,将Serializable
用作:
<property name="hibernate.connection.isolation">8</property>
这段代码是:
ExecutorService service = Executors.newFixedThreadPool(10);
IntStream.range(0, 20).forEach(t -> {
service.submit(() -> {
updateSalary(2L);
});
});
static void updateSalary(long id) {
Session s = sessionFactory.openSession();
org.hibernate.Transaction tx = null;
try {
tx = s.beginTransaction();
Customer c = (Customer) s.load(Customer.class, id);
c.setSalary(c.getSalary() + 10);
tx.commit();
}
catch(Exception e) {
e.printStackTrace();
tx.rollback();
}
finally {
s.close();
}
}
但是会引发异常:
org.postgresql.util.PSQLException: ERROR: could not serialize access due to concurrent update
如果我使用ReentrantLock
同步方法updateSalary()
:
static void updateSalary(long id) {
lock.lock();
Session s = sessionFactory.openSession();
org.hibernate.Transaction tx = null;
try {
tx = s.beginTransaction();
Customer c = (Customer) s.load(Customer.class, id);
c.setSalary(c.getSalary() + 10);
tx.commit();
}
catch(Exception e) {
e.printStackTrace();
tx.rollback();
}
finally {
s.close();
}
lock.unlock();
}
它有效并且线程安全。 这是在休眠事务中实现线程安全的适当方法吗? 如果没有,推荐的方法是什么? 在这种情况下,如何使用Session.buildLockRequest()
实现线程安全?
事务并非旨在使程序具有线程安全性。 它们用于保证对数据库所做的一组更改是完全应用或根本不应用,包括确保您已读取的数据在事务期间没有更改。
您所看到的行为是完全可以预期的。 数据库检测到并发更新,并引发异常通知您,因此您可以采取适当的措施(例如重试,或通知用户数据可能已更改)。
正如john16384回答的那样,事务旨在确保一组语句是否一起执行。
我不会锁定关键方法,因为它将影响性能和可伸缩性。 我将让方法并发执行,但是使用Hibernates VERSION列来确定数据在获取后是否已更新。 您可以使用Hibernate VERSION列方法找到大量材料。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.