MyBatis源码分析-SQL语句执行的完整流程(1)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

MyBatis源码分析-SQL语句执行的完整流程

MyBatis 是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map 使用简单的XML 或注解,将接口和Java 的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。如何新建MyBatis源码工程请点击MyBatis源码分析-IDEA 新建MyBatis源码工程。

MyBatis框架主要完成的是以下2件事情:

根据JDBC规范建立与数据库的连接。

通过反射打通Java对象与数据库参数交互之间相互转换的关系。

MyBatis框架是一种典型的交互式框架,先准备好交互的必要条件,然后构建一个交互的环境,在交互环境中划分会话,在会话中与数据库进行交互数据。

1 MyBatis主要的类

Configuration MyBatis所有的配置信息都维持在Configuration对象之中。

SqlSession 作为MyBatis工作的主要顶层API,表示和数据库交互的会话,完成必要数据库增删改查功能

Executor MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护

StatementHandler 封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数、将Statement结果集转换成List集合。

ParameterHandler 负责对用户传递的参数转换成JDBC Statement 所需要的参数,

ResultSetHandler 负责将JDBC返回的ResultSet结果集对象转换成List类型的集合;

TypeHandler 负责java数据类型和jdbc数据类型之间的映射和转换

MappedStatement MappedStatement维护了一条节点的封装,

SqlSource 负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回

BoundSql 表示动态生成的SQL语句以及相应的参数信息

以上几个类在SQL操作中都会涉及,在SQL操作中重点关注下SQL参数什么时候写入和结果集怎么转换为Java对象,这两个过程正好对应的类是PreparedStatementHandler和ResultSetHandler类。

(图片来自《深入理解mybatis原理》MyBatis的架构设计以及实例分析)

2 SQL执行流程

MyBatis主要设计目的还是为了让我们在执行SQL时对输入输出的数据的管理更加方便,所以方便的让我们写出SQL和方便的获取SQL的执行结果是MyBatis的核心竞争力。下面就用一个例子来从源码角度看一下SQL的完整执行流程。

新建配置文件conf.xml:

conf.xml

首先建立数据表,这里就以user表为例:

复制代码

DROP TABLE IF EXISTS user;

CREATE TABLE user (

id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,

name VARCHAR(32) NOT NULL,

password VARCHAR(32) NOT NULL,

email VARCHAR(32),

phone VARCHAR(16),

admin VARCHAR(16)

);

复制代码

然后新建与数据表对应的类User:

User

再新建usre表的配置文件:

userMapper.xml

最后新建测试类:

复制代码

/**

* MyBatis测试类

*/

public class TestMain {

public static void main(String[] args) throws IOException {

String resouce = "conf.xml";

InputStream is = Resources.getResourceAsStream(resouce);

// 构建sqlSession工厂

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

// 获取sqlSession

SqlSession session = sqlSessionFactory.openSession();

User user;

try {

/**

* 第一种方式: 直接执行已映射的SQL 语句

*/

String statement = "erDao.getById";

user = session.selectOne(statement, 1);

System.out.println(user);

}

finally {

session.close();

}

/**

* 第二种方式: 执行更清晰和类型安全的代码

// UserDao userDao = session.getMapper(UserDao.class);

// user = userDao.getById(1);

// System.out.println(user);

}

}

复制代码

由于我们分析的是SQL的执行流程,那就重点关注下user = session.selectOne(statement, 1); 这行代码~ 注意,传进去的参数是1。

session是DefaultSqlSession类型的,因为sqlSessionFactory默认生成的SqlSession是DefaultSqlSession类型。selectOne()会调用selectList()。

复制代码

// DefaultSqlSession类

public List selectList(String statement, Object parameter, RowBounds rowBounds) {

try {

MappedStatement ms = configuration.getMappedStatement(statement);

// CURD操作是交给Excetor去处理的

return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);

} catch (Exception e) {

throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);

} finally {

ErrorContext.instance().reset();

}

}

复制代码

在DefaultSqlSession.selectList中的各种CURD操作都是通多Executor进行的,这里executor的类型是CachingExecutor,接着跳转到其中的query方法中。

// CachingExecutor 类

public List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { BoundSql boundSql = ms.getBoundSql(parameterObject); // 获取绑定的sql命令,比如"SELECT * FROM xxx"

CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);

return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);

}

getBoundSql为了获取绑定的sql命令,在创建完cacheKey之后,就进入到CachingExecutor 类中的另一个query方法中。

复制代码

// CachingExecutor 类

@Override

public List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {

Cache cache = ms.getCache();

if (cache != null) {

flushCacheIfRequired(ms);

if (ms.isUseCache() && resultHandler == null) {

相关文档
最新文档