【问题标题】:Data does not get inserted into the table sometime数据有时不会插入到表中
【发布时间】:2012-06-08 22:08:55
【问题描述】:

我有一个表 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 = ?) ";

【问题讨论】:

    标签: java sql jdbc struts oracle11g


    【解决方案1】:

    看起来您插入的不是普通值,而是基于参数的选择结果。 您使用的是INSERT ... SELECT () 子句,因此如果SELECT 部分不返回任何行,则INSERT 不会插入任何内容,stmt.executeUpdate() 将返回0。找出SELECT 不返回任何行的原因。

    这可能是因为当您对rpt_audit_transportation 执行插入操作时,某些触发器会在其他表中保存内容,但这只是猜测。

    【讨论】:

    • 只有在这些其他表中成功保存数据后,才会调用上述方法(writeToAudit())。所以我们没有违反其他表中的任何约束。从表面上看,数据出现在这些其他表中,只是不在 rpt_audit_transportation 表中。
    • 在这种情况下:您确定总是调用writeToAudit() 吗?可能是你的java代码有bug,导致这个方法没有被调用?
    • 是的,它总是被调用。我设置了断点来确保这一点。 stmt.executeUpdate();未插入数据时返回 0,插入时返回 1。
    【解决方案2】:

    问题是您有一个 catch 正在吞噬您的异常

    catch (Exception e) {
    }
    

    这意味着当 SQL 语句引发错误时,您是在告诉您的代码捕获异常并忽略它。这样做几乎总是一个错误,因为正如您所发现的那样,这意味着您的代码可能无法执行您期望的操作,而无法让您知道某事失败了。至少,您需要在某处记录异常。但是,一般来说,如果您无法修复导致异常的任何条件,则应该重新引发异常,或者根本不首先捕获它。

    我的猜测是第二次插入违反了表上定义的某些约束。但是由于您的代码正在捕获异常并将其丢弃,因此不会通知您存在违反约束的情况,您的代码也不会注意到违反了哪个约束。

    【讨论】:

    • 感谢您的回复。我在 catch 块中有一些语句。我没有包括它,因为我不想让这篇文章太长。我在 catch 块中放置了断点以检查它是否被击中。但它永远不会。就约束而言,我能在表上看到的唯一约束就是主键。
    • @javaStudent - 如果您想简化您发布的代码,最好完全删除异常处理程序。如果您在调试器中单步执行代码,int temp = stmt.executeUpdate(); 是否会再次执行?如果是这样,temp 显示您被插入了多少行?
    • 当数据出现在我的表中时,temp 显示为 1,否则为 0。
    • 正如我在回答中所写 - 您使用的是 INSERT ... SELECT (),因此如果 SELECT 部分未返回任何行,则 INSERT 将不会插入任何内容。找出SELECT 不返回任何行的原因。
    • @npe 我检查了插入语句的选择部分是否返回任何内容并且它确实返回了一行数据。
    【解决方案3】:
    1. cntrct_no 相同时,您会遇到异常,并且您正在抑制@Justin Cave 所说的那样。这可能是因为您对该字段具有唯一约束,并且数据库抛出错误并且您正在抑制。

    2. cntrct_no 更改时 - 显然约束不会失败,而且对于主键,因为您使用的是序列,它会生成下一个数字,并且很高兴将其插入数据库中。

      李>

    永远不要抑制异常。在该块中做一些事情,要么重新抛出应用程序特定的异常,要么转换为错误代码并将其传播到前端。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多