@see https://blog.csdn.net/bbirdsky/article/details/8784434
@see https://blog.csdn.net/zhang41228/article/details/52799868
问题现象:
org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0
解决方法:
手动加上try...catch语句块,在catch块中return null,由于这是你业务逻辑代码,spring不会自做主张返回null,万一你没有处理呢?抛出将是空指针异常,反而误导开发者。因此,基于职责单一设计原则,spring抛出异常是合理的(jdbcTemplate的异常都是RuntimeException),它只是负责去查找数据,至于没有找到数据处理逻辑由用户完成。
如果不希望抛出此异常,而是返回为null。
查看源代码可知
- @Override
- public <T> T queryForObject(String sql, RowMapper<T> rowMapper) throws DataAccessException {
- List<T> results = query(sql, rowMapper);
- return DataAccessUtils.requiredSingleResult(results);
- }
源码中结果集返回调用了DataAccessUtils的一个静态方法,在这个静态方法中spring做了判断:
- 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();
- }
我们可以写一个类直接继承JdbcTemplate,重写queryForObject()方法,结果集==0的时候,return null;
- public class OverrideJdbc extends JdbcTemplate{
- /**
- * 重写JdbcTemplate里面的queryForObject方法源码调用的requiredSingleResult,当查询到的结果为空时返回null(原来是抛出异常)
- */
- @Override
- public <T> T queryForObject(String sql, Class<T> requiredType) throws DataAccessException {
- return queryForObject(sql, getSingleColumnRowMapper(requiredType));
- }
- public <T> T queryForObject(String sql, RowMapper<T> rowMapper) throws DataAccessException {
- List<T> results = query(sql, rowMapper);
- return requiredSingleResult(results);
- }
- public static <T> T requiredSingleResult(Collection<T> results) throws IncorrectResultSizeDataAccessException {
- int size = (results != null ? results.size() : 0);
- if (size == 0) {
- return null;
- }
- if (results.size() > 1) {
- throw new IncorrectResultSizeDataAccessException(1, size);
- }
- return results.iterator().next();
- }
- }
然后在spring的配置文件里为这个类OverrideJdbc 注入dataSource
【注意】如果你之前用了jdbcTemplate并且在spring配置文件里面注入了dataSource,你再注入一个就会报如下的错
你把jdbcTemplate的bean注释掉就行了,因为你写的OverrideJdbc继承的jdbcTemplate,它跟jdbcTemplate类型一样,所以你在用@AutoWired的时候只会识别一个bean,多了或者少了都会报错,我就是被这个纠结了一下午时间
- <!-- <bean id= "jdbcTemplate" class ="org.springframework.jdbc.core.JdbcTemplate">
- <property name= "dataSource" ref ="dataSource"></property>
- </bean> -->
- <!-- 配置spring jdbc -->
- <bean id="overrideJdbc" class="com.dao.OverrideJdbc">
- <property name= "dataSource" ref ="dataSource"></property>
- </bean>
配置好之后就可以使用了,当然,jdbcTemplate里面的其他方法也可以这样重写,看个人需求。