一篇文章教你搞定Spring整和JDBC的多种方式

一、概述

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 配置数据源

  1. 数据源文件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

  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">

    <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.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());
}

>> 运行效果

=== 注意 ===

  1. query() 可以用来做列表的查询,第一个参数是需要执行的sql语句,第二个参数是映射类对象
  2. 映射类中,让数据库表中的字段和实体类类属性对应起来,这样做查询时,会将数据库中字段对应的数据暂存到实体类对象的属性中。
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));
}

>> 运行效果:

=== 说明 ===

  1. queryForObject() 当查询单个对象的时候可以使用。第一个参数是需要执行的sql语句,第二个参数是映射类对象。
  2. 如果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);

    }

}

=== 说明 ===

  1. 因为只有整合的方式发生变化,方法的业务逻辑没有变化,和上面的案例的代码一样。
  2. 和上面不继承的区别在于,此类不需要添加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();
    }
}

=== 说明 ===

  1. 注意在测试类中切换新建的EmpExtendsDaoImpl,其他的和不继承的方式一样。

=== 总结 ===

基于JDBC技术编写DAO组件可以采用下面两种模式,一种是继承JdbcSupport的方式,一种是不继承JdbcSupport的方式,使用较多的是不继承的方式。

相关推荐
CoderJia程序员甲2 分钟前
重学SpringBoot3-Spring WebFlux之HttpHandler和HttpServer
java·spring boot·reactor·1024程序员节
岁岁岁平安4 分钟前
mysql上课总结(2)(DCL的所有操作总结、命令行快速启动/关闭mysql服务)
数据库·mysql·命令行·权限·dcl·localhost
Boboboobo4 分钟前
记MySQL下一次DEPENDENT SUBQUERY的优化
数据库·sql·mysql·性能优化
chuk.10 分钟前
【JAVA】利用钉钉自定义机器人监控NACOS服务,实现实时下线通知
java·机器人·钉钉
weixi_kelaile52010 分钟前
ai智能语音电销机器人可以做哪些事情?
java·linux·服务器·人工智能·机器人·云计算·腾讯云
hummhumm13 分钟前
Oracle 第13章:事务处理
开发语言·数据库·后端·python·sql·oracle·database
书鸢123617 分钟前
力扣每日一题合集
java·算法·leetcode
小黑0319 分钟前
Spark SQL
大数据·sql·spark
魔道不误砍柴功20 分钟前
Java 中 String str = new String(“hello“); 里面创建了几个对象?
java·开发语言·string·new
菜菜-plus1 小时前
微服务技术,SpringCloudAlibaba,Redis,RocketMQ,Docker,分库分表
java·spring boot·redis·spring cloud·docker·微服务·java-rocketmq