【问题标题】:Why do JPA EntityManager queries always return NullPointerException?为什么 JPA EntityManager 查询总是返回 NullPointerException?
【发布时间】:2017-05-14 23:59:13
【问题描述】:

我正在尝试在我的 Java 8 Web 项目中实现 Java Persistence API (JPA)。在 Tomcat 8 上运行。

我使用的persistence.jar来自EclipseLink

我的 persistence.xml 配置如下:

<?xml version="1.0" encoding="UTF-8"?>
  <persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
    <persistence-unit name="myDatabase" transaction-type="JTA">
      <non-jta-data-source>jdbc/myDB</non-jta-data-source>
    </persistence-unit>
  </persistence>

我的 JNDI 资源是在 context.xml 中定义的,并且我已经测试它可以作为另一个类中的常规 DataSource 进行查询,因此数据库连接正常运行。

我关注了Java EE 7: The Big Picture,Danny Coward 博士的“第 12 章:现代记忆:Java 持久性 API”,但无法获得任何 em.find, em.createNamedQuery 等工作。

我使用实体管理器访问数据:[stub]

@Singleton
public class JPAPersonDataImpl {
    @PersistenceUnit
    private EntityManager em;

    private Person getPersonById(int id) {
        return (em.find(Person.class, id));
    }
}

如果使用实体管理器工厂,我的数据访问权限:[stub]

@Singleton
public class JPAPersonDataImpl {
    @PersistenceUnit(unitName = "myDatabase")
    private EntityManagerFactory entityManagerFactory;

    private Person getPersonById(int id) {
        EntityManager em = entityManagerFactory.createEntityManager();
        try {
            return (em.find(Person.class, id));
        } finally {
            em.close();
        }
    }
}

我的 Person.class [存根]

@Entity
@NamedQueries(
        {
                @NamedQuery(
                        name = "Person.getAllPersons",
                        query = "select m from Person m"
                ),
                @NamedQuery(
                        name = "Person.getPersonByUsername",
                        query = "select m from Person m where m.userName = :userName"
                ),
                @NamedQuery(
                        name = "Person.getLastPersonCreated",
                        query = "select m from Person m order by m.PersonId desc"
                ),
                @NamedQuery(
                        name = "Person.getUsernames",
                        query = "select m.userName from Person m"
                )
        }
)
public class Person implements Serializable {
    @Id
    @Column(name="PersonId")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
    private String userName;
    private String firstName;
    private String surname;
    private Date joined;

    public Person() {}

    public Person(int id, String userName, String firstName, String surname, Date joined) {
        this.id = id;
        this.userName = userName;
        this.firstName = firstName;
        this.surname = surname;
        this.joined = joined;
    }

    public int getId() {
        return this.id;
    }

    public String getUserName() {
        return this.userName;
    }

    public String getFirstName() {
        return this.firstName;
    }

    public String getSurname() {
        return this.surname;
    }

    public Date getJoinedDate() {
        return this.joined;
    }
}

执行 NamedQueries 的示例(我已经尝试了所有的 TypedQuery、Query 以及创建原生查询 - 都返回 NullPointer):

@Singleton
public class JPAPersonDataImpl {
    @PersistenceUnit(unitName = "myDatabase")
    private EntityManagerFactory entityManagerFactory;

    // This can also be modifed to use EntityManager instead of EntityManagerFactory
    private boolean userNameIsInUse(String username) {
        EntityManager em = entityManagerFactory.createEntityManager();
        try {
            TypedQuery<Person> queryUserNames = em.createNamedQuery("Person.getUsernames", Person.class);
            List queryResultList = queryUserNames.setMaxResults(1).getResultList();
            return (matchInList(queryResultList, username));
        } finally {
            em.close();
        }
    }
}

当存在有效的 JNDI 资源时,为什么任何访问尝试(查询、持久化、删除、查找等)都会返回 NullPointerException?我可以做一个简单的测试来确定 EntityManager 是否设置正确?

【问题讨论】:

  • 我猜你是在实例化而不是注入你的JPAPersonDataImpl
  • 如果您能分享 excpetion 的完整堆栈跟踪,将会很有帮助。
  • 我认为@chrylis 在这里有答案。您如何处理 JPAPersonDataImpl 实例的创建?您应该使用@EJB 注释注入它,该注释赋予容器(Tomcat)控制权。你应该JPAPersonDataImpl bean = new JPAPersonDataImpl()这样自己实例化它。
  • 嗨@chrylis 和~matt - 我认为你的诊断对我来说是正确的。我对 Java EE 完全陌生 - 所以我正在下载 Apache OpenEJB 并将我的 bean 设为 Enterprise Bean 以查看它是否有效。我猜这让我想到了另一个问题——为什么 IntelliJ 编译器不以开发人员更容易看到的方式处理注释问题?也许我需要为 EJB 正确设置我的项目结构!
  • Tomcat 不是 EJB 容器(它是一个 Servlet 容器)。使用 @EJB 进行注释不适用于 Tomcat。您需要像 GlassFish、JBoss 这样的 Web 服务器(它们提供 EJB 容器)。

标签: java jpa jndi tomcat8


【解决方案1】:

您应该了解Entitymanagers 的管理方式。 i) 容器管理 ii) 应用程序管理。 在您的情况下,由于 Tomcat 不是 J2EE 容器,请查看 Application managed EM。 看看这个。 https://docs.oracle.com/javaee/7/tutorial/persistence-intro003.htm

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-04
    • 2020-03-19
    • 2021-05-24
    • 1970-01-01
    • 2020-11-26
    • 1970-01-01
    • 2019-09-11
    • 1970-01-01
    相关资源
    最近更新 更多