jdbc/mybatis使用及Spring-mybatis整合源码分析

本文主要对 JDBC连接db / Spring-JDBC连接db / Mybatis独立使用 / Spring整合Mybatis 几种db连接和使用的过程作出总结,并对其中的关键环节进行源码分析。事务部分暂时还没整理,后面会补全。部分配置文件还没加上,后面会补全。说明:文中大部分内容来源于阅读《Spring源码深度解析》时的笔记,同时添加了一些自己的理解。书中使用的Spring 5.x版本,代码有点老,但核心原理一直都差不多。1 JDBC连接db一般流程在开发环境加载指定db的驱动程序在ja
摘要由CSDN通过智能技术生成

本文主要对 JDBC连接db / Spring-JDBC连接db / Mybatis独立使用 / Spring整合Mybatis 几种db连接和使用的过程作出总结,并对其中的关键环节进行源码分析。
事务部分暂时还没整理,后面会补全。
部分配置文件还没加上,后面会补全。
说明:文中大部分内容来源于阅读《Spring源码深度解析》时的笔记,同时添加了一些自己的理解。书中使用的Spring 5.x版本,代码有点老,但核心原理一直都差不多。

1 JDBC连接db

一般流程

  1. 在开发环境加载指定db的驱动程序
  2. 在java程序中加载驱动程序
  3. 创建数据连接对象
  4. 创建Statement对象
  5. 调用Statement对象相关方法执行sql,解析结果ResultSet
  6. 关闭db连接
        /** JDBC连接db的一般流程(样例代码, 去除了非关键逻辑) **/
        // 加载驱动程序
        Class.forName("com.mysql.jdbc.Driver");
        // 创建数据连接对象
        Connection conn = DriverManager.getConnection(dbUrl, dbUser, dbPsw);
        // 创建Statement对象
        Statement stmt = conn.createStatement();
        // 调用Statement对象相关方法执行sql
        ResultSet rs = stmt.executeQuery(sql);
        // 解析结果ResultSet
        ResultSetMetaData rsmd = rs.getMetaData();
        int columnsNumber = rsmd.getColumnCount();
        List<Map> result = new ArrayList<>();
        while (rs.next()) {
   
            Map<String, Object> map = new HashMap<>();
            for (int i = 1; i <= columnsNumber; i++) {
   
                map.put(rsmd.getColumnName(i), rs.getString(i));
            }
            result.add(map);
        }
        // 完成后关闭资源
        rs.close();
        stmt.close();
        conn.close();

2 Spring-JDBC连接db

一般流程

  1. 创建db表,假设为user
CREATE TABLE 'user' (
  'id' int(11) NOT NULL auto_increment,
  'name' varchar(64) default '' NOT NULL,
  PRIMARY KEY ('id')
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  1. 创建对应的PO,假设为UserPO
public class UserPO {
   
  private Integer id;
  private String name;
  // 省略get/set等方法
}
  1. 创建表与实体间的映射
public class UserRowMapper implements RowMapper {
   
  @Override
  public Object mapRow(ResultSet rs, int index) {
   
    UserPO user = new UserPO(rs.getInt("id"), rs.getString("name"));
    return user;
  }
}
  1. 创建数据操作接口
public interface UserService {
   
  void save(UserPO user);
  List<UserPO> getUsers();
}
  1. 创建数据操作接口实现类
public class UserServiceImpl implements UserService {
   
  private JdbcTemplate jdbcTemplate;
  
  public void setDataSource(DataSource dataSource) {
   
    this.jdbcTemplate = new jdbcTemplate(dataSource);
  }
  public void save(UserPO user) {
   
    jdbcTemplate.update("insert into user(name) values(?)", new Object[] {
   user.getName()}, new int[] {
   java.sql.Types.VARCHAR});
  }
  @SuppressWarnings("unchecked")
  public List<UserPO> getUsers() {
   
    List<UserPO> users = jdbcTemplate.query("select * from user", new UserRowMapper());
    return users;
  }
}

上面代码中引用JdbcTemplate的update()/query()等方法,底层核心方法为execute()。下面讲解下execute()方法(为便于凸显核心逻辑,使用的源码版本比较低),不感兴趣的同学可以直接跳过本部分。

  • sql = getSql(preparedStatementCreator)
  • Connection con = DataSourceUtils.getConnection(getDataSource)
    1 conHolder = TransactionSychronizationManager.getResource(dataSource)
    2 如果conHoloder里面有可用connection则复用
    3 否则从dataSource获取 connection
    4 线程中的数据库事务操作都要使用同一个事务链接
  • 引用用户设定的输入参数
    applyStatementSettings(preparedStatement), 其中会调用setFetchSize()/setMaxRows()等
  • 调用回调 result = action.doInPreParedStatement(psToUse)
    1 对update操作
    1.1 pss.setValues(ps) 遍历每个参数来做类型匹配及转换。如果是集合类则需要进入集合类内部递归解析集合内部属性。pss.setValues 调用 doSetValue() 对单个参数及类型做匹配处理。pss代表的类是ArgPreparedStatementSetter。
    1.2 return ps.executeUpdate() 真正执行sql
    1.3 finally 语句块会确保执行 pss.cleanupParameters()
    2 对query操作
    2.1 resultSet = ps.executeQuery()
    2.2 return rse.extractData(rsToUser) 将结果封装并转换成POJO: 对返回结果遍历并对其使用rowMapper进行转换。rse 代表的类为 RowMapperResultSetExtractor.
    2.3 finally 语句块会确保执行 pss.cleanupParameters()
    3 handleWarnings(preparedStatement) 警告处理。
    警告不是异常,它表示很可能出现数据错误,但不一定会影响程序执行,比如DataTruncation,用户可以自己设置处理警告的方式。
    4 exception 时会调用 DataSourceUtils.releaseConnection(con, getDataSource)
    如果当前线程存在事务,说明存在公用数据库连接,这是直接使用ConnectionHolder中的released方法进行连接数减一,而不是真正的释放连接。
    5 finally 语句块会确保执行:
    JdbcUtils.closeStatement(preparedStatement); DataSourceUtils.releaseConnection(con, getDataSource())
  1. 配置spring配置文件
    最重要的两个配置: 1 配置dataSource;2 配置业务bean(UserService),并向其中中注入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-4.1.xsd "
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值