繁体   English   中英

如何使用休眠隔离事务

[英]How to isolate transactions with hibernate

我已经阅读了有关isolation levelshibernate文档,并在使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM