一、结论
首先给出结论:
query(String sql, RowMapper rowMapper) 可以返回一组记录
queryForObject(String sql, RowMapper rowMapper, Object… args) 只返回一条记录,因此一般用于聚合函数的查询
@Override
public List<User> findAll() {
//1.定义sql
String sql = "select * from user";
// BeanPropertyRowMapper:它可自动将一行数据映射到指定类的实例中,它首先将这个类实例化,然后通过名称匹配的方式,映射到属性中去
List<User> users = template.query(sql, new BeanPropertyRowMapper<User>(User.class));
return users; // 返回了 List 这个集合
}
@Override
public User findUserByUsernameAndPassword(String username, String password) {
//如果这里不加 try..catch,查询后封装成 user 对象,如果没有找到这个user对象,则会报:
/*org.springframework.dao.EmptyResultDataAccessException:Incorrect result size:excepted 1,actual 0*/
// 期望查询到1个对象,真正查询到的是0个对象,让它不报这个异常,则加 try..catch
try {
String sql = "select * from user where username = ? and password = ?";
User user = template.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), username, password);
return user;
} catch (DataAccessException e) {
e.printStackTrace(); // 一般这里记录日志,不会用来打印异常
return null;
}
}
到这里,也许你仍然不知道为什么 query 返回一组记录,queryForObject 只返回一条记录,下面我们看看源码吧。
二、queryForObject源码
1)queryForObject 将查询结果存放到 List 集合,返回前调用了 requiredSingleResult(results)
2)这个方法保证返回的数据只有一条,如:这里是查询User对象的方法,那么该方法就只会返回一个封装好的User对象;然后将迭代器的指针往下移一位,方便用户去取数据 。
size == 0:抛出空结果集异常
size > 1:抛出不正确的结果集长度异常
size == 1:返回一条记录,让迭代器的指针指向下一位
三、query源码
可以看到 query 的源码就非常简单了,它直接返回的是查询结果的 List 集合,返回了一组记录。