通过JPA将记录插入数据库

时间:2010-04-24 00:05:44

标签: java jpa

在我的代码中,我正在使用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)

5 个答案:

答案 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的默认值(默认表名,列名等)。但是,如果您需要将实体映射到现有模型,可以使用TableColumn注释对此进行自定义。

然后,创建一个新实例并设置各种属性:

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中... 但我不知道它是否可以用作命名查询。

相关问题