前言
本文debug mybatis源码版本:3.2.7
mybatis提供了JDBC和MANAGED两种事务管理,本文主要讨论的是JDBC事务管理方式。
如果对本文理解不够详细,请先看另一篇博文,模拟实现mybatis数据源和事务:《动态代理+ThreadLocal实现数据源及事务管理》。
本文主要讨论的内容:
1. mybatis JDBC事务的开始、提交、回滚和关闭
2. mybatis JDBC事务中connection的多线程安全
一、mybatis的初始化核心:被抛弃的发动机SqlSessionManager
可以这么错觉的认为,使整个mybatis框架跑起来的是SqlSessionManager,他既是mybatis的“发动机”,也是mybatis的“方向盘”。但是这个类似乎已经被弃用了,被DefaultSqlSessionFactory和DefaultSqlSession替代了,但实际上他们几乎是平等的关系,近乎1=2的概念。我也正在积极寻找被弃用的原因,至少目前从调试框架的结果来看,这个类的确没有被使。但是这个类的思想对于更好的了解Factory和session还是很有帮助的。
1. SqlSessionFactoryBuilder和Configuration
mybatis的起点是SqlSessionFactoryBuilder,他通过builder方法加载mybatis-config.xml配置文件,从而使得整个框架获得“跑动“的环境条件。SqlSessionFactoryBuilder有9个builder方法,四个和字节流有关,四个和字符流有关,完全的一一对应,而所有和流有关的builder方法的最终落点是build(Configuration config),也就是说无论是字节流还是字符流,他们最终都是把读取xml配置文件的流输送给xml的解析对象XMLConfigBuilder,而XMLConfigBuilder对象的终极目的就是parse注入的流成为Configuration对象,而Configuration对象几乎将配置文件中的配置标签一一对应的解析成了与之一致的对象,他就是mybatis框架的配置中心。
package org.apache.ibatis.session;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Properties;
import org.apache.ibatis.builder.xml.XMLConfigBuilder;
import org.apache.ibatis.exceptions.ExceptionFactory;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
public class SqlSessionFactoryBuilder {
/**
* 所有的字符流builder的最终落点为该方法
* 最终将流builder方法传入的流注入到XMLConfigBuilder对象,并通过其parser方法将流解析成Configuration对象
* 解析生成的Configuration对象最终被传入最后一个builder方法构造SqlSessionFactory
*/
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
reader.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
/**
* 所有字节流有关的builder方法的最终落点,该方法的作用和字符流一致,只是传入的流不同而已
*/
public