jdbcTemplate的queryForXXX方法抛出异常解决

分类: Spring 0人评论 selfly 1年前发布

工具包的通用dao中,封装了一个获取大字段blob的方法,初始代码如下:

String sql = String.format(tmp_sql, columnName, tableName, primaryName);
return (byte[]) jdbcTemplate.queryForObject(sql, new Object[] { id },
    new RowMapper() {
        @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 requiredSingleResult(Collection 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() {
    @Override
    public byte[] extractData(ResultSet rs) throws SQLException, DataAccessException {
        if (rs.next()) {
            return rs.getBytes(1);
        }
        return null;
    }
});

再次运行,在记录不存在时将返回null,而不会再抛出异常,问题解决!