2013-04-14 83 views
4

目前我們正在使用遊戲1.2.5與Java和MySQL。我們有一個簡單的JPA模型(一個擴展模型類的Play實體)我們保存到數據庫中。最好的方法來處理多個插入

SimpleModel() test = new SimpleModel(); 
test.foo = "bar"; 
test.save(); 

在每個Web請求我們保存SimpleModel的多個實例,例如:

JPAPlugin.startTx(false); 
for (int i=0;i<5000;i++) 
{ 
    SimpleModel() test = new SimpleModel(); 
    test.foo = "bar"; 
    test.save(); 
} 
JPAPlugin.closeTx(false); 

我們使用JPAPlugin.startTx和closeTx手動啓動和結束交易。 如果只有一個請求執行事務,一切正常。 我們注意到,如果第二個請求試圖同時執行循環,第二個請求會獲得「超出鎖定等待超時;嘗試重新啓動事務javax.persistence.PersistenceException:org.hibernate.exception.GenericJDBCException:could not insert:[ SimpleModel]「,因爲第一個請求會鎖定表,但在第二個請求超時之前不會完成。 這導致多個:

錯誤AssertionFailure:45 - 斷言失敗發生(這可能表明在Hibernate中的一個錯誤,但更可能是由於不安全使用會話) org.hibernate.AssertionFailure:空id在SimpleModel條目中(發生異常後不刷新會話)

另一個消毒是插入過程中的CPU使用率變得瘋狂。

爲了解決這個問題,我想創建一個事務感知隊列來按順序插入實體,但這會導致巨大的插入時間。 處理這種情況的正確方法是什麼?

回答

0

JPAP插件在Play Framwork 1.2.5不是線程安全的,您不會使用此版本的Play解決此問題。

該問題已在Play 2.x上修復,但如果無法遷移,請嘗試直接使用hibernate。

+0

我會試着用2x來看看會發生什麼。 – kospol

0

在這種情況下,您不需要自己處理事務。

取而代之,如果任務耗時,則可以將插入插入控制器方法或異步作業中。

作業和控制器都處理transasctions。

然而,檢查這是你真正想要實現的。每個創建5000條記錄的http請求都不太現實。也許讓一個集合的容器模型更有意義?

+0

每個請求都會啓動一個播放作業,但問題仍然存在。 – kospol

+0

嘗試擺脫startTx和stopTx,因爲事務由JobPlugin處理。你是否正在使用job.now()從控制器異步運行你的作業? – emt14

0

您是否確實需要整個插入事務?如果數據庫在數據導入過程中未被鎖定,是否重要?

您可以簡單地創建一個作業,並執行它的每個刀片:

for (int i=0;i<5000;i++) 
{ 
    new Job() { 
     doJob(){ 
      SimpleModel() test = new SimpleModel(); 
      test.foo = "bar"; 
      test.save(); 
     }.now(); 
} 

這將爲每個插入創建一個單一的交易,並擺脫你的數據庫鎖的問題。

+0

我相信這會讓事情變得更糟...... – kospol

相關問題