• Spring声明式事务基础_JdbcTemplate


    Spring_JdbcTemplate

    关注公众号“小东方不败”,码字不易!

    Spring的学习主要分为3大块:IOC(包括DI),AOP,声明式事务。

    本篇主要记录声明式事务的基础:【Spring框架本身】连接数据库相关的操作。

    JdbcTemplatemybatis很像,但是性能和SQL解耦方面还是有很大区别的。

    Spring整合mybatis在技术实现上来说,是必要的。但是对于JdbcTemplate的学习,作为学习Spring框架学习的补充,也是必要的。

    0x01_JdbcTemplate介绍

    JdbcTemplatespring框架中提供的一个对象,是对原始繁琐的Jdbc API对象的简单封装。spring框架为我们提供了很多的操作模板类。例如:操作关系型数据的JdbcTemplate和操作nosql数据库的RedisTemplate,操作消息队列的JmsTemplate等等。

    话不多说,直接上手试试。

    0x02_创建项目

    创建一个新的模块:

    image-20221105000634377

    我目前用的IDEA版本是官网最新版。如果是2020.3版本的idea(之前我一直用这个版本,所以比较了解),只需要创建一个标准的maven项目即可,不需要选任何archetype。

    创建项目完成之后,请务必确保下面的配置:

    【1】maven:(最好是自己本地的maven)

    image-20221105121629334

    【2】maven的JDK for importer

    之前因为这个出现过不可描述的问题,所以每一次我都改成自己的JDK .

    image-20221105121753460

    【3】在用到lombok的项目中需要勾选:Enable annotation processing

    image-20221105121925077

    0x03_导入依赖

    <dependencies>
    
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-contextartifactId>
            <version>5.3.23version>
        dependency>
    
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-aspectsartifactId>
            <version>5.3.23version>
        dependency>
    
        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>druidartifactId>
            <version>1.1.10version>
        dependency>
    
        <dependency>
            <groupId>aopalliancegroupId>
            <artifactId>aopallianceartifactId>
            <version>1.0version>
        dependency>
    
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>8.0.30version>
        dependency>
    
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-jdbcartifactId>
            <version>5.3.23version>
        dependency>
    
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-ormartifactId>
            <version>5.3.23version>
        dependency>
    
        <dependency>
            <groupId>commons-logginggroupId>
            <artifactId>commons-loggingartifactId>
            <version>1.2version>
        dependency>
    
    
        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-txartifactId>
            <version>5.3.23version>
        dependency>
    
    
        
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.13.2version>
            <scope>testscope>
        dependency>
    
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <version>1.18.24version>
            <scope>providedscope>
        dependency>
        
    dependencies>
    
    
    • 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

    注意:如果配置了阿里或者华为的镜像还是下载有问题的话,建议多install几次依赖,这个没办法。

    0x04_resources目录下的配置文件

    1.jdbc.properties

    这个以前写过很多次,我直接拿来用了:

    根据你的实际环境更改参数,比如数据库的账户名和密码,你的数据库名。

    如果你的mysql版本不是8,那么下面url中的参数可能还需要你google进行更改。

    jdbc_username=root
    jdbc_password=root
    jdbc_driver=com.mysql.cj.jdbc.Driver
    jdbc_url=jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
    
    • 1
    • 2
    • 3
    • 4

    这个文件不要留多余的空格和换行。

    2.applicationContext.xml

    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:c="http://www.springframework.org/schema/c"
           xmlns:util="http://www.springframework.org/schema/util"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/util
           http://www.springframework.org/schema/util/spring-util.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd
    ">
    
        <context:component-scan base-package="com.bones"/>
    
        <context:property-placeholder location="classpath:jdbc.properties"/>
    
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="url" value="${jdbc_url}"/>
            <property name="username" value="${jdbc_username}"/>
            <property name="password" value="${jdbc_password}"/>
            <property name="driverClassName" value="${jdbc_driver}"/>
        bean>
    
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    
            <property name="dataSource" ref="dataSource"/>
        bean>
    beans>
    
    • 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

    注:

    上面的最后是注入JdbcTemplate对象,其中需要配置druid数据源(连接池),即配置初始化JdbcTemplate对象时,需要的DataSource对象:

    什么意思呢?看一下JdbcTemplate类的一部分源码就可以理解了:

    初始化JdbcTemplate,会走构造方法,这点毋庸置疑吧:

    	public JdbcTemplate(DataSource dataSource) {
    		setDataSource(dataSource);
    		afterPropertiesSet();
    	}
    
    • 1
    • 2
    • 3
    • 4

    走构造方法的第一步就是设置数据源setDataSource(dataSource);,所以要将druid数据源设置为JdbcTemplate的数据源,则只需要调用set方法,所以就有了:

    <property name="dataSource" ref="dataSource"/>
    
    • 1

    0x05_搭建项目结构

    数据库表的创建

    由于sql文件比较大,可以去github下载:https://github.com/kirsten-1/sqlFile/blob/main/mydb.sql

    实体类

    com.bones.pojo.Emp

    package com.bones.pojo;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import java.io.Serializable;
    import java.util.Date;
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Emp implements Serializable {
        private Integer empno;
        private String ename;
        private String job;
        private Integer mgr;//上级的员工编号
        private Date hiredate;
        private Double sal;
        private Double comm;//补助金
        private Integer deptno;//部门编号
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    dao层

    com.bones.dao.EmpDaocom.bones.dao.impl.EmpDaoImpl

    EmpDao

    package com.bones.dao;
    
    import org.springframework.stereoty
    
    • 1
    • 2
    • 3

    EmpDaoImpl

    package com.bones.dao.impl;
    
    import com.bones.dao.EmpDao;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public class EmpDaoImpl implements EmpDao {
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    service层

    com.bones.service.EmpServicecom.bones.service.impl.EmpServiceImpl

    EmpService

    package com.bones.service;
    
    public interface EmpService {
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    EmpServiceImpl

    package com.bones.service.impl;
    
    import com.bones.service.EmpService;
    import org.springframework.stereotype.Service;
    
    @Service
    public class EmpServiceImpl implements EmpService {
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    目前的项目结构是 :

    image-20221105140443825

    0x06_JdbcTemplate查询操作

    实验1:查询返回值类型为int

    EmpService接口:

    int findEmpcount();
    
    • 1

    EmpServiceImpl实现类:

    @Autowired
    private EmpDao empDao;
    
    @Override
    public int findEmpcount() {
        return empDao.findEmpcount();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    EmpDao接口:

     int findEmpcount();
    
    • 1

    EmpDaoImpl实现类

    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Override
    public int findEmpcount() {
        /** jdbcTemplate.queryForObject
         *  查询的返回值类型是int数字类型
         *  传入参数有2个
         *  第一个参数:sql语句
         *  第二个参数:返回值类型的class字节码文件
         */
        String sql = "select count(1) from emp";
        int count = jdbcTemplate.queryForObject(sql, Integer.class);
        return count;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    测试:

    /**
     * 对于JdbcTemplate的各种查询操作进行测试
     */
    @Test
    public void testJdbcTemplateQuery(){
        //获取容器
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        EmpServiceImpl empService = context.getBean(EmpServiceImpl.class);
        int empcount = empService.findEmpcount();
        System.out.println("empcount = " + empcount);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    测试结果:

    image-20221105141617245

    注意JdbcTemplate的 API:

    如果是查询结果的返回值类型是普通的基本数据类型:

    int count = jdbcTemplate.queryForObject(sql, Integer.class);
    
    • 1
    • 第一个参数:查询的sql语句
    • 第二个参数:返回值类型的class字节码文件
    • 还要注意Autowired一个JdbcTemplate对象(已经在applicationContext.xml文件中注入了这个对象)
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    
        <property name="dataSource" ref="dataSource"/>
    bean>
    
    • 1
    • 2
    • 3
    • 4

    实验2:查询返回值类型是单个的实体类对象:

    现在根据员工表的员工编号查询单个的emp:

    EmpService接口:

    Emp findEmpByEmpno(int empno);
    
    • 1

    EmpServiceImpl实现类:

    @Autowired
    private EmpDao empDao;
    @Override
    public Emp findEmpByEmpno(int empno) {
        return empDao.findEmpByEmpno(empno);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    EmpDao接口:

    Emp findEmpByEmpno(int empno);
    
    • 1

    EmpDaoImpl实现类:

    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Override
    public Emp findEmpByEmpno(int empno) {
        /**
         * 查询结果是单个的实体类对象   jdbcTemplate.queryForObject
         * 第一个参数:SQL语句
         * 第二个参数:RowMapper对象,因为RowMapper是一个接口,这里用Spring提供的RowMapper的实现类BeanPropertyRowMapper
         *          需要定义泛型和实体类的字节码文件
         * 第三个参数:SQL语句中的参数,一般是传进来的
         */
        String sql = "select * from emp where empno = ?";//底层用的是preparedStatement
        BeanPropertyRowMapper<Emp> mapper = new BeanPropertyRowMapper<>(Emp.class);
        Emp emp = jdbcTemplate.queryForObject(sql, mapper, empno);
        return emp;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    测试:

    @Test
    public void testJdbcTemplateQuery1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        EmpServiceImpl empService = context.getBean(EmpServiceImpl.class);
        Emp emp = empService.findEmpByEmpno(7369);
        System.out.println(emp);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    测试结果:

    image-20221105143150151

    注意:

    关键的API

    /**
         * 查询结果是单个的实体类对象   jdbcTemplate.queryForObject
         * 第一个参数:SQL语句
         * 第二个参数:RowMapper对象,因为RowMapper是一个接口,这里用Spring提供的RowMapper的实现类BeanPropertyRowMapper
         *          需要定义泛型和实体类的字节码文件
         * 第三个参数:SQL语句中的参数,一般是传进来的
         */
        String sql = "select * from emp where empno = ?";//底层用的是preparedStatement
        BeanPropertyRowMapper<Emp> mapper = new BeanPropertyRowMapper<>(Emp.class);
        Emp emp = jdbcTemplate.queryForObject(sql, mapper, empno);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    其中BeanPropertyRowMapperRowMapper接口的一个实现类,是由spring提供的一个类,需要传入参数:查询结果封装的实体类的泛型和字节码文件。

    实验3:查询返回值类型是List

    现在根据部门编号查询emp的List集合.

    EmpService接口:

    List<Emp> findEmpsByDeptno(int deptno);
    
    • 1

    EmpServiceImpl实现类

    @Override
    public List<Emp> findEmpsByDeptno(int deptno) {
        return empDao.findEmpsByDeptno(deptno);
    }
    
    • 1
    • 2
    • 3
    • 4

    EmpDao接口:

    List<Emp> findEmpsByDeptno(int deptno);
    
    • 1

    EmpDaoImpl实现类

    @Override
    public List<Emp> findEmpsByDeptno(int deptno) {
        String sql = "select * from emp where deptno = ?";
        BeanPropertyRowMapper<Emp> mapper = new BeanPropertyRowMapper<>(Emp.class);
        List<Emp> emps = jdbcTemplate.query(sql, mapper, deptno);
        return emps;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    测试方法:

    @Test
    public void testJdbcTemplateQuery2(){
        List<Emp> emps = empService.findEmpsByDeptno(10);
        emps.forEach(System.out::println);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    测试结果:

    image-20221105150423170

    注意:

    和查询单个的emp对象类似,也要用RoeMapper的对象:

    BeanPropertyRowMapper<Emp> mapper = new BeanPropertyRowMapper<>(Emp.class);
    
    • 1

    但是用的JdbcTemplate的API是:

    List emps = jdbcTemplate.query(sql, mapper, deptno);
    
    • 1
    • 第一个参数:SQL语句
    • 第二个参数:RowMapper对象,这里用的是Spring提供的RowMapper实现类BeanPropertyRowMapper,需要指定泛型和实体类的字节码文件。
    • 第三个参数SQL语句的需要传入的参数。

    0x07_JdbcTemplate增删改操作

    JdbcTemplate的增删改操作都是通过update方法完成的。

    其实对于JdbcTemplate的学习建议可以CV代码,因为比较简单。

    EmpService接口:

    int addEmp(Emp emp);
    
    int updateEmp(Emp emp);
    
    int deleteEmp(int empno);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    EmpServiceImpl实现类:

    @Autowired
    private EmpDao empDao;
    
    @Override
    public int addEmp(Emp emp) {
        return empDao.addEmp(emp);
    }
    
    @Override
    public int updateEmp(Emp emp) {
        return empDao.updateEmp(emp);
    }
    
    @Override
    public int deleteEmp(int empno) {
        return empDao.deleteEmp(empno);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    EmpDao接口:

    int addEmp(Emp emp);
    
    int updateEmp(Emp emp);
    
    int deleteEmp(int empno);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    EmpDaoImpl实现类:

    @Override
    public int addEmp(Emp emp) {
        String sql = "insert into emp values(DEFAULT,?,?,?,?,?,?,?)";
        Object[] args = {emp.getEname(),emp.getJob(),emp.getMgr(),emp.getHiredate(),emp.getSal(),emp.getComm(),emp.getDeptno()};
        return jdbcTemplate.update(sql, args);
    }
    
    @Override
    public int updateEmp(Emp emp) {
        String sql = "update emp set ename = ?,job = ?,mgr = ?,hiredate = ?,sal = ?,comm = ?,deptno = ? where empno = ?";
        Object[] args = {emp.getEname(),emp.getJob(),emp.getMgr(),emp.getHiredate(),emp.getSal(),emp.getComm(),emp.getDeptno(),emp.getEmpno()};
        return jdbcTemplate.update(sql, args);
    }
    
    @Override
    public int deleteEmp(int empno) {
        String sql = "delete from emp where empno = ?";
        return jdbcTemplate.update(sql,empno);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    测试方法:

    @Test
    public void testAddEmp(){
        int rows = empService.addEmp(new Emp(null, "Amy", "MANAGER", 7369, new Date(), 1900.0, 80.0, 10));
        System.out.println("rows = " + rows);
    }
    
    @Test
    public void testUpdateEmp(){
        int rows = empService.updateEmp(new Emp(7941, "Jack", "SALSMAN", 7521, new Date(), 2000.0, 70.0, 20));
        System.out.println("rows = " + rows);
    }
    
    @Test
    public void testDeleteEmp(){
        int rows = empService.deleteEmp(7941);
        System.out.println("rows = " + rows);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    0x08_JdbcTemplate_批操作

    批操作主要是:批量增加,批量修改,批量删除。

    下面的实验记录对dept表进行批量的增删改操作。

    实验

    DeptService接口

    package com.bones.service;
    
    import com.bones.pojo.Dept;
    
    import java.util.List;
    
    public interface DeptService {
        int[] batchAdd(List<Dept> depts);
    
        int[] batchUpdate(List<Dept> depts);
    
        int[] batchDelete(List<Integer> deptnos);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    DeptServiceImpl实现类

    package com.bones.service.impl;
    
    import com.bones.dao.DeptDao;
    import com.bones.pojo.Dept;
    import com.bones.service.DeptService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    @Service
    public class DeptServiceImpl implements DeptService {
        @Autowired
        private DeptDao deptDao;
        @Override
        public int[] batchAdd(List<Dept> depts) {
            return deptDao.batchAdd(depts);
        }
    
        @Override
        public int[] batchUpdate(List<Dept> depts) {
            return deptDao.batchUpdate(depts);
        }
    
        @Override
        public int[] batchDelete(List<Integer> deptnos) {
            return deptDao.batchDelete(deptnos);
        }
    }
    
    
    • 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

    DeptDao接口

    package com.bones.dao;
    
    import com.bones.pojo.Dept;
    
    import java.util.List;
    
    public interface DeptDao {
        int[] batchAdd(List<Dept> depts);
    
        int[] batchUpdate(List<Dept> depts);
    
        int[] batchDelete(List<Integer> deptnos);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    DeptDaoImpl实现类

    package com.bones.dao.impl;
    
    import com.bones.dao.DeptDao;
    import com.bones.pojo.Dept;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.stereotype.Repository;
    
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    
    @Repository
    public class DeptDaoImpl implements DeptDao {
        @Autowired
        private JdbcTemplate jdbcTemplate;
        @Override
        public int[] batchAdd(List<Dept> depts) {
            String sql = "insert into dept values(DEFAULT,?,?)";
            List<Object[]> args = new ArrayList<>();
            for (Dept dept : depts) {
                Object[] arg = {dept.getDname(),dept.getLoc()};
                args.add(arg);
            }
            return jdbcTemplate.batchUpdate(sql,args);
        }
    
        @Override
        public int[] batchUpdate(List<Dept> depts) {
            String sql = "update dept set dname = ?,loc = ? where deptno = ?";
            List<Object[]> args = new LinkedList<>();
            for (Dept dept : depts) {
                Object[] arg = {dept.getDname(),dept.getLoc(),dept.getDeptno()};
                args.add(arg);
            }
            return jdbcTemplate.batchUpdate(sql, args);
        }
    
        @Override
        public int[] batchDelete(List<Integer> deptnos) {
            String sql = "delete from dept where deptno = ?";
            List<Object[]> args = new ArrayList<>();
            for (int deptno : deptnos) {
                Object[] arg = {deptno};
                args.add(arg);
            }
            return jdbcTemplate.batchUpdate(sql,args);
        }
    }
    
    
    • 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

    测试方法

    package com.bones.test01;
    
    
    import com.bones.pojo.Dept;
    import com.bones.service.DeptService;
    import com.bones.service.impl.DeptServiceImpl;
    import com.bones.service.impl.EmpServiceImpl;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    public class Test2_TestJdbcTemplateBatch {
       ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
       DeptService deptService = context.getBean(DeptServiceImpl.class);
       @Test
       public void TestBatchAdd(){
          List<Dept> depts = new ArrayList<>();
          for (int i = 0; i < 5; i++) {
             depts.add(new Dept(null,"dname"+i,"loc"+i));
          }
          int[] ints = deptService.batchAdd(depts);
          System.out.println(Arrays.toString(ints));
       }
    
       @Test
       public void testBatchUpdate(){
          List<Dept> depts = new ArrayList<>();
          for (int i = 44; i < 50; i++) {
             depts.add(new Dept(i,"new_dname","new_loc"));
          }
          int[] ints = deptService.batchUpdate(depts);
          System.out.println(Arrays.toString(ints));
       }
    
       @Test
       public void testBatchDelete(){
          List<Integer> empnos = new ArrayList<>();
          for (int i = 44; i < 50; i++) {
             empnos.add(i);
          }
          int[] ints = deptService.batchDelete(empnos);
          System.out.println(Arrays.toString(ints));
       }
    
    }
    
    
    • 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

    总结

    对于JdbcTemplate增删改的操作都是通过API jdbcTemplate.batchUpdate(sql, args);来完成的。

    看一下jdbcTemplate.batchUpdate(sql, args);的源码:

    	@Override
    	public int[] batchUpdate(String sql, List<Object[]> batchArgs) throws DataAccessException {
    		return batchUpdate(sql, batchArgs, new int[0]);
    	}
    
    • 1
    • 2
    • 3
    • 4

    需要传入2个参数:

    • 第一个参数:sql语句
    • 第二个参数:List类型的对象,是对每一次操作的SQL语句中的参数封装成一个Object数组,数组中的每一个值都是SQL的?占位的参数。因为是批量操作,所以是List类型的数组。

    以上就是对JdbcTemplate对于数据库的基本操作。

    0x09_JdbcTemplate总结

    JdbcTemplate Spring JDBC核心包(core)中的核心类,它可以通过配置文件、注解、Java 配置类等形式获取数据库的相关信息,实现了对 JDBC 开发过程中的驱动加载、连接的开启和关闭、SQL 语句的创建与执行、异常处理、事务处理、数据类型转换等操作的封装。我们只要对其传入SQL 语句和必要的参数即可轻松进行 JDBC 编程。

    • 1.Spring对数据库的操作在jdbc上面做了深层次的封装,使用spring的注入功能,可以把DataSource注册到JdbcTemplate之中。

    这个就是在applicationContext.xml中配置的:

    
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    
        <property name="dataSource" ref="dataSource"/>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这里对于JdbcTemplate的配置,我用的是Druid数据源(连接池)

    • 2.JdbcTemplate主要提供以下方法:
    • query方法及queryForXXX(上面用的是queryForObject)方法:用于执行查询相关语句;

    • update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;

    其他API:(作为了解)

    方法说明
    public int update(String sql)用于执行新增、更新、删除等语句;sql:需要执行的 SQL 语句;args 表示需要传入到 SQL 语句中的参数。
    public int update(String sql,Object… args)
    public void execute(String sql)可以执行任意 SQL,一般用于执行 DDL 语句; sql:需要执行的 SQL 语句;action 表示执行完 SQL 语句后,要调用的函数。
    public T execute(String sql, PreparedStatementCallback action)
    public List query(String sql, RowMapper rowMapper, @Nullable Object… args)
    用于执行查询语句;sql:需要执行的 SQL 语句;rowMapper:用于确定返回的集合(List)的类型;args:表示需要传入到 SQL 语句的参数。
    public T queryForObject(String sql, RowMapper rowMapper, @Nullable Object… args)
    public int[] batchUpdate(String sql, List batchArgs, final int[] argTypes)用于批量执行新增、更新、删除等语句; sql:需要执行的 SQL 语句;argTypes:需要注入的 SQL 参数的 JDBC 类型;batchArgs:表示需要传入到 SQL 语句的参数。
    • 其他数据源:
        
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            
            <property name="url" value="${jdbc.url}"/>
            
            <property name="username" value="${jdbc.username}"/>
            
            <property name="password" value="${jdbc.password}"/>
            
            <property name="driverClassName" value="${jdbc.driver}"/>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    Spring 默认使用 DriverManagerDataSource 对数据库连接池进行管理,我们可以在 Spring 的 XML 配置文件中定义 DriverManagerDataSource 的 Bean,并注入到 JdbcTempate 的 Bean 中。

    建议使用druid 数据源。(就像我的例子)

  • 相关阅读:
    Exgcd扩展欧几里得
    【大学英语视听说上】Topic Presentation
    串口一直进空闲中断(并不是空闲就会一直中断) 清中断标志位没用
    利用Python和Selenium编程,实现定时自动检索特定网页,发现特定网页内容发生变化后,向管理员发送提醒邮件(一)
    Apollo 添加自己的地图并显示到DreamView
    maven的安装与配置
    volatile 无法保证原子性 案例展示
    LVGL使用GUI Guider配置STM32界面详细笔记教程
    Java经典面试题——equals和==的区别
    2023-9-14 最长上升子序列
  • 原文地址:https://blog.csdn.net/qq_51550750/article/details/127715765