当前位置: 首页 > 面试题库 >

EJB:在PostConstruct方法中使用EntityManager

叶健柏
2023-03-14
问题内容

构造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();
     }
}

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



 类似资料:
  • 问题内容: SampleBean: 和配置文件是这样的: 而且我没有在bean标记上设置default-init-method属性。 任何机构都可以说出为什么@PostConstruct方法没有被调用的原因。 问题答案: 你需要(或)启用处理功能。

  • 我将HiberNate与Panache一起使用,并且需要在应用程序启动时添加用户。为此,我使用注释我的bean,然后我有一个带有注释的方法。 目前,我正在使用以下代码: 据我发现,当调用此方法时,不能保证所有内容都已经设置好,我想这就是为什么它有时会失败并出现错误的原因。我已经检查过这个问题,但由于它是针对 Spring 的,因此该方法不起作用,我没有找到任何类似的东西 Quarkus。 我是否缺

  • 在上运行的应用程序的上下文中,在执行任何业务方法之前,我需要执行许多启动任务。为此使用,bean似乎是一个很有前途的解决方案。然而,我并不完全清楚应用程序生命周期到底是什么样子。EJB 3.1规范规定了以下内容: 默认情况下,容器负责决定何时初始化单例bean实例。但是,bean开发人员可以选择性地配置单例以进行快速初始化。如果启动注释出现在Singleton bean类上,或者如果Singlet

  • 问题内容: 我想在应用程序开始时阅读文本数据装置(CSV文件),并将其放入数据库中。 为此,我创建了带有初始化方法(@PostConstruct批注)的PopulationService。 我也希望它们在单个事务中执行,因此我在同一方法上添加了@Transactional。 然而,@Transactional似乎被忽略:该交易启动/停止我的低水平DAO方法。 那我需要手动管理交易吗? 问题答案:

  • 我正在为Java11实现一个模块,并希望使用JSR250中的注释(javax.annotation.PostConstruct和javax.annotation.PreDestroy)。 我已经更改了根据依赖项从: 对此: 这个工件此行: 因此,我尝试将其添加到我的模块信息中。java文件: 但是,我得到了一个错误的导入: 错误消息是: 我已经研究了以下相关问题,但仍无法解决我的问题: 我不能在J

  • 我想在我的应用程序开始时读取文本数据夹具(CSV文件),并将其放入数据库。 为此,我创建了一个带有初始化方法的PopulationService(@PostConstruct注释)。 我还希望它们在单个事务中执行,因此我在同一个方法上添加了@Transactional。 然而,@Transactional似乎被忽略了:事务在我的低级DAO方法中启动/停止。 那么我需要手动管理交易吗?