问题
I have the following method that I use with Spring JDBC
public String getState() {
String stateLink = template.queryForObject(
"select state_url from state_scrape_queue where in_use = false ORDER BY scrape_timestamp NULLS FIRST LIMIT 1",
(result, rowNum) -> {
return result.getString("state_url");
});
return stateLink;
}
I can't find an example of how to do a for update with Spring JDBC. I want in_use
to be set to true using for update.
I need to use select for update since this application will be used in a multi-threaded fashion. I don't want more than one thread to get the same row and the way to prevent that is by using select for update
I was able to do this with plain JDBC, here is the question I asked how to do it with plain JDBC
select "for update" with JDBC?
Anyone know how this would be done?
回答1:
This is what I came up with, feel free to recommend improvements
public String getState() throws SQLException {
String state = null;
Connection conn = DataSourceUtils.getConnection(template.getDataSource());
try {
conn.setAutoCommit(false);
String[] colNames = { "id", "state_url", "in_use" };
String query = "select " + Stream.of(colNames).collect(Collectors.joining(", "))
+ " from state_scrape_queue where in_use = false ORDER BY scrape_timestamp NULLS FIRST LIMIT 1 FOR UPDATE";
System.out.println(query);
try (Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery(query)) {
while (rs.next()) {
// Get the current values, if you need them.
state = rs.getString(colNames[1]);
rs.updateBoolean(colNames[2], true);
rs.updateRow();
conn.commit();
}
}
} catch (SQLException e) {
conn.setAutoCommit(true);
e.printStackTrace();
} finally {
conn.setAutoCommit(true);
}
return state;
}
来源:https://stackoverflow.com/questions/56350833/spring-jdbc-select-for-update