2014-10-07 37 views
1

如何確定適用於像下面這樣的JPA存儲庫的CDI範圍?哪個CDI範圍應該是首選的JPA存儲庫

@Transactional 
public class CategoryRep extends EntityRepository<Integer, Category> { 

    private static final long serialVersionUID = 856370976984333182L; 

    public List<Category> getAllCategories() { 
     // TODO 
    } 

    public List<Post> getAllPostsOfCategory(Integer categoryId) { 
     // TODO 
    } 

    @Transactional(value = TxType.REQUIRES_NEW, rollbackOn = RuntimeException.class) 
    public void createCategory(final String name, final String description) 
      throws DaoJpaException { 
     // TODO 
    } 
} 

我能想到的只有兩個CDI作用域:

  1. @SessionScope: 對我來說,這似乎是最合適的範圍,因爲一個實例是專門爲活動會話。
  2. @依賴: 也是合理的,因爲這樣的實例將適合它將被注入的對象的生命週期。

所有其他CDI-範圍是不是在我看來適當的:

  1. @ApplicationScoped:由於應用範圍的倉庫將被創建了一次,一時間,就像一個電話:entityManager.clear()會引起所有當前會話的所有實例也將被分離。另外,這個單個存儲庫必須處理所有傳入的請求。這個範圍可能適用於只讀存儲庫嗎?
  2. @RequestScope:我認爲沒有必要爲每個到來的請求新的存儲庫實例。
  3. @ConversionScoped:轉化是在GUI層通常執行。如果我希望存儲庫在轉換結束後死掉,我可以將其定義爲@Dependent

那麼,有沒有知道這個問題的最佳做法?

回答

3

來描述所有的選項

  • 會話範圍並沒有真正意義,因爲你的倉庫應該是無狀態的會話因此應該有它沒有任何意義(儘管它可以解決併發問題
  • 依賴範圍可能是一個很好的選擇,但是它可能會導致內存泄漏(您永遠無法確定從內存中刪除相關對象)
  • 對話範圍也沒有任何意義,它與Session相同範圍

所以我會去與任何

  • 請求範圍 - 我會說這是最好的選擇,它是無狀態由它的性質,以便你會避免任何併發問題。也不要擔心性能,在新的JVM中真正快速地創建新對象
  • 應用程序範圍也是一個不錯的選擇,但是您需要考慮併發性問題(多個客戶端同時調用相同的方法)。

因此,如果我是你,我會去請求範圍存儲庫,這是最簡單的選擇,你將避免所有這些問題。

+0

謝謝@ @ Version'屬性是否通過使用@ ApplicationScoped來解決併發問題? – 2014-10-08 10:04:07

+0

說實話,我不確定,因爲javadoc只會談論保持完整性,而合併實體,在我看來,這是不夠的。 – 2014-10-08 10:28:25

+0

我認爲樂觀和悲觀鎖定的使用應該解決併發問題。 – 2014-10-09 19:42:36

1

您應該使用@ApplicationScoped。

應該爲每個請求使用一個EntityManager,而不是重用。

在您創建的EntityManager要求的乞討,當它完成提交或回滾它。

@Dependent都會有「主人」的同一範圍內,如果你在一個@RequestScoped注入它和豆腐將具有相同的範圍。

@SessionScoped只能用於小數據(如用戶登錄和權限)。