spring的jdbcTemplate操作(用在dao层)

spring框架是一个一站式框架,在每一层都提供了解决技术:在Dao层是使用了jdbcTemplate。

spring针对不同的持久化技术都提供了不同的模板。

Spring JDBC

  Spring的JDBC模板负责提供数据库资源的管理和错误处理,大大简化了开发人员对数据库操作,使得开发人员可以从繁琐的数据库操作中解脱出来。

Spring jdbcTemplate的解析

  针对数据库的操作,Spring框架提供了jdbcTemplate类,该类是Spring框架数据层的基础,其他更高层次的抽象类是构建在JdbcTemplate类之上,可以说,JdbcTemplate是Spring JDBC的核心类。

  JdbcTemplata类的继承关系十分简单,它继承了JdbcAccessor抽象类,同时实现了JdbcOperations接口。

            

spring多数据库 spring 数据库_数据库

 

  JdbcAccessor的设计中,对DataSource数据源进行了管理和配置,JdbcOperation接口定义中,定义了通过JDBC操作数据库的基本方法,而核心类JdbcTemplate提供了这些接口方法的实现。

 

 Spring JDBC的配置

  Spring JDBC模板主要是有四个包组成,分别是core(核心包),dataSource(数据源包),object(对象包),support(支持包),Spring对数据库的操作都封装在了这几个包中,而想要使用JDBC,就需要对其进行配置,在Spring中,JDBC的配置是在Spring的配置文件applicationContext.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-4.3.xsd">


     <!-- 配置数据源 -->
     <bean id="dataSource" 
         class="org.springframework.jdbc.datasource.DriverManagerDataSource">
         <!-- 数据库驱动 -->
         <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
         <!-- 连接数据库的Url -->
         <property name="url" value="jdbc:mysql://localhost:3306/数据库名"/>
         <!-- 连接数据库的用户名 -->
         <property name="username" value="root"/>
         <!-- 连接数据库的用户名 -->
         <property name="password" value="abc"/>
     </bean>
     
     <!-- 配置JDBC模板 -->
     <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
         <!-- 默认使用数据源 -->
         <property name="dataSource" ref="dataSource"/>
     </bean>
     
     <!-- 配置注入类 -->
     <bean id="" >
         <property name="jdbcTemplate" ref="jdbcTemplate"/>
     </bean>
     
 </beans>



 

  dataSource的四个属性:

属性名

含义

driverClassName

所使用的驱动名称,对应驱动JAR包中的Driver类

url

数据源所在的地址

username

访问数据库的用户名

password

访问数据库的密码

 

Spring JdbcTemplate的常用方法

1.execute():execute(String sql)方法能够完成执行SQL语句的功能,

  先创建数据库spring

  再在配置文件中配置jdbcTemplate



<?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-4.3.xsd">
     <!-- 配置数据源 -->
     <bean id="dataSource" 
         class="org.springframework.jdbc.datasource.DriverManagerDataSource">
         <!-- 数据库驱动 -->
         <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
         <!-- 连接数据库的Url -->
         <property name="url" value="jdbc:mysql://localhost:3306/spring"/>
         <!-- 连接数据库的用户名 -->
         <property name="username" value="root"/>
         <!-- 连接数据库的用户名 -->
         <property name="password" value="abc"/>
     </bean>
     
     <!-- 配置JDBC模板 -->
     <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
         <!-- 默认使用数据源 -->
         <property name="dataSource" ref="dataSource"/>
     </bean>
</beans>



 

  在创建一个类用来测试是否成功



package com.itheima.jdbc;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;

/**
 * 使用execute()方法
 * @author 12428
 *
 */
public class JdbcTemplateTest {
    public static void main(String[] args) {
        //获取配置文件
        ApplicationContext applicationContext=
                new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取JdbcTemplate模板
        JdbcTemplate jdbcTemplate=(JdbcTemplate) applicationContext.getBean("jdbcTemplate");
        //使用execute()方法执行SQL语句,创建用户账号管理表account
        jdbcTemplate.execute("create table account("+
                                "id int primary key auto_increment,"+
                                "username varchar(50),"+
                                "balance double)");
        System.out.println("账户表account创建成功!");
    }
}



 测试结果

spring多数据库 spring 数据库_数据库_02

 

2.update():update()能完成插入,更新,删除数据的操作。

  (1)创建一个类Account类用来对应数据库spring中的表account,如下:



package com.itheima.jdbc;
/**
 * 账户类:用来与数据库spring的表account对应
 * @author 12428
 *
 */
public class Account {
    private Integer id; //账户Id
    private String username; //用户名
    private Double balance; //用户余额
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public Double getBalance() {
        return balance;
    }
    public void setBalance(Double balance) {
        this.balance = balance;
    }
    @Override
    public String toString() {
        return "Account [id=" + id + ", username=" + username + ", balance=" + balance + "]";
    }        
}



 

  (2)创建一个接口类AccountDao,接口中含有几个抽象方法,如下:



package com.itheima.jdbc;

public interface AccountDao {
    
    //添加
    public int addAccount(Account account);
    
    //更新
    public int updateAccount(Account account);
    
    //删除
    public int deleteAccount(int id);
}



(3)创建一个类AccountDaoImpl,该类实现了AccountDao接口,如下:



package com.itheima.jdbc;

import org.springframework.jdbc.core.JdbcTemplate;

public class AccountDaoImpl implements AccountDao {

    // 声明JdbcTemplate属性及其setter方法,使用setter注入属性
    private JdbcTemplate jdbcTemplate;

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

    /**
     * 添加账户 返回一个修改的行数
     */
    @Override
    public int addAccount(Account account) {
        // 定义sql语句
        String sql = "insert into account(username,balance) value(?,?)";
        // 定义数组来存储sql语句中的参数
        Object[] objects = new Object[] { account.getUsername(), account.getBalance() };
        // 执行添加操作,返回的是受SQL影响的记录数
        int num = this.jdbcTemplate.update(sql, objects);
        return num;
    }

    /**
     * 更新账户
     */
    @Override
    public int updateAccount(Account account) {
        // 定义SQL
        String sql = "update account set username=?,balance=? where id=?";
        // 定义数组来存储sql语句中的参数
        Object[] objects = new Object[] { account.getUsername(), account.getBalance(), account.getId() };
        // 执行更新操作,返回的是受SQL语句影响的记录条数
        int num = this.jdbcTemplate.update(sql, objects);
        return num;
    }

    /**
     * 删除用户
     */
    @Override
    public int deleteAccount(int id) {
        // 定义sql
        String sql = "delete from account where id=?";
        // 执行删除操作,返回的是受sql语句影响的记录条数
        int num = this.jdbcTemplate.update(sql, id);
        return num;
    }
}



  

  (4)设置配置文件applicationContext.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-4.3.xsd">
     <!-- 配置数据源 -->
     <bean id="dataSource" 
         class="org.springframework.jdbc.datasource.DriverManagerDataSource">
         <!-- 数据库驱动 -->
         <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
         <!-- 连接数据库的Url -->
         <property name="url" value="jdbc:mysql://localhost:3306/spring"/>
         <!-- 连接数据库的用户名 -->
         <property name="username" value="root"/>
         <!-- 连接数据库的用户名 -->
         <property name="password" value="abc"/>
     </bean>
     
     <!-- 配置JDBC模板 -->
     <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
         <!-- 默认使用数据源 -->
         <property name="dataSource" ref="dataSource"/>
     </bean>
     
     <!-- 配置一个AccountDao的Bean,把jdbcTemplate注入到accountDao里面 -->
     <bean id="accountDao" class="com.itheima.jdbc.AccountDaoImpl">
         <property name="jdbcTemplate" ref="jdbcTemplate"/>
     </bean>
</beans>



 

  (5)创建一个测试类JdbcTemplateTest,使用单元测试,如下:




package com.itheima.jdbc;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;

public class JdbcTemplateTest {
    /*
     * public static void main(String[] args) { //获取配置文件 ApplicationContext
     * applicationContext= new
     * ClassPathXmlApplicationContext("applicationContext.xml"); //获取JdbcTemplate模板
     * JdbcTemplate jdbcTemplate=(JdbcTemplate)
     * applicationContext.getBean("jdbcTemplate");
     * //使用execute()方法执行SQL语句,创建用户账号管理表account
     * jdbcTemplate.execute("create table account("+
     * "id int primary key auto_increment,"+ "username varchar(50),"+
     * "balance double)"); System.out.println("账户表account创建成功!"); }
     */

    /**
     * 添加一个用户
     */
    @Test
    public void addAccount() {
        // 加载配置文件
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取bean
        AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");

        // 创建一个用户
        Account account = new Account();
        account.setUsername("张三");
        account.setBalance(2000.0);
        // 调用方法
        int num = accountDao.addAccount(account);
        // 返回一个结果
        if (num > 0) {
            System.out.println("你已成功添加了" + num + "条数据");
        } else {
            System.out.println("添加数据失败!");
        }
    }

    /**
     * 更新一个用户
     */
    @Test
    public void updateAccount() {
        // 加载配置文件
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取bean
        AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");

        // 创建一个用户
        Account account = new Account();
        account.setId(1);
        account.setUsername("李四");
        account.setBalance(2000.0);

        // 执行更新方法
        int num = accountDao.updateAccount(account);

        // 返回一个结果
        if (num > 0) {
            System.out.println("你已成功修改了" + num + "条数据");
        } else {
            System.out.println("添加数据失败!");
        }
    }

    /**
     * 删除一个用户
     */
    @Test
    public void deleteAccount() {
        // 加载配置文件
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取bean
        AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");

        // 执行删除方法
        int num = accountDao.deleteAccount(1);

        // 输出结果
        if (num > 0) {
            System.out.println("你成功删除了" + num + "条数据");
        } else {
            System.out.println("删除数据失败!");
        }
    }
}




 




 

  (6)运行添加方法的结果如下:

    

spring多数据库 spring 数据库_spring多数据库_03

       

spring多数据库 spring 数据库_测试_04

 

 

(7)运行了更新方法的结果如下:

  

spring多数据库 spring 数据库_数据库_05

           

spring多数据库 spring 数据库_java_06

 

 

(8)运行了删除方法后的结果如下:

  

spring多数据库 spring 数据库_测试_07

     

spring多数据库 spring 数据库_bc_08

 

 

 

 

3.query():query()方法可以执行查询操作

  jdbcTemplate中提供了大量的查询方法,如下是几个常用的查询方法:

方法名

说明

List query(String sql,RowMapper rowMapper)

执行string类型参数提供的的sql语句,并通过RowMapper返回一个List类型的结果

List query(String sql,PreparedStatementSetter pss,RowMapper rowMapper)

根据String类型的参数提供的Sql语句创建的PreparedStatements对象通过RowMapper将结果返回到List中。

List query(String sql,Object[] args,RowMapper rowMapper)

使用Object[]的值来设置sql语句中的参数值,采用RowMapper回调方法直接返回List类型的数据

queryForObject(String sql,RowMapper rowMapper,Object...args)

将args参数绑定到SQL语句中,并通过RowMapper返回一个Object类型的单行记录

queryForList(String sql,Object[] args,class<T> elementType)

该方法可以返回多行数据的结果,但必须是返回列表,elementsType参数返回的是List元素类型

 

(1)先给数据库中添加几条数据,如下:

         

spring多数据库 spring 数据库_spring多数据库_09

 

 

 (2)在AccountDao接口中添加两个查询方法:


//通过id查询
    public Account queryAccountById(int id);
    
    //查询所有的用户
    public List<Account> queryAllAcount();


(3)在AccounDaoImpl中实现两个查询方法


/**
     * 根据id来查询账户
     */
    @Override
    public Account queryAccountById(int id) {
        //声明sql语句
        String sql="select * from account where id=?";
        
        //创建一个新的BeanPropertyRowMapper对象,返回一个需要返回的对象类型,不用再手动转换类型
        RowMapper<Account> rowMapper=new BeanPropertyRowMapper<Account>(Account.class);
        //执行查询语句
        return this.jdbcTemplate.queryForObject(sql, rowMapper, id);
        
    }

    /**
     * 查询所有的账户
     */
    @Override
    public List<Account> queryAllAcount() {
        
        //声明sql语句
        String sql="select * from account";
        
        //创建一个新的BeanPropertyRowMapper对象,返回一个需要返回的对象类型,不用再
        //手动转换类型
        RowMapper<Account> rowMapper=new BeanPropertyRowMapper<Account>(Account.class);
        
        //执行方法
        return this.jdbcTemplate.query(sql, rowMapper);
    }


 

(4)在jdbcTemplateTest中添加两个测试方法,如下:


/**
     * 根据id来查询用户
     */
    @Test
    public void queryAccountById() {
        // 加载配置文件
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取bean
        AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");
        
        //执行方法
        Account account=accountDao.queryAccountById(1);
    
        System.out.println(account);
    }
    
    /**
     * 查询所有的账户
     */
    @Test
    public void queryAllAccount() {
        //获取容器对象
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取对象AccountDao
        AccountDao accountDao=(AccountDao) applicationContext.getBean("accountDao");
        
        //执行方法
        List<Account> accounts=accountDao.queryAllAcount();
        //输出结果
        for(Account account:accounts) {
            System.out.println(account);}
        }


 

(5)执行第一个查询方法:根据Id来进行查询,结果如下:

     

spring多数据库 spring 数据库_测试_10

(6)执行第二个插叙方法:查询所有的账户,结果如下:

    

spring多数据库 spring 数据库_bc_11

 

注意:在执行jdbcTemplate查询操作时,如果查询的结果为空,则会抛出一个错误emptyResultDataAccessException异常,这样做的目的是为了防止程序员不对空值进行判断,保证了查程序的健壮性,如果想要查询结果为空时返回一个null而不是异常,则可以在jdbcTemplate返回查询结果的时候捕获异常,然尔返回null,例:

try{

    Object obj=jdbcTemplate.queryForObject();

        }catch(EmptyResultDataAccessException e){

        return null;

  }