MyBatis 源码阅读

第一篇记录了MyBatis的核心组成和工作逻辑,本篇再添加一些细节

数据源

代码位于datasource包,只对关键部分摘抄,加深印象

java.sql包和javax.sql包

java.sql包

java.sql通常被称为JDBC核心API包,它为Java提供了访问数据源中数据的基础功能

java.sql提供了一个Driver接口作为数据库驱动的接口,以及DriverManager类管理一组驱动。

不同种类的数据库厂商只需根据自身数据库特点开发相应的Driver实现类,并通过DriverManager进行注册即可


Driver接口相关类

基于java.sql包,Java程序能够完成各种数据库操作。通常完成一次数据库操作的流程如下所示:

  • 建立DriverManager对象
  • DriverManager对象中获取Connection对象
  • Connection对象中获取Statement对象
  • 将SQL语句交给Statement对象执行,并获取返回的结果,结果通常放在ResultSet

javax.sql包

javax.sql通常被称为JDBC扩展API包,它扩展了JDBC核心API包的功能,提供了对服务器端的支持,是 Java企业版的重要部分

javax.sql提供了DataSource接口,通过它可以获取面向数据源的Connection对象,与java.sql中直接使用DriverManager建立连接的方式相比更为灵活(实际上,DataSource接口的实现中也是通过DriverManager对象获取Connection对象的)

使用javax.sqlDataSource类执行一条SQL语句的过程如下:

  • 建立DataSource对象
  • DataSource对象中获取Connection对象
  • Connection对象中获取Statement对象
  • 将SQL语句交给Statement对象执行,并获取返回的结果,结果通常放在ResultSet

DriverManager

JDBC驱动程序管理器,可以管理一组JDBC驱动程序

主要的静态方法:

  • void registerDriver: 向DriverManager中注册给定的驱动程序
  • void deregisterDriver: 从DriverManager中删除给定的驱动程序
  • Driver getDriver: 查找能匹配给定URL路径的驱动程序
  • Enumeration getDrivers: 获取当前调用者可以访问的所有已加载的JDBC驱动程序
  • Connection getConnection: 建立到给定数据库的连接

DataSource

DataSourcejavax.sql的一个接口,代表了一个实际的数据源,其功能是作为工厂提供数据库连接

只有以下两个接口方法,都用来获取一个Connection对象:

  • getConnection(): 从当前的数据源中建立一个连接
  • getConnection(String,String): 从当前的数据源中建立一个连接,输入的参数为数据源的用户名和密码

常见实现:

  • 基本实现(UnpooledDataSource): 生成基本的到数据库的连接对象Connection
  • 连接池实现(PoolDataSource): 生成的Connection对象能够自动加到连接池中
  • 分布式事务实现(): 生成的Connection对象能够参与分布式事务

Connection

Connection接口,代表对某个数据库的连接,执行SQL语句和获取结果

常用方法:

  • Statement createStatement: 创建一个Statement对象,通过它能将SQL语句发送到数据库
  • CallableStatement prepareCall: 创建一个CallableStatement对象,通过它能调用存储过程
  • PreparedStatement prepareStatement: 创建一个PreparedStatement对象,通过它能将参数化的SQL语句发送到数据库
  • void commit: 提交当前事务
  • void rollback: 回滚当前事务
  • void close: 关闭当前的 Connection对象

Statement

Statement接口,定义了一些抽象方法能用来执行静态SQL语句并返回结果。通常Statement对象会返回一个结果集对象ResultSet

StatementPreparedStatementCallableStatement接口的区别:

  • Statement: 提供了执行语句和获取结果的基本方法,支持普通的不带参的查询SQL
  • PreparedStatement: 添加了处理输入参数的方法,支持可变参数的SQL
  • CallableStatement: 添加了调用存储过程核函数以及处理输出参数的方法,用于执行对数据库已存储过程的调用

Statement每次执行sql语句,数据库都要执行sql语句的编译,而PreparedStatement只会在第一次进行编译,后续仅需要解析然后填入参数

PreparedStatement还有效避免了SQL注入:

  • ${}: 以Statement执行,将输入参数直接拼接到SQL中,如下情况就会发生SQL注入,导致必然执行
    1
    2
    "select * from table where id=${}" + "3 or 2==2"
    ==> "select * from table where id=3 or 2==2"
  • #{}: 以PreparedStatement执行,先预编译,再将输入参数以字符串直接赋值,如下,不会发生SQL注入
    1
    2
    "select * from table where id=#{}" + "3 or 2==2"
    ==> "select * from table where id='3 or 2==2'"

参考

《MyBatis源码详解——通用源码阅读指导书》