【JavaSE】JDBC(三):Spring的JDBCTemplate基本使用

  经过JDBC(一)、(二),对JDBC原理和使用都有了比较清晰的认识。JDBC(三)就总结一个JDBC的简单封装的工具类JDBCTemplate,它是Spring框架对JDBC的简单封装,提供了一个JDBCTemplate对象简化JDBC的程序开发步骤。

1.为什么使用JDBCTemplate

  JDBC数据库连接池已经能够满足大部分用户最基本的需求,但我们在使用JDBC开发时,必须自己来管理数据库资源如:获取PreparedStatement,设置SQL语句参数,关闭连接等常规步骤。
  而JdbcTemplate是Spring对JDBC的封装,目的是使JDBC更加易于使用。提供的JdbcTemplate类已经处理了资源的建立和释放,帮助我们避免一些常见的错误,比如忘了总要关闭连接。它是运行核心的JDBC工作流,如Statement的建立和执行,而我们只需要提供想要执行SQL语句和提取SQL处理结果。它还能将查询的结果自动封装指定的数据类型,极大提高了我们的开发效率;


2.JDBCTemplate基本使用步骤

这里先说一下使用JdbcTemplate步骤,非常的简单,关键的是中间三个步骤:
  1.导入jar包
  2.创建JdbcTemplate对象
  3.定义sql语句
  4.调用JdbcTemplate里面的方法执行sql语句
  5.处理结果


步骤1:导入jar包(所用jar包资源在文末分享)
导入JdbcTemplate依赖的jar包,因为是Spring框架提供的,想要使用需要导入下面4个包:
    1.spring-beans-5.0.0.RELEASE.jar
    2.spring-core-5.0.0.RELEASE.jar
    3.spring-jdbc-5.0.0.RELEASE.jar
    4.spring-tx-5.0.0.RELEASE.jar
    5.commons.logging-1.2.jar

  当然还需要导入电脑上对应数据库的驱动程序Jar包,本文中使用的是Mysql,步骤2中创建JdbcTemplate对象时,还要给它传入一个数据库连接池对象,所以要有数据库连接池对应的Jar包。
    1.mysql-connector-java-5.1.37-bin.jar
    2.druid-1.0.9.jar

步骤2:创建JdbcTemplate对象
创建JdbcTemplate对象,方便执行SQL语句,使用的构造方法:

//JdbcTemplate构造方法
public JdbcTemplate(DataSource dataSource)
//创建一个JdbcTemplate对象
JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());

  创建JdbcTemplate对象时,还要给它传入一个数据库连接池对象,这里使用的是Druid连接池、和Druid的工具类JDBCUtils都在上一篇文章有详细描述:JDBC(二):数据库连接池(C3P0、Druid),后面贴出JDBCUtils工具类。


步骤3:定义sql语句
  拼接SQL语句,SQL中的参数建议通过占位符?,来代替SQL语句中给定的参数值。好处在文章:JDBC(一):基础有详细提到。


步骤4:调用JdbcTemplate里面的方法执行sql语句
 在JdbcTemplate中执行SQL语句的方法大致分为3类:
   1.execute:可以执行所有SQL语句,一般用于执行DDL语句。
   2.update:用于执行insert、update、delete等DML语句。
   3.queryXxx:用于DQL数据查询语句。

 execute方法,数据库创建、表、列字段创建删改等操作很少在JDBC程序中进行,不多说。主要总结下JdbcTemplate 常用查询数据库的方法:

 - queryForMap():查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合
        * 注意:这个方法查询的结果集长度只能是1,即只能查询一条记录
      
 - queryForList():查询结果,并将结果集封装为list集合
        * 注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中
 
 - query():查询结果,将结果封装为JavaBean对象
        * query的参数:RowMapper接口
            * 一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装
            * new BeanPropertyRowMapper<类型>(类型.class)
        
 - queryForObject():查询结果,将结果封装为对象
        * 一般用于聚合函数的查询

上面只是大致说了方法的,方法参数没有给出,下面是方法详情:

  • public long queryForLong(String sql):执行查询语句,返回查询到的一个long类型的数据。还有很多返回不同数据类型的方法。
  • public Map<String, Object> queryForMap(String sql):执行查询语句,只能将一条记录放到一个Map中。
  • public List<Map<String, Object>> queryForList(String sql):执行查询语句,将结果集封装为List集合,注意:是将每一条记录封装为一个Map集合,再将Map集合装载到List集合中
  • public <T> List<T> query(String sql, RowMapper<T> rowMapper):执行查询语句,返回一个List集合,List中存放的是RowMapper接口指定类型的数据。我们一般不用RowMapper接口,而是用RowMapper的实现类BeanPropertyRowMapper,将数据自动封装,代码更加简洁。
    public class BeanPropertyRowMapper<T> implements RowMapper<T>BeanPropertyRowMapper类实现了RowMapper接口
  • public <T> T queryForObject(String sql, Class<T> requiredType):执行查询语句,返回一个指定类型的数据。

步骤5:处理执行SQL得到的结果
  进行自己的处理逻辑。

Druid连接池配置文件、和Druid的工具类JDBCUtils

druid.properties

# 加载数据库驱动
driverClassName=com.mysql.jdbc.Driver
# 连接数据库的url,db1表示数据库名,useSSL=false表示不使用SSL规范
url=jdbc:mysql://127.0.0.1:3306/db1?useSSL=false&characterEncoding=UTF-8
# 用户登录数据库的账号和密码
username=root
password=123456
# 初始化连接数量
initialSize=5
# 最大连接数量
maxActive=10
# 最大等待时间
maxWait=3000
/**
 * Druid连接池的工具类
 */
public class JDBCUtils {
    //1.定义成员变量DataSource
    private static DataSource ds;

    static {
        try {
            //1.加载配置文件
            Properties pro=new Properties();
            pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
            //2.获取DataSource
            ds= DruidDataSourceFactory.createDataSource(pro);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接对象
     * @return
     */
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }

    /**
     * 释放资源
     * @param stmt
     * @param conn
     */
    public static void close(Statement stmt,Connection conn){
        close(null,stmt,conn);
    }

    /**
     * 释放资源
     * @param rs
     * @param stmt
     * @param connection
     */
    public static void close(ResultSet rs,Statement stmt, Connection connection){
        if (rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (stmt!=null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (connection!=null){
            try {
                connection.close();//归还连接
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获取数据库连接池
     * @return
     */
    public static DataSource getDataSource(){
        return ds;
    }
}

2.1 JdbcTemplate完成CRUD

  调用JdbcTemplate的方法来完成CRUD的操作。现有如下的数据库表emp,使用JdbcTemplate完成一些需求,来理解上面所提到的方法。
在这里插入图片描述
需求:
  1. 修改1号数据的 address 为 广州
  2. 添加一条记录
  3. 删除刚才添加的记录
  4. 查询id为1的记录,将其封装为Map集合
  5. 查询所有记录,将其封装为List
  6. 查询所有记录,将其封装为Emp对象的List集合
  7. 查询总记录数

2.2 代码实现

需求1. 修改1号数据的 address 为 广州
调用JdbcTemplate的update方法:public int update(String sql, @Nullable Object... args)

  • 参数sql:执行的SQL语句;
  • 参数 Object… args :可以有多个参数,按顺序依此对应SQL语句中多个占位符?的值;
public class Demo02 {

    //Junit单元测试,可以让方法独立执行
    /*
        使用JdbcTemplate步骤
        1.导入jar包
        2.创建JDBCTemplate对象
        3.调用JdbcTemplate里面的方法
     */

    //1. 修改1号数据的 address 为广州
    @Test
    public void test1() {
        //创建JDBCTemplate对象
        JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
        //定义sql
        String sql = "update emp set address=? where id=?";
        //调用JdbcTemplate方法,执行sql
        int count = template.update(sql, "广州", 1);
        //获取执行结果,修改成功返回被修改的记录数
        System.out.println(count);//1
    }
    ...
}    

在这里插入图片描述

需求2. 添加一条记录

//2. 向数据添加一条记录
    @Test
    public void test2() {
        //创建JDBCTemplate对象
        JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
        //定义sql
        String sql = "insert into emp(name,address) value(?,?)";
        //调用JdbcTemplate方法,执行sql
        int count = template.update(sql, "赵子龙", "蜀国");
        //获取执行结果,添加成功返回被添加的记录数
        System.out.println(count);//1
    }

在这里插入图片描述

需求3. 删除刚才添加的记录

//3. 删除刚才添加的记录
    @Test
    public void test3() {
        //创建JDBCTemplate对象
        JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
        //定义sql
        String sql = "delete from emp where id=?";
        //调用JdbcTemplate方法,执行sql
        int count = template.update(sql, 9);
        //获取执行结果,删除成功返回被删除的记录数
        System.out.println(count);//1
    }

需求4. 查询id为1的记录,将其封装为Map集合
public Map<String, Object> queryForMap(String sql):执行查询语句,只能将一条记录放到一个Map中。超过了一条则会报错:IncorrectResultSizeDataAccessException错误的结果大小数据访问异常

//4. 查询id为1的记录,将其封装为Map集合
    @Test
    public void test4() {
        //创建JDBCTemplate对象
        JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
        //定义sql
        //String sql = "select * from emp where id=? or id = ?";
        String sql = "select * from emp where id=? ";
        //调用JdbcTemplate方法,执行sql
        //注意:这个方法查询的结果集长度只能是1,超过1则报错
        //Map<String, Object> map = template.queryForMap(sql, 1, 2);//IncorrectResultSizeDataAccessException
        Map<String, Object> map = template.queryForMap(sql, 1);
        //获取执行结果
        System.out.println(map);//{id=1, name=董桌, address=广州, hireDate=2020-07-05 19:27:50.0}
    }
    

需求5. 查询所有记录,将其封装为List
public List<Map<String, Object>> queryForList(String sql):执行查询语句,将结果集封装为List集合,注意:是将每一条记录封装为一个Map集合,再将Map集合装载到List集合中

//5. 查询所有记录,将其封装为List
    @Test
    public void test5(){
        //创建JDBCTemplate对象
        JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
        //定义sql
        String sql = "select * from emp";
        //调用JdbcTemplate方法,执行sql
        List<Map<String, Object>> list = template.queryForList(sql);
        //获取执行结果
        for (Map<String, Object> map : list) {
            System.out.println(map);
        }
    }
    
打印结果:
{id=1, name=董桌, address=广州, hireDate=2020-07-05 19:27:50.0}
{id=2, name=张飞, address=武汉, hireDate=2020-05-31 12:33:35.0}
{id=3, name=李小龙, address=武汉, hireDate=2020-05-31 12:34:02.0}
{id=4, name=王麻子, address=长沙, hireDate=2020-05-31 12:34:08.0}
{id=5, name=赵天, address=北京, hireDate=2020-05-31 12:34:16.0}
{id=6, name=刘长云, address=深圳, hireDate=2020-05-31 12:34:25.0}
{id=7, name=曹德, address=上海, hireDate=2020-05-31 12:33:55.0}  

需求6. 查询所有记录,将其封装为Emp对象(自定义对象)的List集合
public <T> List<T> query(String sql, RowMapper<T> rowMapper):执行查询语句,将结果封装为JavaBean对象,返回一个List集合;
自定义的Emp类

public class Emp {
    private int id;
    private String name;
    private String address;
    private Date hireDate;

    public Emp() {
    }

    public Emp(int id, String name, String address, Date hireDate) {
        this.id = id;
        this.name = name;
        this.address = address;
        this.hireDate = hireDate;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Date getHireDate() {
        return hireDate;
    }

    public void setHireDate(Date hireDate) {
        this.hireDate = hireDate;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", address='" + address + '\'' +
                ", hireDate='" + hireDate + '\'' +
                '}';
    }
}
//6. 查询所有记录,将其封装为Emp对象(自定义对象)的List集合
    @Test
    public void test6(){
        //创建JDBCTemplate对象
        JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
        //定义sql
        String sql = "select * from emp";
        //调用JdbcTemplate方法,执行sql
        List<Emp> list = template.query(sql, new RowMapper<Emp>() {
            @Override
            public Emp mapRow(ResultSet rs, int i) throws SQLException {
                Emp emp=new Emp();
                //从结果集中获取列字段对应的数据记录
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String address = rs.getString("address");
                Date hireDate = rs.getDate("hireDate");

                //存入Emp对象中
                emp.setId(id);
                emp.setName(name);
                emp.setAddress(address);
                emp.setHireDate(hireDate);

                return emp;
            }
        });
        //打印List集合
        for (Emp emp : list) {
            System.out.println(emp);
        }
    }

用RowMapper的实现类BeanPropertyRowMapper,将数据自动封装,代码更加简洁。

	/*
        6. 查询所有记录,将其封装为Emp对象(自定义对象)的List集合
        一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装
        new BeanPropertyRowMapper<类型>(类型.class)
     */
    @Test
    public void test7(){
        //创建JDBCTemplate对象
        JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
        //定义sql
        String sql="select * from emp";
        //调用JdbcTemplate方法,执行sql
        //将查询到的记录自动封装成自定义对象
        List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));
        //遍历List集合,打印
        for (Emp emp : list) {
            System.out.println(emp);
        }
    }
    
两种方式输出结果都是一样的:
Emp{id=1, name='董桌', address='广州', hireDate='2020-07-05 19:27:50.0'}
Emp{id=2, name='张飞', address='武汉', hireDate='2020-05-31 12:33:35.0'}
Emp{id=3, name='李小龙', address='武汉', hireDate='2020-05-31 12:34:02.0'}
Emp{id=4, name='王麻子', address='长沙', hireDate='2020-05-31 12:34:08.0'}
Emp{id=5, name='赵天', address='北京', hireDate='2020-05-31 12:34:16.0'}
Emp{id=6, name='刘长云', address='深圳', hireDate='2020-05-31 12:34:25.0'}
Emp{id=7, name='曹德', address='上海', hireDate='2020-05-31 12:33:55.0'}

需求7. 查询总记录数
public <T> T queryForObject(String sql, Class<T> requiredType):执行查询语句,返回一个指定类型的数据。

//7. 查询总记录数
    @Test
    public void test8(){
        //创建JDBCTemplate对象
        JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
        //定义sql
        String sql="select count(id) from emp";
        //调用JdbcTemplate方法,执行sql
        Long total = template.queryForObject(sql, Long.class);
        System.out.println(total);//打印结果:7
    }

3.小结

  使用JdbcTemplate能够简化我们对JDBC的操作,它是JDBC的一个辅助类(JDBC Template),它封装了JDBC的操作,使用起来非常方便。可以对比前两篇文章来看JdbcTemplata类的方便之处,这篇JDBC(三)拖了挺久,笔者正在努力学习中,哈哈其实是我忘了。
  使用JdbcTemplate用到的jar包:点我. 提取码:lp3b


本文有所帮助的话,欢迎点赞评论,指出不足,笔者由衷感谢o!

推荐阅读:
JDBC(一):基础(本质,操作步骤,类对象详解,工具类,事务)
JDBC:API实战(CURD,封装结果集,批量处理sql,处理二进制大数据文件,获取主键列、元数据).
JDBC(二):数据库连接池(C3P0、Druid)
JDBC(三):Spring的JDBCTemplate基本使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值