深入理解MyBatis(三)—MyBatis的Update操作执行流程
通过配置文件的解析以及Configuration对象的生成,MyBatis完成了初始化;初始化完成后通过获取的SqlSessionFactory,可以得到SqlSession用来进行动态操作;
MyBatis中的insert操作,delete操作,update操作实质上底层都是调用update;本文以insert操作为例分析update的具体执行流程;
个人主页:tuzhenyu’s page
原文地址:深入理解MyBatis(三)—MyBatis的Update操作执行流程
(1) 会话Session的创建
- 通过初始化获取的SessionFactory创建会话对象
SqlSession session = sessionFactory.openSession();
- 调用openSessionFromDataSource()方法执行创建逻辑
public SqlSession openSession() {
return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, false);
}
在openSessionFromDataSource()方法中创建Executor实例,具体的SQL操作都是通过executor执行的
首先从Configuration中获取Encironment对象,其中包含了数据源和相应的事务的配置
根据Encironment对象创建事务工厂transactionFactory,进而创建事务对象transaction
根据产生的事务对象创建executor执行器对象,用来执行具体的SQL操作;
将executor封装到DefaultSqlSession对象中返回中
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
DefaultSqlSession var8;
try {
Environment e = this.configuration.getEnvironment();
TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(e);
tx = transactionFactory.newTransaction(e.getDataSource(), level, autoCommit);
Executor executor = this.configuration.newExecutor(tx, execType);
var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
} catch (Exception var12) {
this.closeTransaction(tx);
throw ExceptionFactory.wrapException("Error opening session. Cause: " + var12, var12);
} finally {
ErrorContext.instance().reset();
}
return var8;
}
根据传入的transaction事务实例创建executor实例,DefaultSqlSession将主要的操作交给executor执行;
executor有三种类型:BatchExecutor,ReuseExecutor和simpleExecutor;BatchExecutor专门用来执行批处理;ReuseExecutor会重用statement执行sqi操作;simpleExecutor只是简单执行sql语句;默认是simpleExecutor;
如果开启catch缓存的话会利用装饰器模式创建CachingExecutor,CachingExecutor在查询数据库之前会先查询缓存;
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null?this.defaultExecutorType:executorType;
executorType = executorType == null?ExecutorType.SIMPLE:executorType;
Object executor;
if(ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if(ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
if(this.cacheEnabled) {
executor = new CachingExecutor((Executor)executor);
}
Executor executor1 = (Executor)this.interceptorChain.pluginAll(executor);
return executor1;
}
(2) Insert方法执行流程
1. 创建执行器Executor
- 通过openSession()方法创建一个SqlSession的实例DefaultSqlSession作为具体SQL执行的入口,DefaultSqlSession对象中封装着属性Configuration,Executor,autoCommit等;
public int insert(String statement) {
return this.insert(statement, (Object)null);
}
public int insert(String statement, Object parameter) {
return this.update(statement, parameter);
}
insert操作是通过调用update语句进行的相关逻辑,delete操作也是通过调用update实现的具体逻辑;
根据statement从configuration中获取到相应的MappedStatement对象(在初始化中已经解析加载到configuration中)
对参数parameter中的集合进行处理;
public int update(String statement, Object parameter) {
int var4;
try {
this.dirty = true;
MappedStatement e = this.configuration.getMappedStatement(statement);
var4 = this.executor.update(e, this.wrapCollection(parameter));
} catch (Exception var8) {
throw ExceptionFactory.wrapException("Error updating database. Cause: " + var8, var8);
} finally {
ErrorContext.instance().reset();
}
return var4;
}
Executor最终将MapperStatement的执行委托给了StatementHandler;具体的执行流程:
获取一个connection数据库连接;
调用StatementHandler.prepare()方法获取一个statement
调用StatementHandler.parameterize方法设置sql执行时候需要的参数
调用StatementHandler.update()方法执行具体sql指令
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
int var6;
try {
Configuration configuration = ms.getConfiguratio