getGeneratedKeys returns 一个空的结果集

getGeneratedKeys returns an empty ResultSet

一句话:Statement.getGeneratedKeys() 偶尔会返回一个空的 ResultSet,我正在尝试找出原因。

背景:我正在跟踪用户关于订单和他们的一些物品的请求。我有两个表,称它们为 HeaderDetail。为了 link header 和详细信息正确,Header 有一个名为 request_idSERIAL 列,我在将行插入 Detail 时使用它。这已经运行了很长时间(据我所知),但最近我注意到 有时 getGeneratedKeys() 返回的 ResultSet 是空的。

为澄清起见,这里是代码(出于安全考虑删除了识别细节):

String hdrSql = "insert into Header "
    + "(request_id, order_id, user_id) values (0, ?, ?)";
String dtlSql = "insert into Detail "
    + "(request_id, order_id, line_no, comment) values (?, ?, ?, ?)";
PreparedStatement header = null, details = null;
int rows = 0;
long orderId = request.getOrderId();    // request is an object parameter
try {
    header = connection.prepareStatement(hdrSql, Statement.RETURN_GENERATED_KEYS);
    header.setAutoCommit(false);
    header.setLong(1, orderID);
    header.setString(2, request.getUserId());
    rows = header.executeUpdate();
    ResultSet rs = header.getGeneratedKeys();
    if (!rs.next()) {
        log("Could not get next request_id");   // This statement logged.
        return false;                       // But no exception thrown.
    }
    int requestId = rs.getInt("request_id");

    details = connection.prepareStatement(dtlSql);
    details.setInt(1, requestId);
    details.setLong(2, orderId);
    for (Item item : request.getItems()) {
        details.setInt(3, item.getLineNumber());
        details.setString(4, item.getComment());
        rows += details.executeUpdate();
    }
    // Should have inserted 1 row for header, plus 1 row for each item
    return rowsInserted == request.getItems().size() + 1;
} catch (SQLException sqle) {
    log("Database error" + sqle.getMessage());
    throw sqle;
} finally {
    try {       // Commit or roll back, depending on status:
        if (rows == request.getItems().size() + 1) {
            header.commit();
        } else {
            header.rollback();
            log("Rolled back request");     // This gets logged, too.
        }
        if (header != null) header.close();
        if (details != null) details.close();
    } catch (SQLException sqle) { sqle.printStackTrace(); }

再次,一年多来一直工作良好,但我发现 - 在同一天 - 一些成功但大部分失败。第二天又开始工作,没有一次失败,也没有任何异常。

希望有人能帮忙解释一下。如果它有什么不同,我正在通过 JDBC.

与 Informix 数据库交谈

我将这个问题发布到 IIUG,我得到的回复指出了 Informix (APAR IC98247) 中的一个错误,该错误已在比我使用的版本晚的版本中修复。

我现在正在尝试的解决方案,是一位处于同样困境的朋友推荐的,是从刚插入的行中读取 request_id 的变体

SELECT max(request_id) from Header where order_id = ${orderId} ;
// Avoid race condition, accidentally reading the last row inserted by
//  another thread.

这似乎对他有用。