2017-08-27 98 views
0

我正在用javaEE構建一個REST API。我使用TomEE作爲應用程序服務器。我有一個Singleton JPA DAO來處理Postgres數據庫和Stateless服務,以提供方法給我的RESTfull類,它有GET,POSTDELETE方法。到現在爲止,我使用rest assured來測試我的網址路線。一切工作正常,但我想強調我的系統,所以我這樣做:如何正確處理併發?

Runnable r1 =() -> { 
     for (int i = 0; i < 10; i++) { 
      RegisterAndLogService service = new RegisterAndLogService(); 
      //lots of service calls 
     } 
    }; 

    Runnable r2 =() -> { 
     for (int i = 0; i < 10; i++) { 
      RegisterAndLogService service2 = new RegisterAndLogService(); 
      //lots of service calls 
     } 
    }; 
    Thread t1 = new Thread(r1); 
    Thread t2 = new Thread(r2); 
    t1.start(); 
    t2.start(); 

但是,當我的一個線程第二次迭代將開始,我得到這個:

java.lang.IllegalStateException: Transaction already active 

哪有我一直在等待當前的交易完成,並且正確地處理它們,並將它們堆積起來? EJB/JPA能以某種方式參與進來嗎?進入保存請求並儘快處理它們?

回答

1

很難理解你在這裏做什麼,以及你所問的問題是在測試代碼還是在測試中的API ......或API背後的東西。

但是,如果你得到一個「交易」已經激活這意味着東西正在做這樣的事情:

  • 試圖使用多線程一個JPA事務管理器(不要),
  • 嘗試在同一個線程上執行多個同時事務(不),或者不清除(提交或回滾)事務。

在最後一種情況,查找情況下,你可以通過一個異常從負責交易代碼區域「逃離」無回滾。

我建議您查看您一直在使用的JPA文檔,以確保您瞭解事務,事務管理器和線程之間的關係。


我相信我的情況是第一位的 - 試圖使用一個單一的JPA事務管理器與多個線程。有沒有任何設計模式或有關保持單個JPA事務管理器的良好做法,同時有很多無狀態bean的實例被請求?

工作的唯一方法是讓每個線程擁有自己的事務管理器。每個線程都必須以編程方式創建(並釋放)自己的TM,或者您依賴框架來執行此操作;例如正如各種註釋所指示的那樣。

TM對象被設計爲輕量級(即便於實例化)和非線程安全。你不應該通過線程分享他們,你不應該回收它們。


1 - ...除非你有一個JPA交易是需求跨越多個線程。爲此,有「做法」。

+0

謝謝你的回答。我相信我的案例是第一個(嘗試使用具有多個線程的單個JPA事務管理器)。有沒有任何設計模式可以讓你保持單一的jpa事務管理器,同時有很多無狀態bean的實例被請求? – GabrielRado