(十三)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>

准备实体类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;
    }
}

编写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>

通过源码我们可以看到,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;
    }
}

写完数据源,我们需要把这个数据源传递给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>

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

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

新增、删除与修改数据

在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);
    }

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

修改

测试程序:

    @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);
    }

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

删除

测试程序:

    @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);
    }

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

查询一个

查询一个使用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);
    }

请添加图片描述

查询一个值

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

    @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);
    }

请添加图片描述

查询多个对象

查询结构返回多个对象,使用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);
    }

请添加图片描述

批量操作

批量添加、批量修改、批量删除都是使用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));
    }

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

批量修改

测试程序:

    @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));
    }

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

批量删除

测试程序:

    @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));
    }

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

使用回调函数

如果想参与更加细节的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);
    }

请添加图片描述

使用德鲁伊连接池

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

<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid</artifactId>
  <version>1.1.8</version>
</dependency>

第二步:将德鲁伊中的数据源配置到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>

测试程序:

    @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);
    }

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

忆亦何为

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值