EJB:在PostConstruct方法中使用EntityManager [英] EJB: Using EntityManager in PostConstruct method

查看:88
本文介绍了EJB:在PostConstruct方法中使用EntityManager的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

构建bean后,我想使用EntityManager从数据库中检索数据。在构造函数中是不可能的,因为在调用构造函数之后注入EntityManager。所以我试图用@PostConstruct注释的方法。根据API,PostConstruct方法在所有注入完成后被调用。执行查询工作,但它总是返回一个空列表。如果我在其他方法中使用相同的查询,则返回正确的结果。有没有人知道,为什么在PostConstruct方法中不起作用?

  @Stateful(mappedName =price)
@Singleton
@Startup
public class PriceManagementBean实现PriceManagement {

@PersistenceContext
private EntityManager em;

私人列表< PriceStep> priceSteps = Collections.synchronizedList(new ArrayList< PriceStep>());


public PriceManagementBean(){


}


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


解决有没有人知道,为什么在PostConstruct方法中不起作用?


原因1
你不能同时创建一个@Stateful和@Singleton的bean(你可以这样做,因为Singleton也是有状态的),那就是你遇到麻烦的原因之一。没有例外,但在那里有冲突,您需要先修复。



请记住:




  • 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 {
...
}

现在的bean:

  @Stateless 
public class PriceManagementBean implements PriceManagement {

@PersistenceContext
private EntityManager em;

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

我希望这是有用的。如果您提供有关系统要求的更多信息,我们可以为您提供最佳实践的建议。


After constructing the bean, I want to retrieve data from the database, using the EntityManager. It is not possible in the constructor, because the EntityManager is injected after the constructor is called. So I tried to do it in a method annotated with @PostConstruct. According to the API, a PostConstruct Methods gets called after all injection are done. Executing the query works, but it always returns an empty list. If I use the same query in an other method, it returns the correct result. Does anybody know, why it does not work in the PostConstruct method?

@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();
            .....
       }
}

解决方案

Does anybody know, why it does not work in the PostConstruct method?

Reason 1 You cannot create a bean that is at the same time @Stateful and @Singleton(Well you can but it will make no sense since Singletons are also Stateful), that is one of the reasons you are having trouble. There is no exceptions, but there is a conflict in there, you need to fix that first.

Just remember:

  • A Singleton bean is a bean that mantains its state. There is only one instance of a Singleton in an application and it is shared among all the users of the app. Also since it is a shared(maybe better say concurrent) bean, there is need to implement some kind of locking mechanism using the @Lock annotation.

  • A Stateful bean is a bean that mantains each state after a transaction. When working with
    Stateful beans each user gets a copy of the bean which will last as long as the session - lasts or until a method annotated with @Remove is called

Reason 2 Even if it works, you will be unable to access the results, because you are storing them in an object called res which is only accessible from inside the method init(). I suppose you would like to assign that returned value to the variable priceSteps.

Anyway there are many things wrong in your code, for not saying everything. I don't know what are your system requirements, but here i would give you a simple solution that will allow you to access the database:

I suppose you are trying to in some way return the data in the life cycle of the bean because you want to avoid sending queries again and again if the bean is @Stateful. The thing is, you don't have to do that, you can still make your bean @Stateless and avoid stressing your database with many queries. What you need to do is create a @NamedQuery.

So annotate your entity PriceStep with @NamedQuery and there enter the query string you wrote. In this link you will find information about how to use @NamedQueries: http://docs.oracle.com/cd/B31017_01/web.1013/b28221/ent30qry001.htm

The next thing i would suggest you is to annotate your class PriceManagementBean as *@Stateless*. Don't worry if in each request a new entityManager is created, that does not stress the database at all, because it interacts with the domain model. You don't need @PostConstruct, you just call your @NamedQuery whenever you need it and that's it. The app server will cache it and give it back to each user that requires it without interacting with the database all time.

Here a codesnipet:

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

Now the bean:

@Stateless
public class PriceManagementBean implements PriceManagement {

    @PersistenceContext
    private EntityManager em;

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

I hope this is useful. If you give more information about your system requirements we could give you advice on a best practice.

这篇关于EJB:在PostConstruct方法中使用EntityManager的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆