【问题标题】:Java Swing / JPA / Oracle inserting twiceJava Swing / JPA / Oracle 插入两次
【发布时间】:2012-07-12 09:29:15
【问题描述】:

可能是一个 Java 新手……但它就是这样。使用 JPA 调用 Oracle 11g 数据库的 INSERT 存储过程。就将数据获取到数据库表而言,一切正常。

我已将 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();
    }
}

【问题讨论】:

  • 如果删除List results = q.getResultList();(以及以下行)会怎样?
  • 我这样做的原因是从插入 SPROC 中获取新创建的 ID 和 OUT 参数。 SPROC 有一个执行 Sequence.nextVal 的触发器。

标签: java


【解决方案1】:

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

【讨论】:

  • 问题中提到了用于插入的存储过程,这可能是使用命名查询的原因。
  • 啊。尽管如此,他不需要执行两次插入查询。您需要创建第二个查询并进行选择,尽管这不能轻易保证您在多线程环境中获得正确的对象。根据存储过程的作用,可能需要将其替换为触发器,并以预期的方式使用 JPA。
  • 几乎跑题了:为了在多用户/多线程环境中保持安全,第二个查询必须在与第一个事务相同的事务中执行,并使用正确的隔离级别。但在这种情况下,似乎最好把它排除在外。完全题外话:我仍然希望有一天能够更好地支持 Java ORM 中的存储过程。我不是他们的粉丝,但是(通常是出于我无法控制的原因)我在其他每个项目中都不断地打击他们。
  • 好的...从您提供的链接中,它建议使用@GeneratedValue 在表中生成一个ID,对吗?我特别排除了这一点,因为我有一个使用 Sequence.nextVal 的触发器,它工作正常。我使用 q.getResultList() 从包含新创建的 ID 的存储过程中获取 OUT 参数。存储的 Proc 返回 Sequence.currval
【解决方案2】:

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

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();
    }

}

【讨论】:

    猜你喜欢
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-14
    • 2013-12-21
    • 1970-01-01
    相关资源
    最近更新 更多