簡體   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