2013-07-26 68 views
1

我使用Hibernate來實現對運行Jboss5一個Web應用程序的DAO層(DB的Sybase)我如何檢查DB是交易之間的鎖定

我面臨的問題是當客戶端/用戶界面多次同時進行HTTP調用時(這反過來又會調用DAO插入方法)會導致兩個調用在幾乎相同的時間運行DAO插入方法。我真正想要的是

  1. 第1請求調用DAO方法
  2. 1請求讀取當前的分貝值
  3. 檢查如果基於當前的分貝值
  4. 如果有效的新數據是有效的,插入新的價值
  5. ,然後第二個請求讀取當前dB值
  6. 檢查新數據是否有效
  7. 如果有效,將值...等等,如果有更多的呼叫

我DAO層的代碼看起來像這樣:

@Override 
@Transactional 
public Set<PartyData> insertPartyData(final Set<PartyData> pData) throws DataServiceException 
{ 
    sessionFactory.getCurrentSession().getTransaction().begin(); 
    //code to read the current db value 
    //validation code to check if new value can be inserted based on what's currently in db 
    sessionFactory.getCurrentSession().save(pData); 
    sessionFactory.getCurrentSession().getTransaction().commit(); 
} 

問題?

如何確保數據庫在一個事務的持續時間內鎖定表,以便任何其他請求等到上一個事務完成時纔會等待?

+0

你使用什麼web容器? – MaVRoSCy

+0

Web容器 - Jboss5 – kapricanon

+0

您正在使用哪些DBMS? Postgres的?甲骨文? –

回答

0

*答案*

好吧我曾嘗試以下解決方案,它似乎至今已經奏效。

什麼似乎發生每個請求似乎創建一個新的會話,該會話運行在自己的事務。所以沒有兩個請求似乎互相干擾,每個事務一次運行。

我不是hibernate的專家,所以如果這不是正確的方法,請糾正我。

@Override 
@Transactional 
public Set<PartyData> insertPartyData(final Set<PartyData> pData) throws DataServiceException 
{ 
    final Session session = sessionFactory.openSession(); 
    Transaction tx; 
    try { 
     tx = session.beginTransaction(); 
     \\read curren db value and do the validation with new data (throw exception if validation fails else continue) 
     session.save(pData); 
     } 
     tx.commit(); 
    } 
    catch (final Exception e) { 
     throw new DataServiceException(e); 
    } 
    finally { 
     session.close(); 
    } 
    return pData; 
} 
+0

不要忘記,你可以接受你自己的答案.. – MaVRoSCy

+0

是的,但它說我只能在2天后做到這一點??是這樣嗎? – kapricanon

+0

啊,是的,這是正確的 – MaVRoSCy

0

雖然鎖定表將工作 - 鎖定整個表的過程似乎並不正確。必須有其他方式來完成你想要做的事情,比如獨特的限制。

+1

這不提供問題的答案。要批評或要求作者澄清,在他們的帖子下留下評論 - 你總是可以評論你自己的帖子,一旦你有足夠的[聲譽](http://stackoverflow.com/help/whats-reputation),你會能夠[評論任何帖子](http://stackoverflow.com/help/privileges/comment)。 –

+0

@ kapricanon:您的解決方案是不可擴展的,因爲羣集環境不可用。 爲什麼不試試我的答案? – ChanceLai

+0

@ChanceLai - 不能使用唯一約束,因爲數據驗證(我的問題中的第3點)不像檢查重複數據那樣簡單,有一些更復雜的邏輯來檢查某些值的存在並且它們不存在允許插入某些新值。還有其他建議嗎? – kapricanon

0

IMO這是最好的容器級別而不是應用程序級別(不知道它可能甚至在應用層面做)做。

基於此article,您可以通過在連接器中配置兩個屬性來做你喜歡的事情。

設置maxThreads爲1(maxThreads: The maximum number of request processing threads to be created by this connector, which therefore determines the maximum number of simultaneous requests that can be handled. If not specified, this attribute is set to 200.

這將確保您運行的各個時間正好一個請求。

增加acceptCount:(acceptCount: The maximum queue length for incoming connection requests, when all possible request processing threads are in use. Any requests received when the queue is full will be refused. The default value is 10.

這應該被設定得比較高,這樣你就不會拒絕你的服務連接,而隨後添加到隊列,直到另一個請求執行完畢。

+0

對不起,我應該提到我們在共享和高度控制的生產環境中運行。所以改變集裝箱層面的任何設置都是不可能的。 – kapricanon

+0

這很好,一個連接器可以設置爲僅對您的應用程序有效(port,bindAddress) – MaVRoSCy

+0

所以我正確地說如果我將maxThreads設置爲1,我的應用程序將一次只能處理一個請求?如果是的話,這個基石會放慢用戶體驗。 – kapricanon