簡體   English   中英

如何正確使用休眠

[英]How to use hibernate properly

每次我想對休眠進行一些操作時,我的應用程序中都會包含以下代碼:

Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
session.save(obj); //or delete, update etc.
session.getTransaction().commit();
session.close();

這當然不是一個好習慣。 什么是進入休眠狀態而不出現這種情況的最佳方法? 我是否應該使用某些“ Util”類,其中包含執行相同工作的靜態方法? 也許單身人士更好? 我還需要將此代碼包裝在線程或SwingWorker中,以免在訪問數據庫時凍結GUI。

是的,該代碼非常糟糕。

  1. 它為每個數據庫訪問打開一個事務。 這效率低下,而且可能不正確(通常,整個動作組必須是原子操作。例如,請考慮

     public void buy(String accountId) { Account account = load(accountId); account.balance -= 100; save(account); } 

    如果裝入和保存在他們自己的事務中,並且某些惡意用戶同時購買了2件商品,則可能會發生以下情況:

    • 線程1讀取余額(= 1000)
    • 線程2讀取余額(= 1000)
    • 線程1寫入余額(= 900)
    • 線程2寫入余額(= 900)

    因此用戶購買了兩次,但只支付了一次;-)

  2. 如果save()拋出異常,它不會完成事務。 實際上,該事務將無限期保持打開狀態,包括它持有的所有鎖...

諸如此類的復雜性是大多數人以聲明方式對事務進行標定的原因,而不是像使用SpringEJB那樣重新發明方形齒輪的原因。

我認為解決的辦法是基於accountId獲取renentranlock

@Service
public class AccountService {
    private Map<String, ReentrantLock> locks = new HashMap<Long, ReentrantLock>();

    private void unlock(String id) {
        ReentrantLock lock = locks.get(id);
        if (lock != null && lock.isLocked()) {
            lock.unlock();
        }
    }

    private void lock(String id) {
        ReentrantLock lock;
        synchronized (locks) {
            lock = locks.get(id);
            if (lock == null) {
                lock = new ReentrantLock();
                locks.put(id, lock);
            }
        }
        lock.lock();
    }

public void buy(String accountId) {
    this.lock(accountId);
    try{
       Account account = load(accountId);
       account.balance -= 100;
       save(account);
    }finally{
      this.unlock(accountId);
    }
   }
}

如果整個應用程序都需要此功能,則明智的做法是圍繞服務編寫方面。

我強烈建議閱讀文章從休眠網站。

對於任何想在Hibernate中使用會話和事務的最佳方法的人來說,這篇文章都是必須的。

基本上,最佳設計模式將取決於您選擇的事務管理策略(jdbc,jta)和應用事務的模式(程序/聲明式)

正如meriton所指出的那樣,在代碼中為每種方法打開和關閉事務(假設將有幾種此類方法依次工作以形成原子操作)是一種反模式。 本文還將對此進行更詳細的討論。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM