queryForObject()は、レコードが見つからないときEmptyResultDataAccessExceptionをスローします
レガシープロジェクトを見直し、このSpringのJDBCコードスニペットを見つけました:
public User getUser(String username) {
String sql = "SELECT ** FROM USER WHERE username = ?";
return getJdbcTemplate().queryForObject(
sql,
new Object[]{ username },
new RowMapper<UserAttempts>() {
public UserAttempts mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setAge(rs.getInt("age"));
user.setLastModified(rs.getDate("lastModified"));
return user;
}
});
}
問題
開発者は、レコードが見つからないときにnullを返すと仮定します。
User user = abc.getUser("mkyong");
if(user == null){
//...do something
}
問題は、レコードが見つからないときにnullを返す代わりに、Springが `EmptyResultDataAccessException`をスローしたことです。
JdbcTemplate .java
package org.springframework.jdbc.core;
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
//...
public <T> T queryForObject(String sql, Object[]args,
RowMapper<T> rowMapper) throws DataAccessException {
List<T> results = query(sql, args, new RowMapperResultSetExtractor<T>(rowMapper, 1));
return DataAccessUtils.requiredSingleResult(results);
}
DataAccessUtils.java
package org.springframework.dao.support;
public abstract class DataAccessUtils {
//...
public static <T> T requiredSingleResult(Collection<T> results)
throws IncorrectResultSizeDataAccessException {
int size = (results != null ? results.size() : 0);
if (size == 0) {
throw new EmptyResultDataAccessException(1);
}
if (results.size() > 1) {
throw new IncorrectResultSizeDataAccessException(1, size);
}
return results.iterator().next();
}
P.S Springバージョン3.2.8.RELEASE
解決策
nullを返すことはかなり標準的です。なぜSpringが `EmptyResultDataAccessException`をスローしたいのでしょうか?これを修正するには、例外をキャッチしてnullを返します。
public User getUser(String username) {
String sql = "SELECT ** FROM USER WHERE username = ?";
try {
User user = getJdbcTemplate().queryForObject(
sql,
new Object[]{ username },
new RowMapper<UserAttempts>() {
public UserAttempts mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setAge(rs.getInt("age"));
user.setLastModified(rs.getDate("lastModified"));
return user;
}
});
return user;
} catch (EmptyResultDataAccessException e) {
return null;
}
}