0

テーブル A があります。ユーザー インターフェイスを介してテーブル A にデータを挿入します。テーブル A には、シーケンスを使用して生成された ID (主キー) と、その他の 16 の列があります。列の 1 つは cntrct_no と呼ばれます。

UI を介してテーブルにデータを挿入しようとすると、最初は正常に機能します。テーブルAを確認すると、すべてのデータがそこにあります。

しかし、何も変更せずに同じデータを再度挿入しようとすると、データがテーブルに追加されているように見え、エラーは発生しません。しかし、テーブルAを確認すると、2回目に挿入されたデータはありません。

同じデータを 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 = ?) ";
4

3 に答える 3

2

プレーンな値を挿入していないように見えますが、パラメーターに基づく選択の結果です。使用しているのはINSERT ... SELECT ()句であるため、そのSELECT部分が行を返さない場合、INSERTは何も挿入せず、stmt.executeUpdate()を返し0ます。SELECT行が返されない理由を調べてください。

これは、 への挿入を行うときに、他のテーブルに何かを保存するいくつかのトリガーが原因である可能性がありますがrpt_audit_transportation、それは単なる推測です。

于 2012-06-04T20:43:39.820 に答える
2

問題はcatch、例外を飲み込んでいる があることです

catch (Exception e) {
}

つまり、SQL ステートメントがエラーをスローした場合、例外をキャッチして無視するようにコードに指示していることになります。あなたが発見したように、何かが失敗したことを知らせる方法がなく、コードが期待どおりに動作しない可能性があることを意味するため、これを行うことはほとんどの場合エラーです。少なくとも、どこかに例外を記録する必要があります。ただし、一般に、例外の原因となる条件を修正できない場合は、例外を再発生させるか、そもそも例外をキャッチしないようにする必要があります。

私の推測では、2 番目の挿入は、テーブルで定義された制約に違反していると思われます。しかし、コードが例外をキャッチしてそれを破棄しているため、制約違反があったことは通知されず、どの制約が違反されたかをコードが通知することもありません。

于 2012-06-04T20:44:56.183 に答える
1
  1. 同じ場合cntrct_no、例外が発生し、@Justin Cave が語ったようにそれを抑制しています。これは、そのフィールドに一意の制約があり、DB がエラーをスローして抑制していることが原因である可能性があります。

  2. が変更された場合cntrct_no- 明らかに制約が失敗することはなく、主キーの場合、シーケンスを使用しているため、次の番号が生成され、DB に挿入されます。

例外を抑制しないでください。そのブロックで何らかの処理を行い、アプリケーション固有の例外として再スローするか、エラー コードに変換してフロント エンドに伝達します。

于 2012-06-04T20:55:59.010 に答える