2012-06-04 60 views
0

我有一個表A.我通過用戶界面將數據插入到表A中。表A有一個使用序列生成的ID(主鍵)和16個其他列。其中一列稱爲cntrct_no。某些時候數據沒有插入到表中

當我嘗試通過UI向表中插入數據時,它在第一次正常工作。我檢查表A,所有數據都在那裏。

但是,當我嘗試再次插入相同的數據而沒有改變任何東西時,它看起來像數據被添加到表中,我沒有得到任何錯誤。但是當我檢查表A時,第二次插入的數據不存在。

如果我嘗試通過SQL開發人員直接插入相同的數據,則會將數據插入表中。

奇怪的是,如果我只是在UI中更改cntrct_no的值,並保留其餘數據,數據就會被插入。

任何人都可以請向我解釋什麼可能導致此?

不知道這是否有幫助:stmt.executeUpdate();數據未插入時返回0,插入時返回1。

public void writeToAudit(String contractNo, String tripNo, 
     String tripEffDate, 
     String tripDiscDate, String transpModeId, String userId, 
     String transType, AplLeg[] legs) { 

    final Session session = HibernateUtil.getSession(); 
    Connection con = null; 
    con = session.connection(); 
    PreparedStatement stmt = null; 
    PreparedStatement stmtSelId = null; 
    ResultSet rs = null; 
    long nextId = -1; 
    int i=0; 

    try { 

     for(i=0;i<legs.length;i++) { 

      String sqlNextId = "SELECT rpt_audit_transportation_seq.NEXTVAL as seqval FROM DUAL"; 
      stmtSelId = con.prepareStatement(sqlNextId, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); 
      rs = stmtSelId.executeQuery(); 
      rs.last(); 
      final int rows = rs.getRow(); 
      if (rows == 0){ 
       nextId = -1; 
      } 
      rs.beforeFirst(); 
      rs.next(); 
      nextId = rs.getInt(1); 

      if(nextId==-1) 
       throw new SQLException("Cannot get next val from rpt_audit_transportation sequence."); 

      stmt = con.prepareStatement(WRITE_TO_AUDIT_DML); 
      stmt.setLong(1, nextId); 
      stmt.setString(2, userId.toUpperCase()); 
      stmt.setString(3, transType); 
      stmt.setString(4, contractNo); 
      stmt.setString(5, tripNo); 
      stmt.setInt(6, Integer.parseInt(transpModeId)); 
      stmt.setString(7, tripEffDate); 
      stmt.setString(8, tripDiscDate); 
      stmt.setLong(9, legs[i].getLegId().longValue()); 
      int temp = stmt.executeUpdate(); 
      con.commit(); 
     } 

     stmt.close(); 
    } 
    catch (Exception e) { 
    } 
    finally { 
     closeConnection(session, con, stmtSelId, rs); 
    } 
} 

的SQL語句:

private static final String WRITE_TO_AUDIT_DML = 
    "INSERT INTO rpt_audit_transportation " + 
    "(audit_id, audit_date, audit_process, audit_userid, " + 
    "audit_trans_type, audit_route_no, audit_trip_no, " + 
    "audit_eff_dt, audit_disc_dt, audit_orig_facility_id, " + 
    "audit_dest_facility_id, audit_arvl_tm, audit_dprt_tm, " + 
    "audit_leg_seq_no, audit_freq_id, audit_trnsp_mode_id) " + 
    "(SELECT ?, " +  // audit id 
     "SYSDATE, " + 
     "'TOPS_UI', " + 
     "?, " +  // userId 
     "?, " + 
     "rte.cntrct_no, " + 
     "trp.trip_no, " + 
     "rte.cntrct_eff_dt, " + 
     "rte.cntrct_disc_dt, " + 
     "NVL(leg.orig_facility_id, trp.orig_fac_id), " + 
     "NVL(leg.dest_facility_id, trp.dest_fac_id), " + 
     "NVL(leg.arvl_tm, trp.arvl_tm), " + 
     "NVL(leg.dprt_tm, trp.dprt_tm), " + 
     "leg.leg_seq, " + 
     "trp.freq_id, " + 
     "rte.trnsp_mode_id " + 
     "FROM apl_contract rte, " + 
     "apl_trip trp, " + 
     "apl_leg leg " + 
     "WHERE rte.cntrct_no = ? " +  // contract id 
      "AND trp.trip_no = ? " +   // trip no 
      "AND rte.trnsp_mode_id = ? " +  // transp mode id 
      "AND rte.cntrct_locked_ind = 'N' " + 
      "AND trp.trip_eff_dt = to_date(?,'MM/DD/YYYY') " +   // trip eff date 
      "AND trp.trip_disc_dt = to_date(?,'MM/DD/YYYY') " +   // trip disc date 
      "AND trp.cntrct_id = rte.cntrct_id " + 
      "AND leg.trip_id = trp.trip_id " + 
      "AND leg.leg_id = ?) "; 

回答

2

你看上去不插入普通的值,但是基於參數選擇的結果。 您使用的是INSERT ... SELECT()子句,因此如果SELECT部分沒有返回任何行,INSERT將不會插入任何內容,而stmt.executeUpdate()將返回0。找出爲什麼SELECT不返回任何行。

這可能是由於某些觸發器在您插入rpt_audit_transportation時將其他表格中的內容保存在其他表格中,但這只是一種猜測。

+0

只有在數據成功保存在這些其他表中之後,才調用上述方法(writeToAudit())。所以我們沒有違反其他表中的任何限制。問題是,數據出現在這些其他表中,而不是在rpt_audit_transportation表中。 – Susie

+0

在這種情況下:你確定,總是調用'writeToAudit()'?也許這是你的java代碼中的一個錯誤,導致這個方法不被調用? – npe

+0

是的,它總是被調用。我提出了斷點來確保這一點。 stmt.executeUpdate();數據未插入時返回0,插入時返回1。 – Susie

2

的問題是,你有一個catch被吞噬你的異常

catch (Exception e) { 
} 

這意味着,當SQL語句拋出一個錯誤,你告訴你的代碼捕獲異常而忽略它。這樣做幾乎總是一個錯誤,因爲正如你所發現的那樣,這意味着你的代碼可能無法做到你所期望的,而無法讓你知道失敗的東西。至少,您需要在某處記錄異常。但是,一般來說,如果你無法解決導致異常的任何情況,你應該重新提出異常,或者根本不把它放在第一位。

我的猜測是第二次插入違反了表上定義的一些約束。但是,由於你的代碼捕捉異常並將其拋出,所以你沒有被通知有違反約束,你的代碼也沒有注意到違反了哪個約束。

+0

感謝您的回覆。我在catch塊中有一些聲明。我沒有包括它,因爲我不想讓這篇文章太長。我在catch塊中放置了一個斷點來檢查它是否被擊中。但它從來沒有。就約束而言,我能在桌面上看到的唯一約束就是主鍵。 – Susie

+0

@javaStudent - 如果你想簡化你發佈的代碼,你可能會更好地完全移除異常處理程序。如果你在調試器中遍歷代碼,'int temp = stmt.executeUpdate();'會再次執行嗎?如果是這樣,那麼'temp'顯示你插入了多少行? –

+0

當數據顯示在我的表中時temp顯示1,當它不顯示時顯示0。 – Susie

1
  1. cntrct_no一樣你得到一個例外,你是supperessing通過@Justin洞所講述。這可能是因爲你對該字段有一個唯一的約束,並且數據庫會引發一個錯誤,並且你正在壓制。

  2. cntrct_no改變 - 顯然約束不會失敗,主鍵,因爲你正在使用的序列它會產生下一個號碼,並愉快地被插入到數據庫中。

千萬不要壓制異常。在該塊中做一些事情或者重新拋出特定於應用程序的異常,或者將其轉換爲錯誤代碼並將其傳播到前端。

相關問題