Remove an ancient TODO: Get rid of SELECT FOR UPDATE and instead locklessly claim the next available primary key value.

This commit is contained in:
Par Winzell
2008-12-09 22:56:55 +00:00
parent 817857d20e
commit cc07817238
@@ -123,36 +123,51 @@ public class TableValueGenerator extends ValueGenerator
public int nextGeneratedValue (Connection conn, DatabaseLiaison liaison)
throws SQLException
{
PreparedStatement stmt = null;
PreparedStatement readStatement = null;
PreparedStatement writeStatement = null;
try {
// TODO: Make this lockless!
String query =
readStatement = conn.prepareStatement(
" SELECT " + liaison.columnSQL(_valueColumnName) +
" FROM " + liaison.tableSQL(_valueTable) +
" WHERE " + liaison.columnSQL(_pkColumnName) + " = ? FOR UPDATE";
stmt = conn.prepareStatement(query);
stmt.setString(1, _pkColumnValue);
" WHERE " + liaison.columnSQL(_pkColumnName) + " = ? ");
readStatement.setString(1, _pkColumnValue);
ResultSet rs = stmt.executeQuery();
if (!rs.next()) {
throw new SQLException("Failed to find next primary key value " +
"[table=" + _valueTable + ", column=" + _valueColumnName +
", where=" + _pkColumnName + "=" + _pkColumnValue + "]");
}
int val = rs.getInt(1);
JDBCUtil.close(stmt);
stmt = conn.prepareStatement(
writeStatement = conn.prepareStatement(
" UPDATE " + liaison.tableSQL(_valueTable) +
" SET " + liaison.columnSQL(_valueColumnName) + " = ? " +
" WHERE " + liaison.columnSQL(_pkColumnName) + " = ?");
stmt.setInt(1, val + _allocationSize);
stmt.setString(2, _pkColumnValue);
stmt.executeUpdate();
return val;
" WHERE " + liaison.columnSQL(_pkColumnName) + " = ? " +
" AND " + liaison.columnSQL(_valueColumnName) + " = ? ");
for (int tries = 0; tries < 10; tries ++) {
// execute the query
ResultSet rs = readStatement.executeQuery();
if (!rs.next()) {
throw new SQLException(
"Failed to find next primary key value [table=" + _valueTable +
", column=" + _valueColumnName + "]");
}
// fetch the next available value
int val = rs.getInt(1);
// claim this value locklessly
writeStatement.setInt(1, val + _allocationSize);
writeStatement.setString(2, _pkColumnValue);
writeStatement.setInt(3, val);
// if we modified a row, we know we and nobody else got this particular value!
if (writeStatement.executeUpdate() == 1) {
return val;
}
// else try again
}
throw new SQLException(
"Failed to claim next primary key value in 10 attempts [table=" + _valueTable +
", column=" + _valueColumnName + "]");
} finally {
JDBCUtil.close(stmt);
JDBCUtil.close(readStatement);
JDBCUtil.close(writeStatement);
}
}