target
理解为什么会有JdbcTemplate的出现
掌握 JdbcTemplate 的三种使用方式
掌握JdbcTemplate 常用API
1. 概述
JDBC已经能够满足大部分用户最基本的需求,但是在使用JDBC时,必须自己来管理数据库资源如:获取PreparedStatement,设置SQL语句参数,关闭连接等步骤。Spring对JDBC进行了封装,简化了JDBC的相关操作,这就是JdbcTemplate:
JdbcTemplate是Spring对JDBC的封装,目的是使JDBC更加易于使用。
JdbcTemplate是Spring的一部分,处理了资源的建立和释放。
他帮助我们避免一些常见的错误,比如忘了总要关闭连接。
他运行核心的JDBC工作流,如Statement的建立和执行,而我们只需要提供SQL语句和提取结果。
2. 使用
2.1 搭建环境
① 导入jar
commons-dbcp-1.4.jar
commons-logging-1.2.jar
commons-pool-1.6.jar
mysql-connector-java-8.0.15.jar
spring-beans-4.3.9.RELEASE.jar
spring-context-4.3.9.RELEASE.jar
spring-core-4.3.9.RELEASE.jar
spring-expression-4.3.9.RELEASE.jar
spring-jdbc-4.3.9.RELEASE.jar
spring-tx-4.3.9.RELEASE.jar
② 数据库相关
准备好数据库及模拟的数据:
- 创建数据库
create database test;
- 使用数据库
use test;
- 创建表
create table user(
id int primary key auto_increment,
username varchar(30),
password varchar(30)
)
- 插入数据
insert into user(username,password) values('jerry','jerry1234');
insert into user(username,password) values('grace','grace1234');
③ 实体类
新建实例类,对数据库里的字段进行封装:
package com.lee.spring.bean;
public class User {
private int id;
private String name;
private String password;
}
2.2 三种使用方式
jdbcTemplate提供了三种实现方式,根据自己的需求去选择合适的方式使用:
① 纯手写方式使用JdbcTemplate(不推荐)
直接在测试方法中进行测试即可:
@Test
public void test01() {
//1.创建数据源
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test?useSSL=false&characterEncoding=utf-8");
dataSource.setUsername("root");
dataSource.setPassword("root");
//2.创建模板
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
//3.使用API
String sql = "insert into user(username,password) values(?,?)";
jdbcTemplate.update(sql , "rose" , "rose1234");
}
查看数据库,发现成功插入数据:
这种方式是不推荐的,因为数据源的操作全部是手工编码的,尤其是数据库连接相关操作一定是放在配置文件中才是最佳的。
② 使用IoC注入方式
Dbcp数据源
-
jar包:
commons-dbcp-1.4.jar
commons-pool-1.6.jar
Dao层:
public class UserDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void updateUser( User user) {
String sql = "update user set username = ? ,password=? where id = ?";
Object[] orgs = {user.getName(),user.getPassword(),user.getId()};
jdbcTemplate.update(sql , orgs);
}
}
需要注意:在 Dao中需要提供jdbcTemplate和他的setter方法。
- 配置文件:
<!-- 配置jdbc模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 将userDao纳入到IOC容器 -->
<bean id="userDao" class="com.lee.spring.dao.UserDao">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<!-- 配置数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
- 测试:
@Test
public void test02() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao =(UserDao) context.getBean("userDao");
User user = new User();
user.setId(1);
user.setName("杰瑞");
user.setPassword("admin");
userDao.updateUser(user );
}
除了使用Dbcp数据源,还可以使用c3p0数据源实现:
-
jar包
c3p0-0.9.5.2.jar
mchange-commons-java-0.2.20.jar
配置文件
<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!-- 配置jdbc模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
③ 继承JdbcDaoSupport方式
上面的方法,我们每一个dao类都需要一个JdbcTemplate属性。Spring已经为JdbcTemplate做了封装,直接继承JdbcDaoSupport就可以调用已经封装好的JdbcTemplate。
第一步:dao类继承JdbcDaoSupport
public class UserDao extends JdbcDaoSupport {
public List<Map<String, Object>> findAll(){
String sql = "select * from user";
List<Map<String, Object>> list = this.getJdbcTemplate().queryForList(sql);
return list;
}
}
第二步:配置文件删掉JdbcTemplate的注入,直接把数据源注入给dao
<!-- 将userDao纳入到IOC容器 -->
<bean id="userDao" class="com.lee.dao.UserDao">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
测试:
@Test
public void test03() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao =(UserDao) context.getBean("userDao");
List<Map<String,Object>> all = userDao.findAll();
System.out.println(all);
}
2.3 properties使用
一般情况下,我们会把数据库相关信息在一个单独的文件中配置,可以使用properties。
在src下新建db.properties
:
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/test
jdbc.user=root
jdbc.password=root
编写Spring配置文件applicationContext.xml
:
直接使用 $
获取db.properties
中的值
<!-- 将数据库配置文件导入 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
注意:
如果数据库连接失败,可以在相应的属性前加 jdbc.
。
3. API
JdbcTemplate常用的API如下:
3.1 配置类表映射
有时候数据表的字段和实体类的属性不是一一对应的,需要手动进行匹配。怎么匹配?通过实现RowMapper接口。
🌰
UserMapper的作用就是对user数据表的字段和User类的属性匹配:
package com.lee.spring.dao;
public class UserMapper implements RowMapper<User> {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("username"));
user.setPassword(rs.getString("password"));
return user;
}
}
在Dao里进行查询:
查询单个用户使用queryForObject()方法
,查询多个用户使用query()方法
package com.lee.spring.dao;
public class UserDao extends JdbcDaoSupport {
// 查询单个用户
public User getUserById(int id) {
String sql = "select * from user where id = " + id;
User user = this.getJdbcTemplate().queryForObject(sql, new UserMapper());
return user;
}
// 查询多个用户
public List<User> getAllUsers() {
String sql = "select * from user";
List<User> allUsers = this.getJdbcTemplate().query(sql, new UserMapper());
return allUsers;
}
}
编写测试类进行测试:
@Test
public void test04() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao =(UserDao) context.getBean("userDao");
User user = userDao.getUserById(1);
System.out.println(user);
}
@Test
public void test05() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao =(UserDao) context.getBean("userDao");
List<User> allUsers = userDao.getAllUsers();
System.out.println(allUsers);
}
3.2 query相关方法
方法 | 描述 | 参数 | 返回值 |
---|---|---|---|
queryForObject(String sql, RowMapper rowMapper) | 查询单个对象,以对象方式返回 | 第一个参数:执行的查询语句 第二个参数:一个映射类对象(比如UserMapper) | T |
queryForMap(String sql) | 查询单个对象,以map方式返回 | 执行的查询语句 | Map<String, Object> |
query(String sql, RowMapper rowMapper) | 查询多个对象,返回值为List<T> | 第一个参数:执行的查询语句 第二个参数:一个映射类对象(比如UserMapper) | List<T> |
queryForList(String sql) | 查询你多个对象,返回值为List<Map<String,Object>> | 执行的查询语句 | List<Map<String,Object>> |
🌰
package com.lee.spring.dao;
public class UserDao extends JdbcDaoSupport {
// queryForObject:查询单个对象,以对象方式返回
public User queryForObject(int id) {
String sql = "select * from user where id = " + id;
User user = this.getJdbcTemplate().queryForObject(sql, new UserMapper());
return user;
}
// queryForMap:查询单个对象,以map方式返回
public Map<String, Object> queryForMap(int id) {
String sql = "select * from user where id = " + id;
Map<String, Object> map = this.getJdbcTemplate().queryForMap(sql);
return map;
}
// query(String sql, RowMapper rowMapper):查询多个对象,返回值为List<T>
public List<User> queryAll() {
String sql = "select * from user";
List<User> allUsers = this.getJdbcTemplate().query(sql, new UserMapper());
return allUsers;
}
// queryForList(String sql):查询多个对象,以List<Map<String, Object>>返回
public List<Map<String, Object>> queryForList(){
String sql = "select * from user";
List<Map<String, Object>> list = this.getJdbcTemplate().queryForList(sql);
return list;
}
}
编写测试类测试:
@Test
public void test06() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao =(UserDao) context.getBean("userDao");
Map<String, Object> map = userDao.queryForMap(1);
System.out.println(map);
System.out.println("-------------------------");
User user = userDao.queryForObject(1);
System.out.println(user);
System.out.println("-------------------------");
List<User> all = userDao.queryAll();
System.out.println(all);
System.out.println("-------------------------");
List<Map<String, Object>> list = userDao.queryForList();
System.out.println(list);
}
3.3 update
方法:update(String sql, Object... args)
其中,args为更新的参数
作用:更新、修改、删除操作,返回受影响的行数 .
🌰
package com.lee.spring.dao;
public class UserDao extends JdbcDaoSupport {
public int updateUser( User user) {
String sql = "update user set username = ? ,password=? where id = ?";
Object[] orgs = {user.getName(),user.getPassword(),user.getId()};
int i = this.getJdbcTemplate().update(sql , orgs);
return i;
}
}
测试:
@Test
public void test07() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao =(UserDao) context.getBean("userDao");
User user = new User();
user.setId(1);
user.setName("杰瑞");
user.setPassword("admin");
userDao.updateUser(user );
}
3.4 batchUpdate
方法:batchUpdate(SQL语句1,SQL语句2....);
作用:执行批量操作,可以是批量更新、批量插入、批量删除,参数为string数组
返回值:整形数组。数组中数字表示相应的SQL语句影响的行数。
🌰
package com.lee.spring.dao;
public class UserDao extends JdbcDaoSupport {
public int[] batch() {
String sql1 = "delete from user";
String sql2 = "insert into user values(1,'aa','aa123'),(2,'bb','bb123')";
String sql3 = "update user set password = 'admin' where id =1";
int[] nums = this.getJdbcTemplate().batchUpdate(sql1,sql2,sql3);
return nums;
}
}
测试:
@Test
public void test08() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao =(UserDao) context.getBean("userDao");
int[] batch = userDao.batch();
for (int i : batch) {
System.out.println(i);
}
}