问题
In one sentence: Statement.getGeneratedKeys()
is occasionally returning an empty ResultSet
, and I'm trying to figure out why.
Background: I am keeping track of users' requests regarding orders and some of their items. I have two tables, call them Header
and Detail
. To link the header and details properly, Header
has a SERIAL
column named request_id
, which I use when inserting rows into Detail
. This has been working fine for a long time (as far as I know), but recently I noticed that sometimes, the ResultSet
returned by getGeneratedKeys()
is empty.
To clarify, here is the code (identifying details removed for security):
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(); }
Again, been working fine for more than a year, but I found - on the same day - some successes but mostly failures. Worked again the next day, with nary a single failure, and no exceptions at all.
I'm hoping someone can help explain. If it makes any difference, I'm talking to an Informix database over JDBC.
回答1:
I posted this question to IIUG, and the response I got there pointed to a bug in Informix (APAR IC98247), fixed in a version later than the one I am using.
The solution I'm trying now, recommended by a friend in the same predicament, is to read the request_id
from the row just inserted by variation of
SELECT max(request_id) from Header where order_id = ${orderId} ;
// Avoid race condition, accidentally reading the last row inserted by
// another thread.
This seems to have worked for him.
来源:https://stackoverflow.com/questions/32447602/getgeneratedkeys-returns-an-empty-resultset