使用 Maven + intelliJ + Tomcat 7 + JPA2 在 EntityManager 上出现 NullpointerException

NullpointerException on EntityManager using Maven + intelliJ + Tomcat 7 + JPA2

您好,我正在使用 JPA2 设置一个非常简单的应用程序,当我尝试使用 EntityManager 时出现空指针异常 我在用: 智能想法 行家 联合行动计划 2 小服务程序 3 Tomcat7

这是我的项目结构: -> http://picpaste.com/screen1-ZKITGaeh.jpg

Persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>

<persistence-unit name="mymoneyunit" transaction-type="RESOURCE_LOCAL">
    <description>
        Persistence unit for the JPA tutorial of the Hibernate Getting Started Guide
    </description>
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
    <class>com.mymoney.entities.User</class>

    <properties>
        <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
        <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/moneydb" />
        <property name="javax.persistence.jdbc.user" value="root" />
        <property name="javax.persistence.jdbc.password" value="****" />

        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
        <property name="hibernate.show_sql" value="true" />
        <property name="hibernate.format_sql" value="true"/>
        <property name="hibernate.hbm2ddl.auto" value="create-drop" />
    </properties>

</persistence-unit>

UserDAO:

package com.mymoney.database;

import com.mymoney.entities.User;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import java.util.List;

public class UserDAO {
    private EntityManager em;
    @PersistenceContext(unitName = "mymoneyunit")
    public void setEntityManager(EntityManager entityManager) {
        this.em = entityManager;
    }
    public List<User> findAll() {

        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<User> criteria = cb.createQuery(User.class);
        Root<User> user = criteria.from(User.class);

        criteria.select(user).orderBy(cb.asc(user.get("name")));
        return em.createQuery(criteria).getResultList();
    }
}

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>myMoney</groupId>
    <artifactId>myMoney-artifact</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
    <properties>
        <hibernate.version>4.3.8.Final</hibernate.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
   <!--     <dependency>
            <groupId>javax.enterprise</groupId>
            <artifactId>cdi-api</artifactId>
            <scope>provided</scope>
        </dependency> -->
        <!-- MySQL JDBC connector -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.27</version>
            <scope>provided</scope>
        </dependency>

        <!-- tomcat jdbc -->
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jdbc</artifactId>
            <version>7.0.35</version>
            <scope>provided</scope>
        </dependency>
        <!-- ******* JPA/Hibernate ******** -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.0-api</artifactId>
            <version>1.0.1.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.jboss.weld</groupId>
            <artifactId>weld-core</artifactId>
            <version>2.0.4.Final</version>
            <exclusions>
                <exclusion>
                    <groupId>org.jboss.spec.javax.el</groupId>
                    <artifactId>jboss-el-api_3.0_spec</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

</project>

家庭控制器:

@WebServlet("/home")
public class HomeController extends javax.servlet.http.HttpServlet {

    protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

    }

    protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
        System.out.println("doGet");
        UserDAO uDao = new UserDAO();
        List<User> users = uDao.findAll();
        for(User usr : users){
            System.out.println(usr.getEmail());
        }
    }
}

beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
                      http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
    bean-discovery-mode="all">
</beans>

异常:

java.lang.NullPointerException
    com.mymoney.database.UserDAO.findAll(UserDAO.java:25)
    com.mymoney.controllers.HomeController.doGet(HomeController.java:28)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)

没有任何内容被写入与 JPA 设置相关的日志:(。

感谢您的帮助

更新

我把 persistence.xml 移到了 resources/META-INF 创建了一个新的 class 来管理实体管理器,而不是使用注解来注入实体管理器:

public class PersistenceManager {
    private static PersistenceManager INSTANCE;
    private EntityManagerFactory emFactory;

    public static PersistenceManager getInstance(){
        if(PersistenceManager.INSTANCE == null){
            PersistenceManager.INSTANCE = new PersistenceManager();
        }    
        return PersistenceManager.INSTANCE;
    }

    private PersistenceManager() {
        emFactory = Persistence.createEntityManagerFactory("mymoneyunit");
    }

    public EntityManager getEntityManager() {
        return emFactory.createEntityManager();
    }


    public void close() {
        emFactory.close();
    }
}

现在我得到: 原因:java.lang.ClassNotFoundException:无法加载请求 class:com.mysql.jdbc.Driver

修复了上面的问题,在intellij中检查要导出的mysql jar并更改它在class路径中的顺序。

Unseen 违规代码位于此处:

private EntityManager em;
    @PersistenceContext(unitName = "mymoneyunit")
    public void setEntityManager(EntityManager entityManager) {
        this.em = entityManager;
    }
    ...
}

在上面的代码中,容器不会将 EntityManager 注入到您的 UserDAO class 因为:

1). @PersistenceContext 注释可用于任何 CDI bean、EJB 或 JSF ManagedBean。

2).这个特定的 EntityManager 作为 EXTENDED 持久性上下文注入,这仅仅意味着 EntityManager 是在以下情况下创建的@Stateful bean 在 @Stateful bean 被销毁时被创建和销毁。

简单地说,EntityManager 中的数据在 @Stateful bean 的生命周期内被缓存。

EXTENDED 持久性上下文的使用仅适用于 @Stateful bean。

所以,把这个:

@Stateful
public class UserDAO {
    private EntityManager em;
    @PersistenceContext(unitName = "mymoneyunit")
    public void setEntityManager(EntityManager entityManager) {
        this.em = entityManager;
    }
    ....
}

现在您的 EntityManager 名称为 mymoneyunit 将由容器注入。

注意: 为了使用 JavaEE 依赖注入,您需要使用一种 CDI 实现,例如 JBoss Weld(在这种情况下,您需要配置为如何使用 JBoss Weld with Tomcat)或由 TomEE.

提供