在我的代码中,我正在使用JSF - 前端,EJB-Middile Tier和JPA连接到DB。使用WebservicesCalling EJB。使用MySQL作为DAtabase。 我创建了Voter表,我需要在其中插入记录。 我将值从JSF传递给EJB,它正在工作。我创建了JPA控制器类(它自动生成基于数据库类的持久性代码) 例如:获得实体经理等,
em = getEntityManager();
em.getTransaction().begin();
em.persist(voter);
em.getTransaction().commit();
我也创建了命名查询:
@NamedQuery(name = "Voter.insertRecord", query = "INSERT INTO Voter v
values v.voterID = :voterID,v.password = :password,v.partSSN = :partSSN,
v.address = :address, v.zipCode = :zipCode,v.ssn = :ssn,
v.vFirstName = :vFirstName,v.vLastName = :vLastName,v.dob = :dob"),
但仍然无法插入记录?
任何人都可以帮我通过JPA将记录插入数据库。(持久性对象)?
如果我们使用容器管理实体管理器,我们是否需要再次编写开始和提交事务... 像这样:
em.getTransaction().begin();
em.getTransaction().commit();
我写道:
Voter v= new Voter(voterID,password,partSSN,address,zipCode,ssn,vFirstName,vLastName,d1,voterFlag);
em.persist(v);
但它导致Null指针异常。
SEVERE: java.lang.NullPointerException
at ejb.Registration.reg(Registration.java:39)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
at com.sun.ejb.containers.BaseContainer.invokeTargetBeanMethod(BaseContainer.java:4038)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5223)
答案 0 :(得分:24)
我认为你错过了JPA的观点。使用JPA,您不应该编写查询来插入,更新或删除持久对象,JPA将为您生成它们。 因此,您需要做的是创建域对象并对其进行注释以使其“可持久化”(此类带注释的对象称为实体)并告诉JPA引擎如何将它们“映射”到您的数据库。让我试着向你展示正确的道路......
首先,创建一个Voter
域对象并添加JPA注释(实体类必须使用Entity
注释进行注释,必须具有无参数构造函数,必须实现Serializable
,必须有Id
注释标识的主键:
@Entity
public class Voter implements Serializable {
private Long id;
private String firstName;
private String lastName;
private String password;
// other attributes
// No-arg constructor
public Voter() {}
@Id @GeneratedValue // property access is used
public Long getId() { return this.id; }
protected void setId(Long id) { this.id = id; }
// other getters, setters, equals, hashCode
}
我在这里使用JPA的默认值(默认表名,列名等)。但是,如果您需要将实体映射到现有模型,可以使用Table
或Column
注释对此进行自定义。
然后,创建一个新实例并设置各种属性:
Voter voter = new Voter();
voter.setFirstName(firstName);
voter.setLastName(lastName);
...
坚持下去:
em.getTransaction().begin();
em.persist(voter);
em.getTransaction().commit();
这只是一个简短的介绍,JPA不能在一个答案中涵盖。为了更进一步,我建议从Java EE 5教程中查看Introduction to the Java Persistence API。
更新:在托管组件(例如EJB)中,通常会注入EntityManager
并且事务由容器管理(即您没有显式调用begin/commit
})。在您的情况下,我的赌注是EntityManager
未成功注入并且调用其上的任何方法会导致NPE。但这只是猜测,你需要提供更多细节。 EJB的第39行是什么? EntityManager
如何注释?你的persistence.xml
看起来像什么?请使用相关详细信息更新您的问题。
答案 1 :(得分:2)
此外,您不需要再次编写开始和提交事务。就像这样:
em.getTransaction().begin();
em.getTransaction().commit();
如果您只使用容器管理的实体管理器,因为它是由容器自动完成的。
答案 2 :(得分:1)
我想它不会从构造函数中插入的参数中检索导致NullPointerExpception的值。如果你使用voter.setPassword(密码)会更好;例如,将值传入Voter实体。还要检查值是否为空。
答案 3 :(得分:1)
编写一个方法,该方法将设置值并使用它。
Query q = em.createNamedQuery("NamedQueryXYZ").setParameter("parameter name", valueToSet)
参数名称将使用您的示例“password”或“attribute”,基本上是冒号之后的任何内容。
我对JPA,JSF以及所有爵士乐都很陌生,但我希望这会有所帮助。
答案 4 :(得分:1)
如果您使用实体管理器意味着您使用JTA处理事务,那么实体管理器将由容器处理,您将无法使用
em.getTransaction().begin();
em.getTransaction().commit();
em.getTransaction()
这是一个由JTA处理的实体交易。
您需要直接使用persist()
,因为您拥有实体管理员,并且您将添加数据。
如果你想使用查询,它总是可以在en.createQuery中... 但我不知道它是否可以用作命名查询。