在前面我们学习了JDBC Template,尽管此时可以直接利用JDBCTemplate进行数据库的操作,但是在大部分的DAO的实现子类中,却很少有人会这样做,大家往往会让DAO的实现子类既实现了DAO同时又继承一个JdbcDaoSupport的抽象类。为什么会这样呢?先来看之前学习的JDBC Template。

我们为获得JDBCTemplate对象,需要在xml文件中进行配置:

1
2
3
4
<!--配置JDBC工具类-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>

然后在使用的地方使用下面的代码进行注入:

1
2
@Autowired
private JdbcTemplate jdbcTemplate;

这其实就是让Spring容器来管理JdbcTemplate,如果你继承了JdbcDaoSupport,那么这些过程都可以不需要了。

JdbcDaoSupport

JdbcDaoSupport是Spring内置的一个Dao层的基类,来自spring-jdbc-4.2.4.RELEASE.jar这个包。其内部定义了JdbcTemplate的set方法,也就是说dao类只需继承JdbcDaoSupport类,就可以省略JdbcTemplate的set方法的书写,通过查看源码你会发现,该方法是final修饰的:

1
2
3
4
5
6
7
8
/**
* Set the JdbcTemplate for this DAO explicitly,
* as an alternative to specifying a DataSource.
*/
public final void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
initTemplateConfig();
}

被final修饰的方法意味着该方法无法被子类重写,同时它还提供了注入数据库连接池的set方法:

1
2
3
4
5
6
7
8
9
/**
* Set the JDBC DataSource to be used by this DAO.
*/
public final void setDataSource(DataSource dataSource) {
if (this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()) {
this.jdbcTemplate = createJdbcTemplate(dataSource);
initTemplateConfig();
}
}

从该方法中可以知道,如果Spring配置文件中没有配置jdbcTemplate ,那么它是可以通过注入dataSource的时候自动创建jdbcTemplate,因此它可以省略JdbcTemplate类的注册工作。

说白了就是JdbcDaoSupport可以简化dao类有关JdbcTemplate注入的相关工作,如果需要使用JdbcTemplate,只需要调用JdbcDaoSupportgetJdbcTemplate方法即可获取,再也不需要在Spring文件中进行配置了。

银行转账案例

我们以银行转账为例进行介绍,这个案例很经典,后续会以这个例子介绍Spring事务管理相关的知识。

第一步,新建数据库spring_money和表account:

1
2
3
4
5
6
7
8
9
10
11
12
drop database if exists spring_money;
create database spring_money;
use spring_money;
create table account
(
id bigint auto_increment primary key,
name varchar(32) not null,
money bigint not null,
constraint account_name_uindex
unique (name)
);
insert into account (name, money) values('小明', 2000),('小白', 2000);

第二步,新建Maven项目spring_money:
其中pom.xml配置信息为:

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.envy</groupId>
<artifactId>Spring_money</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<spring.version>4.2.7.RELEASE</spring.version>
</properties>

<dependencies>
<!--Spring核心组件-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>

<!--Spring AOP组件-->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>

<!--AspectJ AOP开发需要引入的两个包-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>

<!--MySql驱动,注意版本号-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>

<!--JDBC Template-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>

<!-- druid数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.25</version>
</dependency>

<!-- 测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</project>

第三步,创建一个实体包com.envy.entity,接着在里面新建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
package com.envy.entity;

public class Account {
private int id;
private String name;
private Long money;

public int getId(){
return id;
}

public void setId(int id){
this.id=id;
}

public String getName(){
return name;
}

public void setName(String name){
this.name=name;
}

public Long getMoney(){
return money;
}

public void setMoney(Long money){
this.money = money;
}

public String toString(){
return "Account:id is"+id+";name is"+ name+ ";money is"+money;
}
}

第四步,创建一个Dao包com.envy.dao,接着在里面新建AccountDao接口:

1
2
3
4
5
6
7
8
package com.envy.dao;

import com.envy.entity.Account;

public interface AccountDao {
void save(Account account);
}

然后在com.envy.dao中新建一个Impl包,在Impl中新建AccountDao接口的实现类AccountDaoImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.envy.dao.Impl;

import com.envy.dao.AccountDao;
import com.envy.entity.Account;
import org.springframework.jdbc.core.support.JdbcDaoSupport;


//dao层,继承JdbcDaoSupport
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {

public void save(Account account) {
String sql = "insert into account(name,money)values(?,?)";
getJdbcTemplate().update(sql,"小红",1000L); // 从父类JdbcDaoSupport中获取jdbcTemplate
}
}

第六步,创建一个db.properties配置文件:

1
2
3
4
5
6
7
8
#加载驱动
druid.driverClassName=com.mysql.jdbc.Driver
#加载数据库
druid.url=jdbc:mysql://localhost:3306/spring_money?useUnicode=true&characterEncoding=UTF-8
#用户名
druid.username=root
#密码
druid.password=root

第七步,创建一个applicationContext.xml配置文件:(XML配置方式管理Bean,注释掉的内容表示多余,但是便于理解这里依旧贴出代码)

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
<!--读取外部db.properties配置信息-->
<context:property-placeholder location="classpath:db.properties"/>
<!--开启包扫描-->
<context:component-scan base-package="com.envy.service.Impl"/>
<!--配置数据源-->
<bean id = "dataSource" class = "com.alibaba.druid.pool.DruidDataSource" destroy-method = "close">
<!--数据库基本信息配置-->
<property name="url" value="${druid.url}"/>
<property name="username" value="${druid.username}"/>
<property name="password" value="${druid.password}"/>
<property name="driverClassName" value="${druid.driverClassName}"/>
</bean>


<!--注册AccountDaoImpl-->
<bean id="accountDao" class="com.envy.dao.Impl.AccountDaoImpl">
<!--注入属性:dataSource属性来自jdbcDaoSupport类,只需要继承即可拥有-->
<property name="dataSource" ref="dataSource"/>
<!--dataSource属性对应的setDataSource方法内部会自动创建jdbcTemplate因此,这里无需再注入jdbcTemplate属性-->
<!--<property name="jdbcTemplate" ref="jdbcTemplate"/>-->
</bean>

<!-- 继承JdbcDaoSupport后,不需要注册JdbcTemplate类-->
<!--<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">-->
<!--<property name="dataSource" ref="dataSource"/>-->
<!--</bean>-->

第八步,开始测试,新建JdbcDaoSupportAccountTest.java测试文件

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
import com.envy.dao.AccountDao;
import com.envy.entity.Account;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JdbcDaoSupportAccountTest {

@Autowired
private AccountDao accountDao;

@Test
public void testOne(){
Account account = new Account();
account.setName("小红");
account.setMoney(888L);
accountDao.save(account);
}
}

运行测试代码发现没有问题,因此建议大家在Spring中使用JdbcDaoSupport。