如何用hibernate隔离事务

时间:2017-03-11 19:10:30

标签: java multithreading hibernate transactions

我已阅读有关hibernate的{​​{1}}文档,我在一个示例中尝试使用isolation levels来检查它们是否在执行同一数据集上的事务时保证线程安全同时。我使用最强的PostgreSqlisolation 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(); } 来实现线程安全?

2 个答案:

答案 0 :(得分:0)

事务不是为了使程序具有线程安全性。它们用于保证数据库的一组更改完全应用或根本不应用,包括确保您在事务期间读取的数据没有更改。

您所看到的行为是完全可以预料到的。数据库检测到并发更新并抛出异常通知您,以便您可以采取适当的措施(如再次尝试,或通知用户数据可能已更改)。

答案 1 :(得分:0)

正如john16384所述,交易是为了确保一组语句是否一起执行。

我不会对关键方法进行锁定,因为它会影响性能和可伸缩性。我会让方法同时执行,但使用Hibernates VERSION列来确定数据在获取后是否已更新。您可以使用Hibernate VERSION列方法找到大量材料。