簡體   English   中英

EJB:在PostConstruct方法中使用EntityManager

[英]EJB: Using EntityManager in PostConstruct method

在構造bean之后,我想使用EntityManager從數據庫中檢索數據。 在構造函數中是不可能的,因為在調用構造函數之后注入EntityManager。 所以我嘗試在用@PostConstruct注釋的方法中做到這一點。 根據API,在完成所有注入后調用PostConstruct方法。 執行查詢有效,但它總是返回一個空列表。 如果我在其他方法中使用相同的查詢,則返回正確的結果。 有誰知道,為什么它在PostConstruct方法中不起作用?

@Stateful(mappedName = "price")
@Singleton
@Startup
public class PriceManagementBean implements PriceManagement {

    @PersistenceContext
    private EntityManager em;

    private List<PriceStep> priceSteps =  Collections.synchronizedList(new ArrayList<PriceStep>());


    public PriceManagementBean(){


    }


    @PostConstruct
    public void init(){
        javax.persistence.Query query = em.createQuery("SELECT ps FROM PriceStep ps");
        List<PriceStep> res = query.getResultList();
            .....
       }
}

有誰知道,為什么它在PostConstruct方法中不起作用?

原因1你不能同時創建一個@Stateful和@Singleton的bean(嗯,你可以,但是因為Singletons也是有狀態的,所以沒有任何意義),這是你遇到麻煩的原因之一。 沒有例外,但是那里存在沖突,你需要先解決這個問題。

只記得:

  • Singleton bean是一種保持其狀態的bean。 應用程序中只有一個Singleton實例,它在應用程序的所有用戶之間共享。 此外,由於它是一個共享(可能更好的並發)bean,因此需要使用@Lock注釋實現某種鎖定機制。

  • 有狀態bean是一種在交易后保留每個州的bean。 在工作時
    有狀態bean每個用戶都獲得一個bean的副本,該副本將持續與會話一樣長 - 持續或直到調用@Remove注釋的方法為止

原因2即使它有效,您也無法訪問結果,因為您將它們存儲在一個名為res的對象中,該對象只能從方法init()內部訪問。 我想你想將返回的值分配給變量priceSteps

無論如何,你的代碼中有很多錯誤,因為沒有說出一切。 我不知道你的系統要求是什么,但在這里我會給你一個簡單的解決方案,允許你訪問數據庫:

我想你正試圖以某種方式返回bean生命周期中的數據,因為如果bean是@Stateful,你想避免一次又一次地發送查詢。 問題是,您不必這樣做,您仍然可以使您的bean @Stateless並避免使用許多查詢來壓縮您的數據庫。 你需要做的是創建一個@NamedQuery

因此,使用@NamedQuery注釋您的實體PriceStep ,然后輸入您編寫的查詢字符串。 在此鏈接中,您將找到有關如何使用@NamedQueries的信息http//docs.oracle.com/cd/B31017_01/web.1013/b28221/ent30qry001.htm

接下來的事情我會建議你是來注釋類PriceManagementBean* @Stateless *。 不要擔心,如果在每個請求中創建一個新的entityManager,它根本不會對數據庫造成壓力,因為它與域模型交互。 您不需要@PostConstruct,只需在需要時調用@NamedQuery就可以了。 應用服務器將緩存它並將其返回給需要它的每個用戶,而不是始終與數據庫交互。

這里有一個代碼:

@Entity
@NamedQuery(
    name="allPriceSteps",
    queryString="SELECT ps FROM PriceStep ps"
)
public class PriceStep implements Serializable {
...
}

現在豆子:

@Stateless
public class PriceManagementBean implements PriceManagement {

    @PersistenceContext
    private EntityManager em;

    public List<PriceStep> getAllPriceSteps() {
         Query query =  em.createNamedQuery("allPriceSteps");
         return query.getResultList();
     }
}

我希望這很有用。 如果您提供有關系統要求的更多信息,我們可以為您提供最佳實踐建議。

根據您的要求,請嘗試以下方法

  • 刪除@Stateful [不能同時使用兩者]

  • @Startup將在APPLICATION INIT期間初始化單例bean [請注意應用程序未完全初始化]。 這可能會在加載EntityManager時引起一些問題,並且我假設EntityManager橋未完全初始化。 嘗試在完成應用程序啟動后調用init [ie,] Remove @Startup

暫無
暫無

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

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