• (十三)Spring之JdbcTemplate



    Spring学习目录

    上一篇:(十二)Spring IoC注解式开发

    下一篇:(十四)Spring之回顾代理模式
    JdbcTemplate是Spring提供的一个JDBC模板类,是对JDBC的封装,简化JDBC代码。
    当然,也可以不用,可以让Spring集成其它的ORM框架,例如:MyBatis、Hibernate等。
    先使用JdbcTemplate完成增删改查。

    环境

    数据库表:t_user
    请添加图片描述
    初始数据:
    请添加图片描述
    spring6里程碑版本的仓库
    依赖:spring context依赖、junit依赖、log4j2依赖
    log4j2.xml文件放到类路径下。
    使用JdbcTemplate需要再引入spring-jdbc依赖,以及mysql驱动:

    	<!--spring jdbc依赖-->
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>6.0.0-M2</version>
        </dependency>
        <!--mysql依赖-->
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.30</version>
        </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    准备实体类User:

    public class User {
        private Integer id;
        private String loginName;
        private String loginPwd;
    
        public User() {
        }
    
        public User(Integer id, String loginName, String loginPwd) {
            this.id = id;
            this.loginName = loginName;
            this.loginPwd = loginPwd;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", loginName='" + loginName + '\'' +
                    ", loginPwd='" + loginPwd + '\'' +
                    '}';
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public void setLoginName(String loginName) {
            this.loginName = loginName;
        }
    
        public void setLoginPwd(String loginPwd) {
            this.loginPwd = loginPwd;
        }
    }
    
    
    • 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

    编写Spring配置文件:创建spring.xml
    JdbcTemplate是Spring提供好的类,这类的完整类名是:org.springframework.jdbc.core.JdbcTemplate
    直接将这个类配置到Spring配置文件中,纳入Bean管理即可。

    <?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">
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"></bean>
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    通过源码我们可以看到,JdbcTemplate是继承jdbcAccessor,而jdbcAccessor有一个DataSource属性,这个属性是数据源,连接数据库需要Connection对象,而生成Connection对象是数据源负责的。所以我们需要给JdbcTemplate设置数据源属性。
    请添加图片描述

    请添加图片描述
    所有的数据源都是要实现javax.sql.DataSource接口的。这个数据源可以自己写一个,也可以用写好的,比如:阿里巴巴的德鲁伊连接池,c3p0,dbcp等。我们这里自己先手写一个数据源。
    创建数据源MyDataSource,实现DataSource接口,默认实现里面的方法:

    public class MyDataSource implements DataSource {
    
        private String driver;
    
        private String url;
    
        private String username;
    
        private String password;
    
        public void setDriver(String driver) {
            this.driver = driver;
        }
    
        public void setUrl(String url) {
            this.url = url;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        @Override
        public Connection getConnection() throws SQLException {
            Connection connection = null;
            try {
                Class.forName(driver);
                connection = DriverManager.getConnection(url,username,password);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return connection;
        }
    
        @Override
        public Connection getConnection(String username, String password) throws SQLException {
            return null;
        }
    
        @Override
        public PrintWriter getLogWriter() throws SQLException {
            return null;
        }
    
        @Override
        public void setLogWriter(PrintWriter out) throws SQLException {
    
        }
    
        @Override
        public void setLoginTimeout(int seconds) throws SQLException {
    
        }
    
        @Override
        public int getLoginTimeout() throws SQLException {
            return 0;
        }
    
        @Override
        public Logger getParentLogger() throws SQLFeatureNotSupportedException {
            return null;
        }
    
        @Override
        public <T> T unwrap(Class<T> iface) throws SQLException {
            return null;
        }
    
        @Override
        public boolean isWrapperFor(Class<?> iface) throws SQLException {
            return false;
        }
    }
    
    
    • 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

    写完数据源,我们需要把这个数据源传递给JdbcTemplate。因为JdbcTemplate中有一个DataSource属性:

    <?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">
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <!--这里需要数据源,也可以集成其他数据源-->
            <property name="dataSource" ref="myDataSource"/>
        </bean>
    
        <!--配置自己的数据源-->
        <bean id="myDataSource" class="com.jdbctemplate.bean.MyDataSource">
            <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mydbtest"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
        </bean>
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    测试JdbcTemplate是否已设置好:

        @Test
        public void testJdbc(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
            System.out.println(jdbcTemplate);
            System.out.println(jdbcTemplate.getDataSource());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    请添加图片描述
    环境准备完成

    新增、删除与修改数据

    在JdbcTemplate当中,insert,delete,update语句,都是调用update方法。
    update方法两个参数

    • 第一个参数是传sql语句
    • 第二个参数args是可变长参数,有几个问号,传几个值

    新增

    测试程序:

        @Test
        public void testInsert(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
            String sql = "insert into t_user(loginName,loginPwd) values(?,?)";
            int count = jdbcTemplate.update(sql, "张三", "123456");
            System.out.println(count);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    请添加图片描述
    新增成功,数据改变:
    请添加图片描述

    修改

    测试程序:

        @Test
        public void testUpdate(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
            String sql = "update t_user set loginName = ? , loginPwd = ? where id = ?";
    
            int count = jdbcTemplate.update(sql, "李四", "654321",7);
            System.out.println(count);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    请添加图片描述
    修改成功,数据改变:
    请添加图片描述

    删除

    测试程序:

        @Test
        public void testDelete(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
            String sql = "delete from t_user where id = ?";
    
            int count = jdbcTemplate.update(sql, 7);
            System.out.println(count);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    请添加图片描述
    删除成功。数据改变:
    请添加图片描述

    查询一个

    查询一个使用queryForObject方法,三个参数:

    • 第一个参数:sql语句
    • 第二个参数:映射器对象,在构造方法中指定映射的对象类型。
    • 第三个参数:可变长参数,给sql语句的占位符问号传值。

    查询一个对象

    测试程序:

        @Test
        public void testSelectOne(){
    
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
    
            String sql = "select * from t_user where id = ?";
            User user = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), 2);
            System.out.println(user);
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    请添加图片描述

    查询一个值

    有时候查询是一个值,例如总记录条数:
    测试程序:

        @Test
        public void testSelectOneValue(){
            // 获取JdbcTemplate对象
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
            // 执行select
            String sql = "select count(1) from t_user";
            Integer count = jdbcTemplate.queryForObject(sql, int.class); // 这里用Integer.class也可以
            System.out.println("总记录条数:" + count);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    请添加图片描述

    查询多个对象

    查询结构返回多个对象,使用query方法,与queryForObject方法用法差不多,只是query方法的返回值是一个List集合
    测试程序:

        @Test
        public void testSelectAll(){
            // 获取JdbcTemplate对象
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
            // 执行select
            String sql = "select * from t_user";
            //查询多个是调用query方法。
            List<User> users = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));
            System.out.println(users);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    请添加图片描述

    批量操作

    批量添加、批量修改、批量删除都是使用batchUpdate方法,该方法返回值是一个int集合,表示操作的数据成功与否,有两个参数:

    • 第一个参数:sql语句
    • 第二个参数:需要操作的list集合,主要给问号赋值

    批量添加

    测试程序:

        @Test
        public void testAddBatch(){
            // 获取JdbcTemplate对象
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
            // 批量添加
            String sql = "insert into t_user(id,loginName,loginPwd) values(?,?,?)";
            //这里需要注意的是问号顺序
            Object[] objs1 = {null, "张三", "123"};
            Object[] objs2 = {null, "李四", "321"};
            Object[] objs3 = {null, "王五", "231"};
            List<Object[]> list = new ArrayList<>();
            list.add(objs1);
            list.add(objs2);
            list.add(objs3);
    
            int[] count = jdbcTemplate.batchUpdate(sql, list);
            System.out.println(Arrays.toString(count));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    请添加图片描述
    运行成功,数据改变:
    请添加图片描述

    批量修改

    测试程序:

        @Test
        public void testUpdateBatch(){
            // 获取JdbcTemplate对象
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
            // 批量修改
            String sql = "update t_user set loginName = ?, loginPwd = ? where id = ?";
            //这里需要注意的是问号顺序
            Object[] objs1 = {"张三11", "546", 8};
            Object[] objs2 = {"李四22", "654", 9};
            Object[] objs3 = {"王五33", "456", 10};
            List<Object[]> list = new ArrayList<>();
            list.add(objs1);
            list.add(objs2);
            list.add(objs3);
    
            int[] count = jdbcTemplate.batchUpdate(sql, list);
            System.out.println(Arrays.toString(count));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    请添加图片描述
    运行成功,数据改变:
    请添加图片描述

    批量删除

    测试程序:

        @Test
        public void testDeleteBatch(){
            // 获取JdbcTemplate对象
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
            // 批量删除
            String sql = "delete from t_user where id = ?";
            Object[] objs1 = {8};
            Object[] objs2 = {9};
            Object[] objs3 = {10};
            List<Object[]> list = new ArrayList<>();
            list.add(objs1);
            list.add(objs2);
            list.add(objs3);
            int[] count = jdbcTemplate.batchUpdate(sql, list);
            System.out.println(Arrays.toString(count));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    请添加图片描述
    运行成功,数据改变:请添加图片描述

    使用回调函数

    如果想参与更加细节的jdbc代码可以使用回调函数
    execute方法,两个参数:

    • 第一个:sql语句
    • 第二个:回调接口PreparedStatementCallback,需实现doInPreparedStatement方法

    测试成功:

        @Test
        public void testCallback(){
            // 获取JdbcTemplate对象
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
            String sql = "select * from t_user where id = ?";
            User user = jdbcTemplate.execute(sql, new PreparedStatementCallback<User>() {
                @Override
                public User doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
                    User user = null;
                    ps.setInt(1, 1);
                    ResultSet rs = ps.executeQuery();
                    if (rs.next()) {
                        user = new User();
                        user.setId(rs.getInt("id"));
                        user.setLoginName(rs.getString("loginName"));
                        user.setLoginPwd(rs.getString("loginPwd"));
                    }
                    return user;
                }
            });
            System.out.println(user);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    请添加图片描述

    使用德鲁伊连接池

    之前数据源是用我们自己写的。也可以使用别人写好的。例如比较牛的德鲁伊连接池。
    第一步:引入德鲁伊连接池的依赖。

    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.8</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    第二步:将德鲁伊中的数据源配置到spring配置文件中。和配置我们自己写的一样。
    创建一个新的配置文件spring2.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">
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <!--这里需要数据源,也可以集成其他数据源-->
            <property name="dataSource" ref="druidDataSource"/>
        </bean>
    
        <!--配置德鲁伊数据源-->
        <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mydbtest"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
        </bean>
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    测试程序:

        @Test
        public void testSelectAllForDruid(){
            // 获取JdbcTemplate对象
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring2.xml");
            JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
            
            String sql = "select * from t_user";
            
            List<User> users = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));
            System.out.println(users);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    运行可以发现使用了INFO com.alibaba.druid.pool.DruidDataSource - {dataSource-1} inited(德鲁伊连接池)
    请添加图片描述

  • 相关阅读:
    Java多线程之8锁案例
    MySQL: 锁
    【头歌】——抓取Ethernet包(计算机网络)
    OneNote 教程,如何在 OneNote 中使用绘图和批注?
    React入门到精通学习路线
    岩土工程监测利器:多通道振弦数据记录仪应用隧道监测
    基于RFID技术的烟草供应链数字化管理方案
    瑞吉外卖实战项目全攻略——第二天
    Qt OPC UA初体验
    命令模式:将请求封装为对象
  • 原文地址:https://blog.csdn.net/weixin_45832694/article/details/128005160