Spring框架IOC使用SpringJdbcTemplate

一、JdbcTemplate的简介

     SpringJdbcTemplate是Spring框架中对Jdbc的封装。其提供了常用的数据库操作方法,包括:

  • update (更新数据,包括增删改)
  • queryForObject (查询单行)
  • query (查询多行)

并且,JdbcTemplate提供了对查询结果进行封装的方法,这极大的减少了我们花在封装返回结果集的工作量。

二、JdbcTemplate的使用

1、导入依赖
     要使用JdbcTemplate,首先要做的就是导入所需的依赖。这里使用的是Maven工程的方式导入,如果不是Maven工程请自行下载相关的Jar包导入即可。

        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-contextartifactId>
            <version>5.2.6.RELEASEversion>
        dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-jdbcartifactId>
            <version>5.2.6.RELEASEversion>
        dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-txartifactId>
            <version>5.2.6.RELEASEversion>
        dependency>

        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>8.0.17version>
        dependency>

2、创建jdbcTemplate对象

     创建JdbcTemplate对象之间呢,我们打开它所在的类,发现有三个构造方法,这里选择带一个参数的构造方法。既然选择了这个方法,那创建JdbcTemplate对象之前应该先获取一个DateSource对象。DateSource对象我们都很熟悉了,它里面包含了用户要连接数据库的相关信息。

Spring框架IOC使用SpringJdbcTemplate_第1张图片

		// 准备数据源:spring内置数据源,DriverManagerDataSource
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/eesy?serverTimezone=GMT");
        ds.setUsername("root");
        ds.setPassword("811236");
		//1. 创建对象
        JdbcTemplate jt = new JdbcTemplate(ds);

3、 使用JdbcTemplate对象执行操作
     这里使用的是JdbcTemplate的query方法,这个方法有很多的重载。我们使用的是带sql语句和RowMapper参数的这一个。RowMapper是一个接口,要使用的话,我们还要实现它的mapRow方法。其中的泛型是要封装的实体类,参数中的ResultSet是键值对形式的结果集,i表示第几行结果,从0开始。

        //2. 执行操作
        List<Account> accounts = jt.query("select * from account", new RowMapper<Account>() {
            public Account mapRow(ResultSet resultSet, int i) throws SQLException {
                Account account = new Account();
                account.setId(resultSet.getInt("id"));
                account.setName(resultSet.getString("name"));
                account.setMoney(resultSet.getFloat("money"));
                return account;
            }
        });
        for (Account account : accounts) {
            System.out.println(account);
        }

     经过上面一顿操作,我们已经可以使用JdbcTemplate对象来查询数据库中的数据了。
     但是,上面的使用是有问题的。首先DataSource是写死在代码中的无法在运行的过程中修改。其次JdbcTemplate对象是使用new关键字new出来的。最后对结果集的封装代码还是要我们自己手动去完成。
Spring框架IOC使用SpringJdbcTemplate_第2张图片

  • 完整的使用类
package cn.snowing.jdbctemplate;

import cn.snowing.domain.Account;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

public class JdbcTemplateDemo1 {
    public static void main(String[] args) {
        // 准备数据源:spring内置数据源,DriverManagerDataSource
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/eesy?serverTimezone=GMT");
        ds.setUsername("root");
        ds.setPassword("811236");
        //1. 创建对象
        JdbcTemplate jt = new JdbcTemplate(ds);
        //2. 执行操作
        List<Account> accounts = jt.query("select * from account", new RowMapper<Account>() {
            public Account mapRow(ResultSet resultSet, int i) throws SQLException {
                Account account = new Account();
                account.setId(resultSet.getInt("id"));
                account.setName(resultSet.getString("name"));
                account.setMoney(resultSet.getFloat("money"));
                return account;
            }
        });
        for (Account account : accounts) {
            System.out.println(account);
        }
    }
}

三、JdbcTemplate使用的改进

     其实在导入Jar的时候,我们导入整个spring.framework的内容,但是在上面的代码中,我们仅仅只是用到了其中的jdbc相关的内容。并没有用到spring的核心容器来做IOC,也没有将依赖注入交给spring来处理。

     此外,在上面的操作中,我们是把使用和定义都放在了同一个类中,这明显违背了职责单一性原则。因此,首先要做的就是将责任分离。

     在实际的开发当中,通常将对数据库操作的方法放在Dao层。基于面向接口编程的原则,这里首先定义一个Dao的接口,然后再实现这个接口。这个接口应当包含对数据操作的常用方法,比如常用的增删改查方法等等。这里只是描述问题,因此只是定义了三个方法。

Dao接口

package cn.snowing.dao;

import cn.snowing.domain.Account;

/**
 * 账户的持久层接口
 */
public interface IAccountDao {
    /**
     * 根据id查询账户
     * @param id
     * @return
     */
    Account findAccountById(Integer id);

    /**
     * 根据名称查询账户
     * @param name
     * @return
     */
    Account findAccountByName(String name);

    /**
     * 更新账户
     * @param account
     */
    void updateAccount(Account account);

}

Dao实现类

package cn.snowing.dao.impl;

import cn.snowing.dao.IAccountDao;
import cn.snowing.domain.Account;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;


import java.util.List;

/**
 * 账户的持久层实现类
 */
public class AccountDaoImpl implements IAccountDao {
    private JdbcTemplate jdbcTemplate;

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public Account findAccountById(Integer id) {
        List<Account> accounts = jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<Account>(Account.class), id);
        return accounts.isEmpty()?null:accounts.get(0);
    }

    public Account findAccountByName(String name) {
        List<Account> accounts = jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<Account>(Account.class), name);
        if (accounts.isEmpty()){
            return null;
        }

        if (accounts.size()>1){
            throw new RuntimeException("结果集不唯一");
        }

        return accounts.get(0);
    }

    public void updateAccount(Account account) {
        jdbcTemplate.update("update account set name = ?, money = ? where id = ?"
                , account.getName(), account.getMoney(), account.getId());
    }
}

     接口比较简单,我们就不看了,这进而直接看实现类。实现类定义了jdbctemplate成员变量,类中的所有方法都使用这个对象来执行Sql语句。但是这里并没有创建这个对象。

     这就是我们上面说的要解决的问题。我们需要将jdbcTemplate对象的创建交给Spring框架来完成。要想spring框架帮我们创建对象,就要进行相应的配置。那我们就配置一个jdbcTemplate对象,但是发现jdbcTemplate对象需要一个DataSource对象。所以,还需要配置一个DataSource对象,然后通过property中的ref属性来引用。这样一来DataSource写死和new JdbcTemplate对象的问题都得到了解决。


<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource">property>
    bean>

    
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/eesy?serverTimezone=GMT"/>
        <property name="username" value="root"/>
        <property name="password" value="811236"/>
    bean>
beans>

     完成了上面的配置,那么DataSource对象有了,创建jdbcTemplate的参数也就有了。但是执行查询方法时,封装结果集的方法还没有讲。其实上面的代码中已经给出了,BeanPropertyRowMapperRowMapper的一个实现类。我们只需要向其提供泛型和字节码,就能够自动的帮我们实现对结果集的封装。而不需要我们再写RowMapper的实现类。

     经过上面的操作,貌似所有的操作都已经完成了。那就写一个测试类吧。等等,我们要使用这个dao的实现类是不是还要new一个dao实现类的对象?那不行,我千辛万苦才解决new一个jdbcTemplate对象的问题,结果又来一个new dao实现类的操作? 这显然不合理,怎么办呢?当然还是交给spring框架来处理。

     在上面的bean.xml中加入以下内容,这样dao实现类的对象也加入到了spring的核心容器中。需要使用这个对象时直接从spring核心容器中拿就可以。

    
    <bean id="accountDao" class="cn.snowing.dao.impl.AccountDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    bean>

下面就是测试类。

package cn.snowing.jdbctemplate;

import cn.snowing.dao.IAccountDao;
import cn.snowing.dao.impl.AccountDaoImpl;
import cn.snowing.domain.Account;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;

public class JdbcTemplateDemo4 {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        IAccountDao accountDao = ac.getBean("accountDao", IAccountDao.class);
        //2. 执行操作
        Account account = accountDao.findAccountByName("bbb");
        System.out.println(account);
        account.setMoney(10010f);
        accountDao.updateAccount(account);
        account = accountDao.findAccountById(account.getId());
        System.out.println(account);
    }
}

Spring框架IOC使用SpringJdbcTemplate_第3张图片

你可能感兴趣的:(spring)