使用Prepared Statement插入Java DB Compound Key会产生错误

时间:2014-10-27 10:56:23

标签: java sql prepared-statement javadb

我在java db,Alumnus和Certificate中有两个表,它们之间有多对多的关系。所以我介绍了第三个表ALUMNUS_HAS_CERTIFICATE来维护两个表和新的第三个表之间的一对多关系。第三个复合键由原始表的主键组成。我的问题是 我无法使用预准备语句将带有一个重复键的数据插入到第三个表中。 注意:第三个表有一个复合键。

下面的

是表的SQL代码。

 CREATE TABLE ALUMNUS (

ALUMNUS_ID INT NOT NULL PRIMARY KEY 
 GENERATED ALWAYS AS IDENTITY 
 (START WITH 1 , INCREMENT BY 1),
 ALUMNUS_NO INT UNIQUE,  
 FIRST_NAME VARCHAR (45) ,
 LAST_NAME VARCHAR (45) ,
 OTHER_NAME VARCHAR (100),
 RESIDENTIAL_ADDRESS VARCHAR (300),
 MAILING_ADDRESS VARCHAR (300),
 EMAIL VARCHAR (120) ,
 TELEPHONE VARCHAR (25),
 EMPLOYEED BOOLEAN NOT NULL DEFAULT FALSE,
 JOB_TITLE VARCHAR (200),
 EMPLOYER_NAME VARCHAR(120),
 EMPLOYER_ADDRESS VARCHAR (300)

 );

CREATE TABLE CERTIFICATE (
 CERT_ID INT NOT NULL PRIMARY KEY
 GENERATED ALWAYS AS IDENTITY (START WITH 1 , INCREMENT BY 1),
 CERTIFICATE VARCHAR (300) UNIQUE NOT NULL 
);


 CREATE TABLE ALUMNUS_HAS_CERT (
  ALUMNUS_CK INT NOT NULL,
  CERT_CK INT NOT NULL,
  YEAR_GRADUATED SMALLINT
 );


   --CONSTRAINTS

  ALTER TABLE ALUMNUS_HAS_CERT ADD CONSTRAINT Alumnus_Has_Cert_Compound_Key PRIMARY KEY    
  (ALUMNUS_CK,CERT_CK);


  ALTER TABLE APP.ALUMNUS_HAS_CERT 
   ADD FOREIGN KEY (ALUMNUS_CK)
   REFERENCES APP.ALUMNUS(ALUMNUS_ID) ON DELETE CASCADE;

   ALTER TABLE APP.ALUMNUS_HAS_CERT 
    ADD FOREIGN KEY (CERT_CK)
    REFERENCES APP.CERTIFICATE(CERT_ID) ON DELETE CASCADE;

sql string

 String alumnusHasCert = "INSERT INTO APP.ALUMNUS_HAS_CERT "
            + "(ALUMNUS_CK , CERT_CK ,YEAR_GRADUATED ) "
            + "VALUES ( ? , ? , ?)";

准备好的陈述的代码片段

    try (PreparedStatement stmAlumnusCert = con.prepareStatement(certUpdate) {
                                stmAlumnusCert.setInt(1, alumnusID);
                                stmAlumnusCert.setInt(2, certID);
                                stmAlumnusCert.setInt(3,year_graduated );
                                stmAlumnusCert.executeUpdate();
                            }

来自netbeans IDE的错误消息如下所示:

   IntegrityConstraintViolationException: The statement was aborted because it would have caused a
      duplicate key value in a unique or primary key constraint or unique index identified by
 'ALUMNUS_HAS_CERT_COMPOUND_KEY' defined on 'ALUMNUS_HAS_CERT'.

at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(Unknown Source) at
 org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.TransactionResourceImpl.handleException(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.handleException(Unknown Source)
at org.apache.derby.impl.jdbc.ConnectionChild.handleException(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeStatement(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeLargeUpdate(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeUpdate(Unknown Source)
at wa_poly.UpdateData.update(UpdateData.java:192)
at wa_poly.MyJFrame.update(MyJFrame.java:1067)
at wa_poly.MyJFrame.updateButtonActionPerformed(MyJFrame.java:762)
at wa_poly.MyJFrame.access$1300(MyJFrame.java:65)
at wa_poly.MyJFrame$14.actionPerformed(MyJFrame.java:528)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2346)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6527)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6292)
at java.awt.Container.processEvent(Container.java:2234)
at java.awt.Component.dispatchEventImpl(Component.java:4883)
at java.awt.Container.dispatchEventImpl(Container.java:2292)
at java.awt.Component.dispatchEvent(Component.java:4705)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4898)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4533)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4462)
at java.awt.Container.dispatchEventImpl(Container.java:2278)
at java.awt.Window.dispatchEventImpl(Window.java:2739)
at java.awt.Component.dispatchEvent(Component.java:4705)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:746)
at java.awt.EventQueue.access$400(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:697)
at java.awt.EventQueue$3.run(EventQueue.java:691)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.awt.EventQueue$4.run(EventQueue.java:719)
at java.awt.EventQueue$4.run(EventQueue.java:717)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:716)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Suppressed: java.sql.SQLException: Cannot close a connection while a transaction is still active.
    at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(Unknown Source)
    at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Unknown Source)
    at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Unknown Source)
    at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
    at org.apache.derby.impl.jdbc.EmbedConnection.newSQLException(Unknown Source)
    at org.apache.derby.impl.jdbc.EmbedConnection.checkForTransactionInProgress(Unknown Source)
    at org.apache.derby.impl.jdbc.EmbedConnection.close(Unknown Source)
    at wa_poly.UpdateData.update(UpdateData.java:212)
    ... 40 more
   Caused by: java.sql.SQLException: Cannot close a connection while a transaction is still 

    active.
    at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
    at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(Unknown 
    Source)
    ... 48 more
   Caused by: java.sql.SQLException: The statement was aborted because it would have caused a
  duplicate key value in a unique or primary key constraint or unique index identified by 
 'ALUMNUS_HAS_CERT_COMPOUND_KEY' defined on 'ALUMNUS_HAS_CERT'.
at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(Unknown Source)
... 51 more

  Caused by: ERROR 23505: The statement was aborted because it would have caused a duplicate key
  value in a unique or primary key constraint or unique index identified by
  'ALUMNUS_HAS_CERT_COMPOUND_KEY' defined on 'ALUMNUS_HAS_CERT'.
at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
at org.apache.derby.impl.sql.execute.IndexChanger.insertAndCheckDups(Unknown Source)
at org.apache.derby.impl.sql.execute.IndexChanger.doInsert(Unknown Source)
at org.apache.derby.impl.sql.execute.IndexChanger.insert(Unknown Source)
at org.apache.derby.impl.sql.execute.IndexSetChanger.insert(Unknown Source)
at org.apache.derby.impl.sql.execute.RowChangerImpl.insertRow(Unknown Source)
at org.apache.derby.impl.sql.execute.InsertResultSet.normalInsertCore(Unknown Source)
at org.apache.derby.impl.sql.execute.InsertResultSet.open(Unknown Source)
at org.apache.derby.impl.sql.GenericPreparedStatement.executeStmt(Unknown Source)
at org.apache.derby.impl.sql.GenericPreparedStatement.execute(Unknown Source)
... 45 more

1 个答案:

答案 0 :(得分:0)

预准备语句中的参数顺序应与SQL语句中的顺序相同:

String certUpdate = "UPDATE APP.ALUMNUS_HAS_CERT "
        + "SET YEAR_GRADUATED = ? " //1 
        + "WHERE ALUMNUS_CK = ? AND CERT_CK = ? "; //2 and 3 



try (PreparedStatement stmAlumnusCert = con.prepareStatement(certUpdate) {

                            stmAlumnusCert.setInt(1,year_graduated); 
                            stmAlumnusCert.setInt(2, certID);
                            stmAlumnusCert.setInt(3, alumnusID);                                                                                stmAlumnusCert.executeUpdate();
           }

错误的订单可能会在您的表格中创建一个重复的复合键。

PS:问题已更新,此答案不适用。