【问题标题】:Problems in injecting entity manager into stateless bean将实体管理器注入无状态bean的问题
【发布时间】:2011-12-17 13:03:15
【问题描述】:

我正在开发一个 EJB3 应用程序,我在其中使用无状态 bean。 EntityManager 似乎没有正确注入到我的 bean 中。

这是无状态 bean 的代码:

@Stateless
@LocalBean
public class FirmEJB {

    @PersistenceContext(unitName = "Fr14_07_Nezdolij_lab3PU")
    private EntityManager em;

    @PersistenceUnit(unitName="Fr14_07_Nezdolij_lab3PU")
    private EntityManagerFactory emf;

    public FirmEJB() {
        emf = Persistence.createEntityManagerFactory("Fr14_07_Nezdolij_lab3PU");
        em = emf.createEntityManager();
    }

    public EntityManager getEm() {
        return em;
    }

    public void setEm(EntityManager em) {
        this.em = em;
    }

    public Employee createEmployee(Employee e){
        em.persist(e);
        return e;
    }

    public Project createProject(Project p){
        em.persist(p);
        return p;
    }

    public Customer createProject(Customer c){
        em.persist(c);
        return c;
    }

    public Department createProject(Department d){
        em.persist(d);
        return d;
    }

    public ProjectManager createProjectManager(ProjectManager prjman){
        em.persist(prjman);
        return prjman;
    }

}

当我尝试创建FirmEJB I 的实例时,出现以下异常:

Exception in thread "main" java.lang.NullPointerException
    at sttls.FirmEJB.createEmployee(FirmEJB.java:42)
    at entity.Main.main(Main.java:33)

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="Fr14_07_Nezdolij_lab3PU" transaction-type="RESOURCE_LOCAL">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>jdbc/fir</jta-data-source>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
            <property name="eclipselink.ddl-generation" value="create-tables"/>
            <property name="eclipselink.jdbc.url" value="jdbc:derby://localhost:1527/firmDB;create=true"/>
            <property name="eclipselink.jdbc.user" value="admin"/>
            <property name="eclipselink.jdbc.password" value="admin"/>
        </properties>
    </persistence-unit>
</persistence>

客户端代码

public static void main(String[] args) throws ClassNotFoundException, Exception {

    Employee emp1 = new Employee("Alan", "Smith");

    FirmEJB firmejb = new FirmEJB();
    firmejb.createEmployee(emp1);
}

【问题讨论】:

  • 你的entity.Main.main(Main.java:33) 是什么?这是您从 Java SE 执行的 static void main 方法吗?您是否使用任何 Java EE 6 容器来运行您的代码?
  • 我刚刚向 FirmEJB 类添加了一个公共构造函数和私有 EntityManagerFactory 字段,现在 FirmEJB 已正确初始化,但持久性在 FirmEJB 方法中不起作用...
  • 是的,我正在使用 Java EE 6 容器,我从 JavaSE main() 方法调用 FirmEJB。无效吗?
  • 您应该发布您的客户端代码,向我们展示您是如何执行 FirmEJB 的。也请发布您的persistence.xml 以获得许可。
  • 我还更改了 FirmEJB 类中的代码。

标签: java-ee-6


【解决方案1】:

您正在 Java SE 环境中使用 Java EE 功能。 那行不通。

负责依赖注入的 Java EE 容器,因此 PersisteneContextPersistenceUnit 仅在 Java EE 容器环境(如 Glassfish 或 JBoss)中才有意义。

如果你这样定义:

@PersistenceContext(unitName = "Fr14_07_Nezdolij_lab3PU")
private EntityManager em;

@PersistenceUnit(unitName="Fr14_07_Nezdolij_lab3PU")
private EntityManagerFactory emf;

public FirmEJB() {
    emf = Persistence.createEntityManagerFactory("Fr14_07_Nezdolij_lab3PU");
    em = emf.createEntityManager();
}

您通过注释定义依赖注入,同时您自己创建 EMF 和 EM 的实例。在您的情况下,注释毫无意义

此外:

  • persistence.xml 中,您定义使用RESOURCE_LOCAL 事务类型,同时定义&lt;jta-data-source&gt; 元素(这意味着您将使用JTA 事务),
  • 我假设您使用的是 EclipseLink,所以 &lt;exclude-unlisted-classes&gt;false&lt;/exclude-unlisted-classes&gt; 正在工作。请注意,这不是一个可移植的解决方案 - 为了确保在 Java SE 环境中您的实体对 JPA 提供者可见,您应该使用 &lt;class&gt; 元素定义它们。

最后但同样重要的是,如果您在这样的 Java SE 环境中执行代码并且不启动任何嵌入式 EJB 容器,则不需要 @Stateless,因为您的类 没有任何 EJB自然。注释为@Stateless@Stateful 的POJO 通过在EJB 容器中执行获得EJB 特性。在这种情况下,它就像一个普通的 Java 类。

注意 - 即使您使用嵌入式 EJB 容器,您显示的代码也将不会实例化 EJB。您不能将 new FirmEJB() 与 EJB 一起使用。容器应该负责为您提供 EJB 的实例。
这就是抽象的全部意义——你依赖于抽象而不是创造。

您可能有兴趣进一步阅读 OpenJPA JPA ConceptsOpenEJB Documentation

【讨论】:

  • 另外,请定义“持久性在 FirmEJB 方法中不起作用”是什么意思。
  • 它不会将实体持久化到表中。在我的客户端代码示例中,创建了所有表,但 Employee emp1 不在表Employees 中,尽管我调用了firmejb.createEmployee(emp1);
  • 这可能是因为您没有提交交易。如果您使用RESOURCE_LOCAL 交易类型,则意味着您需要通过EntityManager#getTransaction 获取EntityTransaction 并使用它:在您的交易开始时begin() 和在进行更改后commit()
  • 好的,我明白了。那么在JavaSE中使用Persistence API正常吗?
  • 是的。你只是用不同的方式。我认为您应该阅读 EJB 和 JPA 之间的区别。您不需要 EJB 来使用 JPA。两者 - EJB 和 JPA 都可以在 Java SE 中使用(即通过嵌入式容器的 EJB 和使用 RESOURCE_LOCAL 实体管理器的 JPA。)。希望它说清楚:-)
【解决方案2】:

你需要改变transaction-type="RESOURCE_LOCAL" to transaction-type="JTA"

【讨论】:

  • 请给你的答案添加一些解释!
猜你喜欢
  • 2011-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-24
  • 2020-04-22
  • 2015-01-04
相关资源
最近更新 更多