一、概述
Spring 对JDBC等数据库访问技术编写DAO提供了一下几个重要支持。
- Spring 对DAO异常提供了统一处理
- Spring 对DAO编写提供了支持的抽象类
- 提高编程效率,减少JDBC编码量。
1.1 Spring对DAO异常支持
Spring把特定某种技术的异常,如SQLException,同意转化为自己的异常,这些异常以DataAccessException为父类,它们封装了原始异常对象,不会丢失原始错误信息。
DataAccessException继承于RuntimeException,是非检查异常,不会因为没有处理异常而出现编译错误,异常必须处理,可以使用拦截器或者在界面层统一处理。
1.2 Spring对DAO编写的支持
Spring为了便于以一种一致的方式使用各种数据访问技术,如JDBC和Hibernate。Spring提供了一套抽象的DAO类,这些抽象类提供了一些方法,通过它们可以获得与数据访问技术相关的数据源和其他配置信息。
- JdbcTemplate 封装常用JDBC方法。
- HibernateTemplate 封装Hibernate方法。
- JdbcDaoSupport 这个是JDBC数据访问对象的基类。
- HibernateDaoSupport 这个是Hibernate数据访问对象的基类。
JdbcDaoSupport
JdbcDaoSupport是利用JDBC技术编写DAO的父类,通过该类提供的方法,可便于获取Connection和JdbcTemplate等对象信息。
JdbcDaoSupport使用时需要注入一个DataSource对象,对代码有一定的侵入性(耦合度)。
JdbcTemplate
JdbcTemplate封装了连接获取以及连接释放等工作,从而简化了我们对JDBC的使用,避免忘记关闭连接等错误。
JdbcTemplate提供了一下主要方法:
- queryForInt()
- queryForObject()
- query()
- update()
- execute()
1.3 如何编写DAO组件
基于JDBC技术编写DAO组件可以采用下面两种模式:
模式一:
DAO继承JdbcDaoSupport,通过getJdbcTemplate()方法获取JdbcTemplate对象,需要在DAO实现类中注入一个DataSource对象来完成JdbcTemplate对象的实例化。
模式二:
DAO不继承JdbcDaoSupport,在Spring容器中配置一个JdbcTemplate的bean,然后注入给DAO实现类,此种模式更加优雅一些。
二、数据源对象管理
这一节我们将学习Spring对数据源对象的管理
本节课程分别以常用的数据源Druid(德鲁伊)和c3p0来配置学习。
2.1 环境准备
>> 创建一个maven项目
>> pom.xml中添加依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
</dependencies>
>> resources下添加spring的配置文件application.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">
</beans>
>> 编写一个测试方法,测试环境
package datasource;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DataSourceTest {
@Test
public void testEnvironment(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml");
System.out.println(ctx);
}
}
2.2 实现Druid管理
>> 导入druid的依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
>> 在resources中添加数据源properties文件 db.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/study?useUnicode=true&characterEncoding=utf8&&useSSL=false&serverTimezone=UTC
user=root
password=123456
>> 在application.xml中配置DruidDatasource数据源
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<!--加载db资源文件-->
<util:properties id="jdbc" location="classpath:db.properties"></util:properties>
<!--定义数据源-->
<bean id="ds" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
===说明===
- driverClassName: 数据库驱动
- url: 数据库连接地址
- username: 数据库连接用户名
- password:数据库连接密码
- 数据库连接的相关信息要替换成自己的数据库相关信息。
>> 编写测试类,测试从IOC容器中获取对应的bean
//测试从容器中获取druid对象
@Test
public void testDruidBean(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml");
DataSource datasource = ctx.getBean("ds",DataSource.class);
System.out.println(datasource);
}
>> 打印效果如下:说明第三方bean对象druid的对象已经被spring 的IOC容器进行管理
2.3 实现C3P0管理
完成了DruidDataSource的管理,接下来我们来管理c3p0数据源
>> 在pom.xml中添加依赖
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
>> 在application.xml中配置c3p0的bean
加载properties除了可以使用前面用过得<util:properties>以外,还可以使用<context-property-placeholder>,本案例演示一下这种用法:
<!--加载jdbc资源文件-->
<context:property-placeholder location="db.properties"></context:property-placeholder>
<!--定义c3p0 数据源-->
<bean id="c3p0_ds" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driver}"></property>
<property name="jdbcUrl" value="${url}"></property>
<property name="user" value="${user}"></property>
<property name="password" value="${password}"></property>
<property name="maxPoolSize" value="1000"></property>
</bean>
=== 说明 ===
和util加载properties文件使用文件中的key是用的# 而context方式用的是$,且可以直接使用文件中的key
ComboPooledDataSource的属性是通过setter方式进行注入的。
想要注入属性就需要在CombPooledDataSource类或其上层类中有提供属性对应的Setter方法。
C3P0的四个属性和Druid的四个属性是不一样的。
C3P0中封装的驱动类属性名,连接属性名和druid有区别,注意用的时候不要用混了。
>> 编写测试方法,测试从IOC容器中获取c3p0连接池对象
//测试从容器中获取c3p0对象
@Test
public void TestC3P0Bean(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml");
DataSource datasource = ctx.getBean("c3p0_ds",DataSource.class);
System.out.println(datasource);
}
>> 运行之后,会发现程序报错了
从错误信息来看,是说我们的驱动类没有找到,因为我们并没有导入数据库的驱动依赖,在pom.xml中添加一下数据库驱动依赖即可:
<!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.32</version>
</dependency>
>> 添加完毕之后再次运行,就正常了
=== 注意 ===
数据库连接池在配置属性的时候,除了可以注入数据库连接要素意外,还可以注入其他的属性,具体有哪些属性可以用的时候再去查,一般配置:驱动、地址、用户名和密码,其他的都有默认值。
Druid在没有导入mysql驱动包的前提下,不会报错。而c3p0会报错。说明druid在初始化的时候没有去加载驱动,而c3p0则会去加载驱动。
Druid程序虽然运行没有报错,但是当调用DruidDataSource的getConnection()方法获取连接的时候,也会报找不到驱动类的错误。
三、DAO不继承JdbcDaoSupport模式(掌握)
接下来我们来看一看DAO不继承JdbcDaoSupport模式,这个案例我们就采用Druid数据库连接池去配置数据源。
实现方式:
DAO不继承JdbcDaoSupport,在Spring容器中配置一个JdbcTemplate的bean,然后注入给DAO实现类,此种模式更加优雅一些。
3.1 创建员工表emp
DROP TABLE IF EXISTS `emp`;
CREATE TABLE `emp` (
`empno` int NOT NULL AUTO_INCREMENT,
`ename` varchar(20) DEFAULT NULL,
`job` varchar(20) DEFAULT NULL,
`manager` int DEFAULT NULL,
`hiredate` date DEFAULT NULL,
`salary` double DEFAULT NULL,
`comm` double DEFAULT NULL,
`deptno` int DEFAULT NULL,
PRIMARY KEY (`empno`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb3;
-- ----------------------------
-- Records of emp
-- ----------------------------
INSERT INTO `emp` VALUES ('1', '郭靖', 'clerk', '4', '2022-02-03', '7000', '2000', '2');
INSERT INTO `emp` VALUES ('2', '黄蓉', 'saleman', '4', '2023-02-01', '6000', '5000', '3');
INSERT INTO `emp` VALUES ('3', '周瑜', 'saleman', '4', '2023-02-18', '7000', '3000', '3');
INSERT INTO `emp` VALUES ('4', '孙策', 'manager', null, '2021-02-04', '10000', '20000', '1');
3.2 添加依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.23</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.32</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.18</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.10</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
3.3 配置数据源
-
数据源文件jdbc.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/study?useUnicode=true&characterEncoding=utf8&&useSSL=false&serverTimezone=UTC
user=root
password=root -
application.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" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<util:properties id="jdbc" location="classpath:jdbc.properties"></util:properties>
</beans><!--定义数据源--> <bean id="ds" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="#{jdbc.driver}"/> <property name="url" value="#{jdbc.url}"/> <property name="username" value="#{jdbc.user}"/> <property name="password" value="#{jdbc.password}"/> </bean> <!-- 开启注解扫描--> <context:component-scan base-package="com.moxuan"/> <!-- 注入jdbcTemplate对象--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="ds"></property> </bean>
3.4 创建实体类对象
package com.moxuan.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.sql.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Emp {
private Integer empno;
private String name;
private String job;
private Integer manager;
private Date hiredate;
private double salary;
private double comm;
private Integer deptno;
}
3.5 创建映射类
新建一个mapper包,然后创建EmpRowMapper类,让实体类的属性和数据表中的字段对应。
package com.moxuan.mapper;
import com.moxuan.entity.Emp;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
public class EmpRowMapper implements RowMapper<Emp> {
/**
* 将数据库中表的字段和实体类中的属性对应起来
*/
@Override
public Emp mapRow(ResultSet rs, int rowNum) throws SQLException {
Emp e = new Emp();
e.setEmpno(rs.getInt("empno"));
e.setEname(rs.getString("ename"));
e.setJob(rs.getString("job"));
e.setManager(rs.getInt("manager"));
e.setHiredate(rs.getDate("hiredate"));
e.setSalary(rs.getDouble("salary"));
e.setComm(rs.getDouble("comm"));
e.setDeptno(rs.getInt("deptno"));
return e;
}
}
3.6 创建DAO接口
package com.moxuan.dao;
import com.moxuan.entity.Emp;
import java.util.List;
public interface EmpDao {
/** 查询所有的员工**/
List<Emp> findAll();
/** 根据empno查找员工**/
Emp findEmpByEmpno(int empno);
/** 保存员工数据**/
void save(Emp emp);
/** 修改员工数据**/
void update(Emp emp);
/** 删除员工数据**/
void delete(int empno);
}
3.7 创建DAO接口实现类
3.7.1 查询列表
>> **实现查询列表功能:**注入JdbcTemplate对象,添加查询所有员工的方法
@Repository
public class EmpDaoImpl implements EmpDao {
@Resource // 注入jdbcTemplate对象
private JdbcTemplate jdbcTemplate;
@Override
public List<Emp> findAll() {
String sql = "select * from emp";
// 创建映射类对象
RowMapper<Emp> rowMapper = new EmpRowMapper();
// query() 查询结果是一个列表
return jdbcTemplate.query(sql,rowMapper);
}
}
>> 添加测试方法
/**
* 测试查询所有员工
*/
@Test
public void test01(){
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
EmpDaoImpl dao = context.getBean("empDaoImpl",EmpDaoImpl.class);
System.out.println(dao.findAll());
}
>> 运行效果
=== 注意 ===
- query() 可以用来做列表的查询,第一个参数是需要执行的sql语句,第二个参数是映射类对象
- 映射类中,让数据库表中的字段和实体类类属性对应起来,这样做查询时,会将数据库中字段对应的数据暂存到实体类对象的属性中。
3.7.2 查询单个数据
>> **实现根据员工编号查询员工:**在EmpDaoImpl中添加根据empno查询数据的方法
@Override
public Emp findEmpByEmpno(int empno) {
String sql = "select * from emp where empno=?";
RowMapper<Emp> rowMapper = new EmpRowMapper();
return jdbcTemplate.queryForObject(sql,rowMapper,empno);
}
>> 编写测试方法
/**
* 测试根据员工号查询员工
*/
@Test
public void test02(){
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
EmpDaoImpl dao = context.getBean("empDaoImpl",EmpDaoImpl.class);
System.out.println(dao.findEmpByEmpno(3));
}
>> 运行效果:
=== 说明 ===
- queryForObject() 当查询单个对象的时候可以使用。第一个参数是需要执行的sql语句,第二个参数是映射类对象。
- 如果sql语句中有多个号的话,可以在queryForObject() 后面添加对应的参数。
3.7.3 添加数据
>> 实现添加员工功能: 在EmpDaoImpl中添加save方法
@Override
public void save(Emp emp) {
String sql = "insert into emp (ename,job,manager,hiredate,salary,comm,deptno) values(?,?,?,?,?,?,?)";
Object[] params = {
emp.getEname(),
emp.getJob(),
emp.getManager(),
emp.getHiredate(),
emp.getSalary(),
emp.getComm(),
emp.getDeptno()
};
jdbcTemplate.update(sql,params);
}
>> 添加测试方法
@Test
public void test03(){
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
EmpDaoImpl dao = context.getBean("empDaoImpl",EmpDaoImpl.class);
Emp emp = new Emp();
emp.setEname("孙尚香");
emp.setManager(3);
emp.setJob("业务人员");
emp.setHiredate(new Date(System.currentTimeMillis()));
emp.setSalary(5000);
dao.save(emp);
// 调用测试查询所有的方法,查看是否操作成功
test01();
}
>> 运行效果
3.7.4 修改数据
>> 实现修改员工数据功能:在EmpDaoImpl中添加修改员工数据的方法:
@Override
public void update(Emp emp) {
String sql = "update emp set ename=?,job=?,manager=?,hiredate=?,salary=?,comm=?,deptno=? where empno=?";
Object[] params = {
emp.getEname(),
emp.getJob(),
emp.getManager(),
emp.getHiredate(),
emp.getSalary(),
emp.getComm(),
emp.getDeptno(),
emp.getEmpno()
};
jdbcTemplate.update(sql,params);
}
>> 添加测试方法:
/**
* 测试修改员工的方法
*/
@Test
public void test04(){
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
EmpDaoImpl dao = context.getBean("empDaoImpl",EmpDaoImpl.class);
Emp emp = dao.findEmpByEmpno(3);
System.out.println(emp);
emp.setEname("江湖骗子");
dao.update(emp);
emp = dao.findEmpByEmpno(3);
System.out.println(emp);
}
>> 运行结果:
3.7.5 删除数据
>> 实现删除员工的功能:在EmpDaoImpl中添加删除员工数据的方法
@Override
public void delete(int empno) {
String sql = "delete from emp where empno=?";
jdbcTemplate.update(sql,empno);
}
>> 添加删除员工的测试方法:
@Test
public void test05(){
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
EmpDao dao = context.getBean("empDaoImpl",EmpDaoImpl.class);
System.out.println("--------------删除前-----------");
test01();
dao.delete(4);
System.out.println("--------------删除后-----------");
test01();
}
>> 运行效果:
3.8 案例完整代码
3.8.1 pom.xml 依赖文件
<?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.moxuan</groupId>
<artifactId>spring_jdbc</artifactId>
<version>1.0-SNAPSHOT</version>
<name>spring_jdbc</name>
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<junit.version>5.7.0</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.23</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.32</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.18</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
</plugins>
</build>
</project>
3.8.2 application.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" xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--加载jdbc资源文件-->
<util:properties id="jdbc" location="classpath:jdbc.properties"></util:properties>
<!--定义数据源-->
<bean id="ds" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="#{jdbc.driver}"/>
<property name="url" value="#{jdbc.url}"/>
<property name="username" value="#{jdbc.user}"/>
<property name="password" value="#{jdbc.password}"/>
</bean>
<!-- 开启注解扫描-->
<context:component-scan base-package="com.moxuan"/>
<!-- 注入jdbcTemplate对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="ds"></property>
</bean>
</beans>
3.8.3 实体类Emp
package com.moxuan.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.sql.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer manager;
private Date hiredate;
private double salary;
private double comm;
private Integer deptno;
}
3.8.4 Dao接口类
package com.moxuan.dao;
import com.moxuan.entity.Emp;
import java.util.List;
public interface EmpDao {
/** 查询所有的员工**/
List<Emp> findAll();
/** 根据empno查找员工**/
Emp findEmpByEmpno(int empno);
/** 保存员工数据**/
void save(Emp emp);
/** 修改员工数据**/
void update(Emp emp);
/** 删除员工数据**/
void delete(int empno);
}
3.8.5 映射类
添加实体类Emp和数据库emp表的映射类
package com.moxuan.mapper;
import com.moxuan.entity.Emp;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
public class EmpRowMapper implements RowMapper<Emp> {
@Override
public Emp mapRow(ResultSet rs, int rowNum) throws SQLException {
Emp e = new Emp();
e.setEmpno(rs.getInt("empno"));
e.setEname(rs.getString("ename"));
e.setJob(rs.getString("job"));
e.setManager(rs.getInt("manager"));
e.setHiredate(rs.getDate("hiredate"));
e.setSalary(rs.getDouble("salary"));
e.setComm(rs.getDouble("comm"));
e.setDeptno(rs.getInt("deptno"));
return e;
}
}
3.8.6 Dao实现类EmpDaoImpl
package com.moxuan.dao.impl;
import com.moxuan.dao.EmpDao;
import com.moxuan.entity.Emp;
import com.moxuan.mapper.EmpRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import java.util.List;
@Repository
public class EmpDaoImpl implements EmpDao {
@Resource // 注入jdbcTemplate对象
private JdbcTemplate jdbcTemplate;
@Override
public List<Emp> findAll() {
String sql = "select * from emp";
RowMapper<Emp> rowMapper = new EmpRowMapper();
// query() 查询结果是一个列表
return jdbcTemplate.query(sql,rowMapper);
}
@Override
public Emp findEmpByEmpno(int empno) {
String sql = "select * from emp where empno=?";
RowMapper<Emp> rowMapper = new EmpRowMapper();
return jdbcTemplate.queryForObject(sql,rowMapper,empno);
}
@Override
public void save(Emp emp) {
String sql = "insert into emp (ename,job,manager,hiredate,salary,comm,deptno) values(?,?,?,?,?,?,?)";
Object[] params = {
emp.getEname(),
emp.getJob(),
emp.getManager(),
emp.getHiredate(),
emp.getSalary(),
emp.getComm(),
emp.getDeptno()
};
jdbcTemplate.update(sql,params);
}
@Override
public void update(Emp emp) {
String sql = "update emp set ename=?,job=?,manager=?,hiredate=?,salary=?,comm=?,deptno=? where empno=?";
Object[] params = {
emp.getEname(),
emp.getJob(),
emp.getManager(),
emp.getHiredate(),
emp.getSalary(),
emp.getComm(),
emp.getDeptno(),
emp.getEmpno()
};
jdbcTemplate.update(sql,params);
}
@Override
public void delete(int empno) {
String sql = "delete from emp where empno=?";
jdbcTemplate.update(sql,empno);
}
}
3.8.7 测试类
package com.moxuan;
import com.moxuan.dao.EmpDao;
import com.moxuan.dao.impl.EmpDaoImpl;
import com.moxuan.entity.Emp;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractXmlApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.sql.Date;
import java.util.List;
public class JDBCTest {
/**
* 测试查询所有员工
*/
@Test
public void test01(){
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
EmpDaoImpl dao = context.getBean("empDaoImpl",EmpDaoImpl.class);
List<Emp> empList = dao.findAll();
for (Emp emp:empList){
System.out.println(emp);
}
}
/**
* 测试根据员工号查询员工
*/
@Test
public void test02(){
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
EmpDaoImpl dao = context.getBean("empDaoImpl",EmpDaoImpl.class);
System.out.println(dao.findEmpByEmpno(3));
}
@Test
public void test03(){
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
EmpDaoImpl dao = context.getBean("empDaoImpl",EmpDaoImpl.class);
Emp emp = new Emp();
emp.setEname("孙尚香");
emp.setManager(3);
emp.setJob("业务人员");
emp.setHiredate(new Date(System.currentTimeMillis()));
emp.setSalary(5000);
dao.save(emp);
// 调用测试查询所有的方法,查看是否操作成功
test01();
}
/**
* 测试修改员工的方法
*/
@Test
public void test04(){
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
EmpDao dao = context.getBean("empDaoImpl",EmpDaoImpl.class);
Emp emp = dao.findEmpByEmpno(3);
System.out.println(emp);
emp.setEname("江湖骗子");
dao.update(emp);
emp = dao.findEmpByEmpno(3);
System.out.println(emp);
}
@Test
public void test05(){
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
EmpDao dao = context.getBean("empDaoImpl",EmpDaoImpl.class);
System.out.println("--------------删除前-----------");
test01();
dao.delete(4);
System.out.println("--------------删除后-----------");
test01();
}
}
四、Dao继承JdbcDaoSupport模式(了解)
实现方式:
DAO继承JdbcDaoSupport,通过getJdbcTemplate()方法获取JdbcTemplate对象,需要在DAO实现类中注入一个DataSource对象来完成JdbcTemplate对象的实例化。
4.1 修改Dao实现类
>> 新建一个EmpExtendsDaoImpl继承JdbcSupport
package com.moxuan.dao.impl;
import com.moxuan.dao.EmpDao;
import com.moxuan.entity.Emp;
import com.moxuan.mapper.EmpRowMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;
import javax.sql.DataSource;
import java.util.List;
@Repository
public class EmpExtendsDaoImpl extends JdbcDaoSupport implements EmpDao {
@Override
public List<Emp> findAll() {
String sql = "select * from emp";
RowMapper<Emp> rowMapper = new EmpRowMapper();
// query() 查询结果是一个列表
return super.getJdbcTemplate().query(sql,rowMapper);
}
@Override
public Emp findEmpByEmpno(int empno) {
String sql = "select * from emp where empno=?";
RowMapper<Emp> rowMapper = new EmpRowMapper();
return super.getJdbcTemplate().queryForObject(sql,rowMapper,empno);
}
@Override
public void save(Emp emp) {
String sql = "insert into emp (ename,job,manager,hiredate,salary,comm,deptno) values(?,?,?,?,?,?,?)";
Object[] params = {
emp.getEname(),
emp.getJob(),
emp.getManager(),
emp.getHiredate(),
emp.getSalary(),
emp.getComm(),
emp.getDeptno()
};
super.getJdbcTemplate().update(sql,params);
}
@Override
public void update(Emp emp) {
String sql = "update emp set ename=?,job=?,manager=?,hiredate=?,salary=?,comm=?,deptno=? where empno=?";
Object[] params = {
emp.getEname(),
emp.getJob(),
emp.getManager(),
emp.getHiredate(),
emp.getSalary(),
emp.getComm(),
emp.getDeptno(),
emp.getEmpno()
};
super.getJdbcTemplate().update(sql,params);
}
@Override
public void delete(int empno) {
String sql = "delete from emp where empno=?";
super.getJdbcTemplate().update(sql,empno);
}
}
=== 说明 ===
- 因为只有整合的方式发生变化,方法的业务逻辑没有变化,和上面的案例的代码一样。
- 和上面不继承的区别在于,此类不需要添加JdbcTemplate属性。操作数据库的时候使用super.getJdbcTemplate()方法获取父类的JdbcTemplate对象。
4.2 修改application.xml配置
>> 在application.xml中添加配置
<!-- 注入dataSource对象: 继承JdbcSupport模式-->
<bean class="com.moxuan.dao.impl.EmpExtendsDaoImpl" id="empExtendsDaoImpl">
<property name="dataSource" ref="ds"></property>
</bean>
4.3 修改测试类
>> 在测试类修改测试方法
package com.moxuan;
import com.moxuan.dao.EmpDao;
import com.moxuan.dao.impl.EmpDaoImpl;
import com.moxuan.entity.Emp;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javax.sql.DataSource;
import java.sql.Date;
import java.util.List;
/**
* 测试继承JdbcSupport的方式
*/
public class JDBCExtendsTest {
/**
* 测试查询所有员工
*/
@Test
public void test01(){
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
EmpDao dao = context.getBean("empExtendsDaoImpl",EmpDao.class);
List<Emp> empList = dao.findAll();
for (Emp emp:empList){
System.out.println(emp);
}
}
/**
* 测试根据员工号查询员工
*/
@Test
public void test02(){
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
EmpDao dao = context.getBean("empExtendsDaoImpl",EmpDaoImpl.class);
System.out.println(dao.findEmpByEmpno(3));
}
@Test
public void test03(){
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
EmpDao dao = context.getBean("empExtendsDaoImpl",EmpDaoImpl.class);
Emp emp = new Emp();
emp.setEname("孙尚香");
emp.setManager(3);
emp.setJob("业务人员");
emp.setHiredate(new Date(System.currentTimeMillis()));
emp.setSalary(5000);
dao.save(emp);
// 调用测试查询所有的方法,查看是否操作成功
test01();
}
/**
* 测试修改员工的方法
*/
@Test
public void test04(){
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
EmpDao dao = context.getBean("empExtendsDaoImpl",EmpDaoImpl.class);
Emp emp = dao.findEmpByEmpno(3);
System.out.println(emp);
emp.setEname("江湖骗子");
dao.update(emp);
emp = dao.findEmpByEmpno(3);
System.out.println(emp);
}
@Test
public void test05(){
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
EmpDao dao = context.getBean("empExtendsDaoImpl",EmpDaoImpl.class);
System.out.println("--------------删除前-----------");
test01();
dao.delete(4);
System.out.println("--------------删除后-----------");
test01();
}
}
=== 说明 ===
- 注意在测试类中切换新建的EmpExtendsDaoImpl,其他的和不继承的方式一样。
=== 总结 ===
基于JDBC技术编写DAO组件可以采用下面两种模式,一种是继承JdbcSupport的方式,一种是不继承JdbcSupport的方式,使用较多的是不继承的方式。