我已阅读有关hibernate
的{{1}}文档,我在一个示例中尝试使用isolation levels
来检查它们是否在执行同一数据集上的事务时保证线程安全同时。我使用最强的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
将方法updateSalary()
同步为:
ReentrantLock
它有效且线程安全。这是在hibernate事务中实现线程安全的适当方法吗?如果不是,推荐的方式是什么?在这种情况下,如何使用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();
}
来实现线程安全?
答案 0 :(得分:0)
事务不是为了使程序具有线程安全性。它们用于保证数据库的一组更改完全应用或根本不应用,包括确保您在事务期间读取的数据没有更改。
您所看到的行为是完全可以预料到的。数据库检测到并发更新并抛出异常通知您,以便您可以采取适当的措施(如再次尝试,或通知用户数据可能已更改)。
答案 1 :(得分:0)
正如john16384所述,交易是为了确保一组语句是否一起执行。
我不会对关键方法进行锁定,因为它会影响性能和可伸缩性。我会让方法同时执行,但使用Hibernates VERSION列来确定数据在获取后是否已更新。您可以使用Hibernate VERSION列方法找到大量材料。