JdbcTemplate底层实现解析

jdbctmplate底层源码及解析

一、回顾jdbc基础知识

  • jdbc是java语言用来规范客户端如何访问数据库的应用程序接口,提供了查询和更新数据库中数据的方法。

  • jdbc是面向关系型数据库的。

  • 不同的数据库厂商有不同的jdbc的jar包。

  • jdbc基本步骤

    • 加载驱动
    • 获取Connection对象
    • 获取执行sql的statement对象(推荐使用prepareStatement,(1)效率好(2)可以解决sql注入的问题。)
    • 执行sql,获取结果
    • 对结果进行处理
    • 释放资源

二、回顾数据源DataSource

  1. DataSource基本概念

    • 负责与数据库的连接,当在应用程序中访问数据库时不必填写连接数据库的代码,直接引用DataSource获取连接数据库的Connection对象即可。
    • 数据库连接池负责分配、管理和释放数据库连接,允许应用程序重复使用一个现有的数据库连接,而不用重新建立一个。
    • 释放空闲时间超过最大空闲时间的数据库连接,避免因为没有释放连接而引起的数据库连接遗漏。
  2. 常见的数据库连接池:dbcp,c3p0,druid

  3. druid使用步骤

    • 导入依赖

    • 提供db.properities

      driverClassName = com.mysql.jdbc.Driver
      url = jdbc:mysql:///javaweb
      username = root
      password = root
      
    • 使用druid创建DataSource

      package com.rookie.util;
      
      import com.alibaba.druid.pool.DruidDataSourceFactory;
      
      import javax.sql.DataSource;
      import java.io.IOException;
      import java.io.InputStream;
      import java.util.Properties;
      
      public class DruidUtils {
      
          private static DataSource dateSource = null;
      	//静态代码块,类加载的时候就会执行
          static{
              try {
                  //1.读取配置文件
                  InputStream is = DruidUtil.class.getClassLoader().getResourceAsStream("db.properties");
                  //2.将is导入properties
                  Properties pp = new Properties();
                  pp.load(is);
                  //3.创建连接池对象
                  dateSource = DruidDataSourceFactory.createDataSource(pp);
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      
          public static DataSource getDateSource(){
              return dateSource;
          }
      }
      
      
  • 然后就可以使用dataSource获取数据库的连接对象Connection,执行sql操作。

三、使用JdbcTemplate

JdbcTemplate是spring对传统的jdbc的封装。

JdbcTemplate比较灵活,但是和ORM框架相比,JdbcTemplate功能则力不从心,学习JdbcTemplate是为了学习ORM框架做铺垫。

@Test
    public void test4(){
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(DruidUtils.getDateSource());

        //1.增删改
        //因为id为主键,会自增,所以可以填NULL;不会出现主键冲突
        jdbcTemplate.update("INSERT INTO ACCOUNT VALUES(NULL,?,?,?)","QWE","1000","0");
        jdbcTemplate.update("UPDATE ACCOUNT SET NAME = ? WHERE ID = ?","ZXC","5");
        jdbcTemplate.update("DELETE FROM ACCOUNT WHERE ID = ?","6");

        //2.查询所有;<> 和 ()内都要填写
        List<User> list = jdbcTemplate.query("SELECT * FROM ACCOUNT", new BeanPropertyRowMapper<User>(User.class));
        list.forEach(user -> System.out.println(user));

        //3.查询一条数据
        User user = jdbcTemplate.queryForObject("SELECT * FROM ACCOUNT where id = ?", new BeanPropertyRowMapper<User>(User.class), "1");
        System.out.println(user);

    }

四、update流程简化总结

//把DataSource接收保存
    JdbcTemplate jdbcTemplate = new JdbcTemplate();
    jdbcTemplate.setDataSource(DruidUtils.getDateSource());
//经过多次重载,内部调用update方法
	//update执行了两件事(1.封装sql语句;2.封装参数)
	jdbcTemplate.update("INSERT INTO ACCOUNT VALUES(NULL,?,?,?)","QWE","1000","0");
	//通过判断,内部执行的是execute方法
	{
        获取数据库连接对象
        初始化statement对象
        通过回调函数执行update函数中的ps->{}里面的逻辑
        //ps->{}包括
        	{
            	将prepareStatement对象和传入的参数进行封装
                int rows = ps.executeUpdate(); 执行sql
            	return rows
        	}
    }

总结:

jdbcTemplate的update方法:

  • 先将sql语句和参数分别封装,封装之后会进行绑定(即将sql语句中的问号替换为传入的参数
  • 有了完整的sql语句之后,进行jdbc的基础操作
    • 获取Connection对象(通过DataSource获得)
    • 初始化prepareStatement对象
    • 执行prepareStatement的executeUpdate方法
    • 返回结果rows
    • 释放数据库连接资源

五、query查询所有的流程

 List<User> list = jdbcTemplate.query("SELECT * FROM ACCOUNT", new BeanPropertyRowMapper<User>(User.class));

BeanPropertyRowMapper的作用:

  • 将结果集的数据封装到具体的对象中去,对象是根据刚开始传进BeanPropertyRowMapper的class来决定的
  • 对象通过反射进行创建,然后通过内省的方式将对象的属性和结果集中的数据进行封装。
  • 封装过程:
    JdbcTemplate底层实现解析

六、queryForObject的流程

query和queryForObject都会执行query()方法,传参和不传参的执行流程不一样,但是最终都会执行execute方法。

注:queryForObject查找不到数据或者查找到的数据数量大于1,都会抛出异常(因为在源码中将result集合的大小设定为了1)

//把DataSource接收保存
    JdbcTemplate jdbcTemplate = new JdbcTemplate();
    jdbcTemplate.setDataSource(DruidUtils.getDateSource());
//经过多次重载,内部调用query方法
	//update执行了两件事(1.封装sql语句;2.封装参数)
	 User user = jdbcTemplate.queryForObject("SELECT * FROM ACCOUNT where id = ?", new BeanPropertyRowMapper<User>(User.class), "1");
	//通过判断,内部执行的是execute方法
	{
        获取数据库连接对象
        初始化statement对象
        action实际对象是匿名内部类
        	{
            	将prepareStatement对象和传入的参数进行封装
                rs = ps.executeQuery(); 执行sql
            	return rse.extractData(rs)
                {
                    创建一个大小为1的集合
                    使用BeanPropertyRowMapper将结果集中的数据封装到一个指定的对象中(通过反射 + 内省 实现)
                }
        	}
    }
上一篇:spring入门实战&源码解读(3):spring JdbcTemplate和事务


下一篇:Spring boot jdbcTemplate