提示
本文内容结构参考了英文版文档,便于中英文对照。
查询
JdbcTemplate 提供多种只读查询 API。大多数接口接受 SQL 字符串和参数(对象或数组),返回由结果集构建的对象;部分接口支持回调/映射器以自定义处理过程。
查询结果集
查询一个对象或 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> args = CollectionUtils.asMap("id", 2);
List<User> result = jdbc.queryForList(
"select * from users where id > :id", args, 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> args = CollectionUtils.asMap("id", 2);
List<Map<String, Object>> result = jdbc.queryForList(
"select * from users where id > :id", args);
// 使用 对象映射 或 类型处理器
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);
查询对象
返回映射到指定类型的单行。常见场景:聚合查询、主键查找。若结果为多行会抛出异常。
- 示例:使用 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> args = CollectionUtils.asMap("id", 2);
User user = jdbc.queryForObject(
"select * from users where id = :id", args, 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> args = CollectionUtils.asMap("id", 2);
Map<String, Object> user = jdbc.queryForMap(
"select * from users where id = :id", args);
// 使用 对象映射 或 类型处理器
List<T> queryForObject(String sql, Class<T> requiredType);
List<T> queryForObject(String sql, Object args, Class<T> requiredType);
List<T> queryForObject(String sql, PreparedStatementSetter pss, Class<T> requiredType);
// 使用 RowMapper
List<T> queryForObject(String sql, RowMapper<T> rowMapper);
List<T> queryForObject(String sql, Object args, RowMapper<T> rowMapper);
List<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> args = CollectionUtils.asMap("age", 2);
Map<Long, String> userMap = jdbc.queryForPairs(
"select uid, name from user where age > :age", Long.class, String.class, args);
// 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 注册器中的类型。如:Stirng、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> args = CollectionUtils.asMap("age", 2);
long count = jdbc.queryForLong(
"select count(*) from user where age > :age", args);
提示
- jdbc.queryForObject("select count(*) from users", Integer.class); // 具有等效能力
// 原始 SQL
List<String> result = jdbc.queryForList(
"select name from users", String.class);
// 位置参数
Object[] args = new Object[]{ 2 };
List<String> result = jdbc.queryForList(
"select name from users where name = ?", args, String.class);
// 名称参数
Map<String, Object> args = CollectionUtils.asMap("name", "Bob");
List<String> result = jdbc.queryForList(
"select name from users where id = :id", args, 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);
使用 ResultSetExtractor
使用 ResultSetExtractor 接口是最灵活处理结果集的方式,用户需要自行实现执行从 ResultSet 中提取结果的实际工作,同时无需担心异常处理。
- 示例:单值
- 示例:值列表
- 函数签名
// 原始 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> args = CollectionUtils.asMap("age", 2);
long count = jdbc.queryForLong(
"select count(*) from user where age > :age", args);
提示
- jdbc.queryForObject("select count(*) from users", Integer.class); // 具有等效能力
// 原始 SQL
List<String> result = jdbc.queryForList(
"select name from users", String.class);
// 位置参数
Object[] args = new Object[]{ 2 };
List<String> result = jdbc.queryForList(
"select name from users where name = ?", args, String.class);
// 名称参数
Map<String, Object> args = CollectionUtils.asMap("name", "Bob");
List<String> result = jdbc.queryForList(
"select name from users where id = :id", args, String.class);
// 使用 ResultSetExtractor
T query(String sql, ResultSetExtractor<T> rse);
T query(String sql, Object args, ResultSetExtractor<T> rse);
T query(String sql, PreparedStatementSetter args, ResultSetExtractor<T> rse);
流式查询
针对超 大结果集,逐行流式处理以节省内存;每行在回调中即时处理。
- 示例
- 函数签名
// 流式消费数据
RowCallbackHandler handler = (rs, rowNum) -> {
// 处理一行
};
// 原始 SQL
jdbc.query("select * from user where age > 2", handler);
// 位置参数
Object[] args = new Object[]{ 2 };
jdbc.query("select * from user where age > ?", args, handler);
// 名称参数
Map<String, Object> args = CollectionUtils.asMap("age", 2);
jdbc.query("select * from user where age > :age", args, handler);
void query(String sql, RowCallbackHandler rch);
void query(String sql, Object args, RowCallbackHandler rch);
void query(String sql, PreparedStatementSetter args, RowCallbackHandler rch);
Map 大小写敏感性
默认情况下以 Map 为数据存储结构时查询返回的 key 对于大小写不敏感。
有如下查询
List<Map<String, Object>> result = jdbc.queryForList("select * from users");
users 表在相同表结构和数据在不同数据库中执行结果会有不同,例如:
- 在 Oracle 返回的列名默认:大写
- 在 MySQL 返回的列名默认:小写
dbVisitor 默认会采用 LinkedCaseInsensitiveMap 工具类以不区分大小写的方式存储查询结果的列名。
- 即
resultsCaseInsensitive参数默认值为true
如果希望使用大小写敏感的方式存储查询结果,需要将其设置为 false。
JdbcTemplate jdbc = ...
jdbc.setResultsCaseInsensitive(false);
List<Map<String, Object>> result = jdbc.queryForList("select * from users");
通过设置 jdbc.setResultsCaseInsensitive(false); 可以决定结果集列名的大小写敏感性。
- 默认情况下,属性值为
true表示结果集列名是大小写不敏感。 - 当设置为
false时,会使用LinkedHashMap存放数据,结果集中列名会严格区分大小写。