2012-07-12 33 views
0

可能是一个新手Java的东西,但它在这里。使用JPA调用INSERT存储过程到Oracle 11g数据库。在将数据传送到数据库表格方面,一切正常。Java Swing/JPA/Oracle插入两次

我已经将JPA代码包装到Java Swing应用程序中。我的问题是数据不知何故被提交两次。我提交数据时显示JOptionPane.showMessageDialog。那只显示一次。但是当我查询表时,表中有两个条目。这里是我的代码....

按钮代码

JButton btnSubmit = new JButton("Submit"); 
btnSubmit.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent arg0) { 
     AddNewCustomer(); 
    } 
}); 
btnSubmit.setBounds(24, 341, 91, 23); 
frmNewCustomer.getContentPane().add(btnSubmit); 

操作方法

public void AddNewCustomer() { 
    Customer.AddCustomer(this.txtFirstName.getText(), 
      this.txtLastName.getText(), this.txtAddress.getText(), 
      this.txtCity.getText(), this.txtState.getText(), 
      this.txtEmail.getText(), this.txtPhone.getText()); 

    JOptionPane.showMessageDialog(frmNewCustomer, "Added new customer", 
      "Status", 1); 
} 

protected static void AddCustomer(String sFirstName, String sLastName, 
     String sAddress, String sCity, String sState, String sEmail, 
     String sPhone) { 
    try { 
     factory = Persistence 
       .createEntityManagerFactory(PERSISTENCE_UNIT_NAME); 
     EntityManager em = factory.createEntityManager(); 
     em.getTransaction().begin(); 

     Query q = em.createNamedQuery("AddCustomer"); 
     q.setParameter("p_PHONE", sPhone); 
     q.setParameter("p_STATE", sState); 
     q.setParameter("p_FIRST_NAME", sFirstName); 
     q.setParameter("p_ADDRESS", sAddress); 
     q.setParameter("p_EMAIL", sEmail); 
     q.setParameter("p_CITY", sCity); 
     q.setParameter("p_LAST_NAME", sLastName); 
     int r = q.executeUpdate(); 
     em.getTransaction().commit(); 

     List results = q.getResultList(); 
     if (results != null) { 
      Object id = results.get(0); 
      if (id != null) { 
       System.out.println(id.toString()); 
      } 
     } 
     em.close(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
+0

如果你所删除'列出结果= q.getResultList();'(及以下几行)? – 2012-07-12 09:35:02

+0

我这样做的共振是从Insert SPROC中获取新创建的ID和OUT参数。 SPROC有一个Sequence.nextVal的触发器。 – Beachdog 2012-07-12 16:45:38

回答

0

您需要删除调用getResultList(),这是执行相同的查询再次(它是一个插入查询,而不是选择查询)。无论如何您都不需要获取ID,请参阅this question。您根本不需要使用查询,但是因为创建条目的适当方式应该使用entityManager.persist(obj)(假设您有一个JPA实体,因此您应该使用JPA实体)。

+0

该问题提到用于执行插入操作的存储过程,这可能是使用命名查询的原因。 – 2012-07-12 09:56:06

+0

啊。不过,他不需要执行两次插入查询。您需要创建第二个查询并进行选择,但这不会轻易保证您在多线程环境中获得正确的对象。根据存储过程的不同,可能需要用触发器代替它,并按照打算使用的方式使用JPA。 – Thor84no 2012-07-12 10:04:30

+0

几乎偏离主题:为了在多用户/多线程环境中保持安全,第二个查询必须在与第一个相同的事务中执行并使用正确的隔离级别。但在这种情况下,似乎最好只是将其忽略掉。完全偏离主题:我仍然希望有一天能够更好地支持Java ORM中的存储过程。我不是他们的粉丝,但(通常是出于我无法控制的原因),我一直在其他项目上打他们。 – 2012-07-12 12:49:32

0

我解决了这个问题。更改代码....

protected static void AddCustomer(String sFirstName,String sLastName, String sAddress, String sCity, String sState,String sEmail,String sPhone) 
{ 

    try { 
     factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME); 
     EntityManager em = factory.createEntityManager(); 
     em.getTransaction().begin(); 

     Query q = em.createNamedQuery("AddCustomer"); 
     q.setParameter("p_PHONE", sPhone); 
     q.setParameter("p_STATE", sState); 
     q.setParameter("p_FIRST_NAME", sFirstName); 
     q.setParameter("p_ADDRESS", sAddress); 
     q.setParameter("p_EMAIL", sEmail); 
     q.setParameter("p_CITY", sCity); 
     q.setParameter("p_LAST_NAME", sLastName); 
     //int r = q.executeUpdate();     
     //em.getTransaction().commit(); 

     List results = q.getResultList(); 
     if(results != null) 
     {   
      Object id = results.get(0); 
      if(id != null) 
      { 
       System.out.println(id.toString()); 
      } 
      em.getTransaction().commit(); 
     } 
     em.close(); 
    } catch (Exception e) { 

     e.printStackTrace(); 
    } 

} 
+0

请将您的答案标记为解决方案,谢谢。 – CSchulz 2012-07-13 08:52:30