查询
JdbcTemplate 提供多种读取结果集的 API;方法名称并不会把连接或数据库操作强制设为只读。大多数接口接受 SQL 字符串和参数(对象或数组),返回由结果集构建的对象;部分接口支持回调/映射器以自定义处理过程。
先选方法
| 你的目标 | 推荐方法 |
|---|---|
| 查询多行 Bean 或 Map | queryForList |
| 查询单行 Bean | queryForObject |
| 查询单行 Map | queryForMap |
| 查询单个值,例如 count、sum | queryForLong、queryForObject |
| 查询两列并转成 Map | queryForPairs |
| 自定义每行如何映射 | RowMapper |
| 自定义整个 ResultSet 如何处理 | ResultSetExtractor |
| 大结果集逐行处理 | RowCallbackHandler 或流式查询 |
查询结果集
查询一个对象或 Map 集合并返回。
- 示例:使用 Bean 映射结果集
- 示例:使用 Map 映射结果集
- 函数签名
// 原始 SQL(独立示例)
{
List<User> users = jdbc.queryForList(
"select * from users where id > 2", User.class);
}
// 位置参数(独立示例)
{
Object[] args = new Object[]{ 2 };
List<User> result = jdbc.queryForList(
"select * from users where id > ?", args, User.class);
}
// 名称参数(独立示例)
{
Map<String, Object> namedArgs = CollectionUtils.asMap("id", 2);
List<User> result = jdbc.queryForList(
"select * from users where id > :id", namedArgs, User.class);
}
// 原始 SQL(独立示例)
{
List<Map<String, Object>> users = jdbc.queryForList(
"select * from users where id > 2");
}
// 位置参数(独立示例)
{
Object[] args = new Object[]{ 2 };
List<Map<String, Object>> result = jdbc.queryForList(
"select * from users where id > ?", args);
}
// 名称参数(独立示例)
{
Map<String, Object> namedArgs = CollectionUtils.asMap("id", 2);
List<Map<String, Object>> result = jdbc.queryForList(
"select * from users where id > :id", namedArgs);
}
// 使用 对象映射 或 类型处理器
List<T> queryForList(String sql, Class<T> elementType);
List<T> queryForList(String sql, Object args, Class<T> elementType);
List<T> queryForList(String sql, PreparedStatementSetter pss, Class<T> elementType);
// 使用 RowMapper
List<T> queryForList(String sql, RowMapper<T> rowMapper);
List<T> queryForList(String sql, Object args, RowMapper<T> rowMapper);
List<T> queryForList(String sql, PreparedStatementSetter pss, RowMapper<T> rowMapper);
// 无需映射使用 List/Map 接收结果
List<Map<String, Object>> queryForList(String sql);
List<Map<String, Object>> queryForList(String sql, Object args);
List<Map<String, Object>> queryForList(String sql, PreparedStatementSetter pss);
查询对象
返回映射到指定类型的单行。常见场景:聚合查询、主键查找。无结果时返回 null,多行时抛出异常;接收可能为空的标量时使用包装类型。
- 示例:使用 Bean 映射结果集
- 示例:使用 Map 映射结果集
- 函数签名
// 原始 SQL(独立示例)
{
User user = jdbc.queryForObject(
"select * from users where id = 2", User.class);
}
// 位置参数(独立示例)
{
Object[] args = new Object[]{ 2 };
User user = jdbc.queryForObject(
"select * from users where id = ?", args, User.class);
}
// 名称参数(独立示例)
{
Map<String, Object> namedArgs = CollectionUtils.asMap("id", 2);
User user = jdbc.queryForObject(
"select * from users where id = :id", namedArgs, User.class);
}
// 原始 SQL(独立示例)
{
Map<String, Object> user = jdbc.queryForMap(
"select * from users where id = 2");
}
// 位置参数(独立示例)
{
Object[] args = new Object[]{ 2 };
Map<String, Object> user = jdbc.queryForMap(
"select * from users where id = ?", args);
}
// 名称参数(独立示例)
{
Map<String, Object> namedArgs = CollectionUtils.asMap("id", 2);
Map<String, Object> user = jdbc.queryForMap(
"select * from users where id = :id", namedArgs);
}
// 使用 对象映射 或 类型处理器
T queryForObject(String sql, Class<T> requiredType);
T queryForObject(String sql, Object args, Class<T> requiredType);
T queryForObject(String sql, PreparedStatementSetter pss, Class<T> requiredType);
// 使用 RowMapper
T queryForObject(String sql, RowMapper<T> rowMapper);
T queryForObject(String sql, Object args, RowMapper<T> rowMapper);
T queryForObject(String sql, PreparedStatementSetter pss, RowMapper<T> rowMapper);
// 无需映射使用 List/Map 接收结果
Map<String, Object> queryForMap(String sql);
Map<String, Object> queryForMap(String sql, Object args);
Map<String, Object> queryForMap(String sql, PreparedStatementSetter pss);
查询键值对
键值对是将查询到的结果集将第一个列和第二个列分别作为 Map 的 Key 和 Value 将整个结果集存储为一个 Map 类型。
- 示例
- 函数签名
// 原始 SQL(独立示例)
{
Map<Long, String> userMap = jdbc.queryForPairs(
"select uid, name from user where age > 2", Long.class, String.class);
}
// 位置参数(独立示例)
{
Object[] args = new Object[]{ 2 };
Map<Long, String> userMap = jdbc.queryForPairs(
"select uid, name from user where age > ?", Long.class, String.class, args);
}
// 名称参数(独立示例)
{
Map<String, Object> namedArgs = CollectionUtils.asMap("age", 2);
Map<Long, String> userMap = jdbc.queryForPairs(
"select uid, name from user where age > :age", Long.class, String.class, namedArgs);
}
// pairKey 和 pairValue 会使用 对象映射 或 类型处理器来进行映射。
Map<K, V> queryForPairs(String sql,
Class<K> pairKey, Class<V> pairValue);
Map<K, V> queryForPairs(String sql,
Class<K> pairKey, Class<V> pairValue, Object args);
Map<K, V> queryForPairs(String sql,
Class<K> pairKey, Class<V> pairValue, PreparedStatementSetter args);
查询值
查询值区别于查询对象是在于值是可映射的最小类型单元,可以是 TypeHandlerRegistry 注册器中的类型。如:String、Int、Date 等。查询值通常有两种情况:
- 查询值列表,例如获取符合条件的对象 ID 集合。
- 查询聚合汇总信息,例如统计总数,求平均值等。
- 示例:单值
- 示例:值列表
- 函数签名
// 原始 SQL(独立示例)
{
long count = jdbc.queryForLong(
"select count(*) from user where age > 2");
}
// 位置参数(独立示例)
{
Object[] args = new Object[]{ 2 };
long count = jdbc.queryForLong(
"select count(*) from user where age > ?", args);
}
// 名称参数(独立示例)
{
Map<String, Object> namedArgs = CollectionUtils.asMap("age", 2);
long count = jdbc.queryForLong(
"select count(*) from user where age > :age", namedArgs);
}
提示
- jdbc.queryForObject("select count(*) from users", Integer.class); // 具有等效能力
// 原始 SQL(独立示例)
{
List<String> result = jdbc.queryForList(
"select name from users", String.class);
}
// 位置参数(独立示例)
{
Object[] args = new Object[]{ "Bob" };
List<String> result = jdbc.queryForList(
"select name from users where name = ?", args, String.class);
}
// 名称参数(独立示例)
{
Map<String, Object> namedArgs = CollectionUtils.asMap("name", "Bob");
List<String> result = jdbc.queryForList(
"select name from users where name = :name", namedArgs, String.class);
}
// 查询 Long 类型值
Long queryForLong(String sql);
Long queryForLong(String sql, Object args);
Long queryForLong(String sql, PreparedStatementSetter args);
// 查询 int 类型值
Integer queryForInt(String sql);
Integer queryForInt(String sql, Object args);
Integer queryForInt(String sql, PreparedStatementSetter args);
// 查询字符串类型值
String queryForString(String sql);
String queryForString(String sql, Object args);
String queryForString(String sql, PreparedStatementSetter args);
结果接收方式
这些示例覆盖最常见的返回形态。需要控制结果映射过程时,可以按下表选择;详细机制见 接收结果。
| 目标 | 推荐方式 | 详细说明 |
|---|---|---|
| 每行转成一个对象 | RowMapper | RowMapper |
| 不定义实体类,直接接收列名和值 | List<Map<String,Object>> | List/Map |
| 大结果集逐行消费,不在内存中收集 | RowCallbackHandler | RowCallbackHandler |
自己接管整个 ResultSet 遍历过程 | ResultSetExtractor | ResultSetExtractor |
| 单列值的序列化/反序列化 | TypeHandler | 类型处理 |
使用 ResultSetExtractor
User user = jdbc.query(
"select * from users where id = ?",
new Object[]{ 1 },
(ResultSetExtractor<User>) rs -> {
if (!rs.next()) {
return null;
}
User u = new User();
u.setId(rs.getLong("id"));
u.setName(rs.getString("name"));
return u;
}
);
逐行处理
回调避免应用收集完整结果集,但是否按需从服务端读取,还取决于 JDBC 驱动、fetchSize 和连接配置。
RowCallbackHandler handler = (rs, rowNum) -> {
// 逐行处理,不收集为 List
};
jdbc.query("select * from users where age > ?", new Object[]{ 18 }, handler);
Map 大小写敏感性
默认情况下,Map 结果的列名 key 大小写不敏感。不同数据库返回列名大小写可能不同,例如 Oracle 常见大写、MySQL 常见小写。需要严格区分大小写时,参考 List/Map 接收数据。
查询参数说明
在查询相关 API 中,参数统一按 Object 传递,可支持的类型如下:
- 位置参数(多个值放入数组或集合,方法接收的是
Object args,不是可变参数)- 数组、Collection、TypeRegistry 中注册的类型
- 名称化参数
- Map、实体 Bean、SqlArg(名称会固定为
arg0)
- Map、实体 Bean、SqlArg(名称会固定为
- 自定义,完全自定义参数设置逻辑,适合需要手动类型控制的场景。
- 动态 SQL
参数类型最终会经过 TypeHandler 处理,确保 JDBC 类型与 Java 类型的正确映射。