【发布时间】: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 容器)。