工具包的通用dao中,封装了一个获取大字段blob的方法,初始代码如下:
String sql = String.format(tmp_sql, columnName, tableName, primaryName); return (byte[]) jdbcTemplate.queryForObject(sql, new Object[] { id }, new RowMapper<Object>() { @Override public Object mapRow(ResultSet rs, int i) throws SQLException { Blob blob = rs.getBlob(1); if (blob == null) { return null; } return blob.getBytes(1, (int) blob.length()); } });
平时使用都没问题,今天在使用它迁移大批量数据时,后台突然抛出异常:
org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0
导致迁移任务终止。
定位问题,发现抛出异常的是jdbcTemplate.queryForObject()方法,查看源代码,发现它在得到结果后还调用了DataAccessUtils.requiredSingleResult(results)方法来检查数据,代码如下:
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(); }
没错,当返回记录为空或多于一条时,就会抛出异常,而我碰到的情况是那条记录不存在。
在这里也挺奇怪没有记录时spring为什么不返回null而要抛出异常呢?
将查询blob的方法修改成下面的代码:
String sql = String.format(tmp_sql, columnName, tableName, primaryName); return jdbcTemplate.query(sql, new Object[] { id }, new ResultSetExtractor<byte[]>() { @Override public byte[] extractData(ResultSet rs) throws SQLException, DataAccessException { if (rs.next()) { return rs.getBytes(1); } return null; } });
再次运行,在记录不存在时将返回null,而不会再抛出异常,问题解决!