Spring 的 JdbcTemplate
# 100.Spring 的 JdbcTemplate
JdBCTemplate 是 Spring 框架中提供的一个对象,是对原始 Jdbc API 对象的简单封装。
# JdBCTemplate 介绍
Spring 框架为我们提供了很多的操作模板类:
- 操作关系型数据的:JdbcTemplate、HibernateTemplate
- 操作 NoSQL 数据库的:RedisTemplate
- 操作消息队列的:JmsTemplate
需要的依赖: spring-jdbc-5.0.2.RELEASE.jar 、 spring-tx-5.0.2.RELEASE.jar(和事务相关)
概念图:
# 环境准备
此时我们可以删掉之前的所有代码,和 pom.xml 文件中的依赖,从头开始搭建
# 引入依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
</project>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 创建实体类
package com.peterjxl.domain;
import java.io.Serializable;
public class Account implements Serializable {
private Integer id;
private String name;
private Float money;
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
注:请自行生成 getter 和 setter
# 入门案例
我们直接新建一个 demo 类来演示:
package com.peterjxl.jdbctemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
/**
* JdbcTemplate的最基本用法
*/
public class JdBCTemplateDemo1 {
public static void main(String[] args) {
// 准备数据源:spring的内置数据源
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql:///learnSpring");
ds.setUsername("learnSpringUser");
ds.setPassword("learnSpringPassword");
// 1. 创建JdbcTemplate对象
JdbcTemplate jt = new JdbcTemplate(ds);
//2. 执行操作
jt.execute("insert into account(name, money) values('ddd', 1000)");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
可以看到能正常 insert 数据。
# 配置 IoC
新建 bean.xml,配置如下内容:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 配置JdBCTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/learnSpring"/>
<property name="username" value="learnSpringUser"/>
<property name="password" value="learnSpringPassword"/>
</bean>
</beans>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
新建一个 demo 类:
package com.peterjxl.jdbctemplate;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
/**
* JdbcTemplate的最基本用法
*/
public class JdBCTemplateDemo2 {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
JdbcTemplate jt = ac.getBean("jdbcTemplate", JdbcTemplate.class);
jt.execute("insert into account(name, money) values('eee', 1000)");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 配置增删改查
新建一个 demo 类:
package com.peterjxl.jdbctemplate;
import com.peterjxl.domain.Account;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import java.util.List;
/**
* JdbcTemplate的增删改查
*/
public class JdBCTemplateDemo3 {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
JdbcTemplate jt = ac.getBean("jdbcTemplate", JdbcTemplate.class);
// 保存
jt.update("insert into account(name, money) values(?, ?)", "fff", 1000f);
//更新
jt.update("update account set name=?, money=? where id=?", "test", 100f, 7);
// 删除
jt.update("delete from account where id=?", 8);
// 查询所有
List<Account> accounts = jt.query("select * from account where money > ?", new AccountRowMapper(), 1000f);
for (Account account : accounts) {
System.out.println(account);
}
// 查询一个
List<Account> accounts1 = jt.query("select * from account where id = ?", new AccountRowMapper(), 1);
// 查询返回一行一列(使用聚合函数,但不加group by子句)
Long count = jt.queryForObject("select count(*) from account where money > ?", Long.class, 1000f);
}
}
/**
* 定义Account的封装策略
*/
class AccountRowMapper implements RowMapper<Account> {
/**
* 把结果集中的数据封装到Account中,然后由Spring把每个Account加到集合中
*/
public Account mapRow(java.sql.ResultSet rs, int rowNum) throws java.sql.SQLException {
Account account = new Account();
account.setId(rs.getInt("id"));
account.setName(rs.getString("name"));
account.setMoney(rs.getFloat("money"));
return account;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
query
方法有很多:
我们可以根据返回类型,和参数列表,来确定我们到底用哪个方法。以查询所有为例,可以定位到这两个方法:
public <T> List<T> query(String sql, @Nullable Object[] args, RowMapper<T> rowMapper)
public <T> List<T> query(String sql, RowMapper<T> rowMapper, @Nullable Object... args)
1
2
2
这两个方法都可以用,区别在于,第一个方法是任何 Java 版本都可以用,而第二个方法用了可变参数,是 Java5 之后才能用。
queryForObject
方法中,如果想返回 int 类型,可以传入 Integer.class。
# JdbcTemplate 在 dao 中的使用
在实际开发过程中,我们都是使用三层架构的。
# 新建 dao 接口
package com.peterjxl.dao;
import com.peterjxl.domain.Account;
public interface IAccountDao {
Account findAccountById(Integer accountId);
Account findAccountByName(String accountName);
void updateAccount(Account account);
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 新增 dao 实现类
package com.peterjxl.dao.impl;
import com.peterjxl.dao.IAccountDao;
import com.peterjxl.domain.Account;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
/**
* 账户的持久层实现类
*/
public class AccountDaoImpl implements IAccountDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public Account findAccountById(Integer accountId) {
List<Account> accounts = jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), accountId);
return accounts.isEmpty() ? null : accounts.get(0); // 如果accounts为空,返回null,否则返回accounts.get(0)
}
@Override
public Account findAccountByName(String accountName) {
List<Account> accounts = jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), accountName);
if (accounts.isEmpty()) {
return null;
}
if (accounts.size() > 1) {
throw new RuntimeException("结果集不唯一");
}
return accounts.get(0);
}
@Override
public void updateAccount(Account account) {
jdbcTemplate.update("update account set name=?, money=? where id=?", account.getName(), account.getMoney(), account.getId());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 配置 bean
<!-- 配置账户的持久层实现类 -->
<bean id="accountDao" class="com.peterjxl.dao.impl.AccountDaoImpl">
<!-- 注入JdbcTemplate -->
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
1
2
3
4
5
2
3
4
5
# 新增测试方法
package com.peterjxl.jdbctemplate;
import com.peterjxl.dao.IAccountDao;
import com.peterjxl.domain.Account;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
/**
* JdbcTemplate的最基本用法
*/
public class JdBCTemplateDemo4 {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
IAccountDao accountDao = ac.getBean("accountDao", IAccountDao.class);
Account account = accountDao.findAccountById(1);
System.out.println(account);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
运行结果:
Account{id=1, name='aaa', money=600.0}
1
# 源码
本项目已将源码上传到 GitHub (opens new window) 和 Gitee (opens new window) 上。并且创建了分支 demo13,读者可以通过切换分支来查看本文的示例代码。
上次更新: 2024/10/1 21:14:36