我有一个表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 = ?) ";
答案 0 :(得分:2)
看起来您没有插入普通值,而是基于参数选择的结果。
您使用的是INSERT ... SELECT ()
子句,因此如果SELECT
部分未返回任何行,INSERT
将不会插入任何内容,stmt.executeUpdate()
将返回{{ 1}}。找出0
没有返回任何行的原因。
这可能是因为当您插入SELECT
时,某些触发器会在其他表中保存内容,但这只是猜测。
答案 1 :(得分:2)
问题是您有catch
吞噬了您的例外
catch (Exception e) {
}
这意味着当SQL语句抛出错误时,您告诉您的代码捕获异常并忽略它。这样做几乎总是一个错误,因为正如您所发现的那样,这意味着您的代码无法满足您的预期而无法让您知道某些内容失败。至少,您需要在某处记录异常。但是,一般情况下,如果你无法解决导致异常的任何条件,你应该重新提出异常,或者根本不抓住它。
我的猜测是第二个插入违反了表中定义的某些约束。但是,由于您的代码正在捕获异常并将其丢弃,因此您不会收到通知,表明存在约束违规,您的代码也没有注意到违反了哪个约束。
答案 2 :(得分:1)
当cntrct_no
相同时,你会得到一个例外,而你正如@Justin Cave所说的那样。这可能是因为您对该字段有一个唯一约束,并且数据库会抛出错误而您正在抑制。
当cntrct_no
被更改时 - 显然约束不会失败,对于主键,因为你使用序列它会生成下一个数字,并且很乐意插入到数据库中。
不要压制异常。在该块中做一些事情要么重新抛出作为特定于应用程序的异常,要么转换为错误代码并将其传播到前端。