将实体管理器注入无状态bean的问题

时间:2011-12-17 13:03:15

标签: java-ee-6

我正在开发一个EJB3-app,我使用无状态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);
}

2 个答案:

答案 0 :(得分:2)

您正在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交易类型,同时您定义<jta-data-source>元素(这意味着您将使用JTA交易),
  • 我假设您正在使用EclipseLink,因此<exclude-unlisted-classes>false</exclude-unlisted-classes>正在运行。请注意,这不是一个可移植的解决方案 - 为了确保在Java SE环境中您的实体对JPA提供程序可见,您应该使用<class>元素定义它们。

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

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

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

答案 1 :(得分:0)

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