JdbcTemplate
大约 3 分钟
JdbcTemplate是Spring提供的⼀个JDBC模板类(org.springframework.jdbc.core.JdbcTemplate),是对JDBC的封装,简化JDBC代码。
JdbcTemplate 非必须,Spring 支持集成 ORM 框架,如Mybatis、Hibernate。
JdbcTemplate 只是一个类,这个类封装了JDBC代码,完全可以交由 Spring IoC 管理。


从源码可知,要使用 JdbcTemplate 需要提供一个数据源 DataSource。
使用准备
准备数据库表
引入依赖
<repositories> <repository> <id>repository.spring.milestone</id> <name>Spring Milestone Repository</name> <url>https://repo.spring.io/milestone</url> </repository> </repositories> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>6.0.0-M2</version> </dependency> <!--新增的依赖:mysql驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.30</version> </dependency> <!--新增的依赖:spring jdbc,这个依赖中有JdbcTemplate--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>6.0.0-M2</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> </dependencies>准备pojo类
准备 DateSource
DateSource 需要实现
javax.sql.DataSource接口,用以获取 Connection 对象。可以自己写,也可以使用三方数据源,如德鲁伊(druid)、c3p0、dbcp。<!--德鲁伊连接池--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.18</version> </dependency>编写Spring配置文件,让容器管理 JdbcTemplate 和 DataSource:
<!--提供数据源--> <!--使用 context 命名空间引入外部属性配置文件--> <bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driver}"></property> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!--注入数据源--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="myDataSource"/> </bean>
使用 JdbcTemplate
获取 JdbcTemplate 对象
// 获取 JdbcTemplate 对象
JdbcTemplate jdbcTemplate =
applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);增删改
// 执⾏插⼊操作
// 注意:insert delete update的sql语句,都是执⾏update⽅法。
String sql = "insert into t_user(id,real_name,age) values(?,?,?)";
// 可变长参数自动给占位符赋值
int count = jdbcTemplate.update(sql, null, "张三", 30);
System.out.println("插⼊的记录条数:" + count);
// insert delete update 都是这一套查一个
// 执⾏select
String sql = "select id, real_name, age from t_user where id = ?";
User user = jdbcTemplate.queryForObject(
sql,
new BeanPropertyRowMapper<>(User.class), // ORM映射,将查询结果集映射为 pojo。
// 可以自动将符合规范的sql字段名映射为 java 属性。如:real_name -> realName
2 // 可变长参数,自动给占位符赋值
);
System.out.println(user);- 查一个使用 queryForObject 方法。(使用 query 也行,但返回List没必要)
如果需要查询一个“值”,也像这么干,注意类型转换即可:
// 执⾏select
String sql = "select count(1) from t_user";
// 如果查询结果只有一个字段,指定这个字段的映射类型即可,不用映射器
Integer count = jdbcTemplate.queryForObject(sql, int.class); // 这⾥⽤Integer.class也可以查多个
// 执⾏select
String sql = "select id, real_name, age from t_user";
List<User> users = jdbcTemplate.query(
sql,
new BeanPropertyRowMapper<>(User.class) // ORM映射
// 需要传值一样走可变长参数
);
System.out.println(users);- 查多个使用 query 方法。
如果查询多个“值”,类似,同上。
批处理
有时一条sql需要执行多次,可以将每次执行的值收集起来,一起执行一起封装,即批处理。
批处理 DML
// 准备Sql
String sql = "insert into t_user(id,real_name,age) values(?,?,?)";
// 封装参数
// 每次执行的sql参数封装为一个数组,依照位置先后赋值给占位符
Object[] objs1 = {null, "⼩花", 20};
Object[] objs2 = {null, "⼩明", 21};
Object[] objs3 = {null, "⼩刚", 22};
// 将所有的 参数数组 存储到List集合中
List<Object[]> list = new ArrayList<>();
list.add(objs1);
list.add(objs2);
list.add(objs3);
// 使用 batchUpdate 方法执行批处理
// 每次批处理的结果作为一个元素存储在返回值数组中
int[] count = jdbcTemplate.batchUpdate(sql, list);
System.out.println(Arrays.toString(count));- insert、delete、update 都这一套。
批处理 Select
JdbcTemplate 没有提供原生的批量查询,需要自己封装。
使用回调函数
使用 execute 方法,可以手动操作预编译sql对象,使用原生JDBC代码,执行sql,并处理查询结果集:
User user = jdbcTemplate.execute(
sql,
new PreparedStatementCallback<User>() {
@Override
// 在这里编写回调函数,使用原生JDBC代码操作ps对象
public User doInPreparedStatement(PreparedStatement ps)
throws SQLException, DataAccessException {
User user = null;
ps.setInt(1, 5); // 手动给占位符传值
ResultSet rs = ps.executeQuery(); // 执行 sql
// 处理查询结果集
if (rs.next()) {
user = new User();
user.setId(rs.getInt("id"));
user.setRealName(rs.getString("real_name"));
user.setAge(rs.getInt("age"));
}
// 这里的返回值即 execute 方法的返回值
return user;
}
}
);