Mybatis核心類:
SqlSessionFactory:每個(gè)基于 MyBatis 的應(yīng)用都是以一個(gè) SqlSessionFactory 的實(shí)例為中心的。SqlSessionFactory 的實(shí)例可以通過 SqlSessionFactoryBuilder 獲得。而 SqlSessionFactoryBuilder 則可以從 XML 配置文件或通過Java的方式構(gòu)建出 SqlSessionFactory 的實(shí)例。SqlSessionFactory 一旦被創(chuàng)建就應(yīng)該在應(yīng)用的運(yùn)行期間一直存在,建議使用單例模式或者靜態(tài)單例模式彼哼。一個(gè)SqlSessionFactory對應(yīng)配置文件中的一個(gè)環(huán)境(environment),如果你要使用多個(gè)數(shù)據(jù)庫就配置多個(gè)環(huán)境分別對應(yīng)一個(gè)SqlSessionFactory。
SqlSession:SqlSession是一個(gè)接口沟优,它有2個(gè)實(shí)現(xiàn)類,分別是DefaultSqlSession(默認(rèn)使用)以及SqlSessionManager睬辐。SqlSession通過內(nèi)部存放的執(zhí)行器(Executor)來對數(shù)據(jù)進(jìn)行CRUD挠阁。此外SqlSession不是線程安全的,因?yàn)槊恳淮尾僮魍陻?shù)據(jù)庫后都要調(diào)用close對其進(jìn)行關(guān)閉溯饵,官方建議通過try-finally來保證總是關(guān)閉SqlSession侵俗。
Executor:Executor(執(zhí)行器)接口有兩個(gè)實(shí)現(xiàn)類,其中BaseExecutor有三個(gè)繼承類分別是BatchExecutor(重用語句并執(zhí)行批量更新)丰刊,ReuseExecutor(重用預(yù)處理語句prepared statements)隘谣,SimpleExecutor(普通的執(zhí)行器)。以上三個(gè)就是主要的Executor啄巧。通過下圖可以看到Mybatis在Executor的設(shè)計(jì)上面使用了裝飾者模式寻歧,我們可以用CachingExecutor來裝飾前面的三個(gè)執(zhí)行器目的就是用來實(shí)現(xiàn)緩存。
MappedStatement:MappedStatement就是用來存放我們SQL映射文件中的信息包括sql語句棵帽,輸入?yún)?shù)熄求,輸出參數(shù)等等。一個(gè)SQL節(jié)點(diǎn)對應(yīng)一個(gè)MappedStatement對象逗概。
解析過程
1 SqlSessionFactoryBuilder.build 創(chuàng)建DefaultSqlSessionFactory實(shí)體弟晚。
使用XMLConfigBuilder .parse()解析mybatis-config.xml, 生成Configuration對象(很重要的對象)
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
SqlSessionFactory var5;
try {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
var5 = this.build(parser.parse());
} catch (Exception var14) {
throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException var13) {
}
}
return var5;
}
2 通過DefaultSqlSessionFactory.openSession創(chuàng)建DefaultSqlSession。
openSession->openSessionFromDataSource
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
DefaultSqlSession var8;
try {
Environment environment = this.configuration.getEnvironment();
TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.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;
}
3 通過DefaultSqlSession拿到Mapper對象的代理MapperProxy.
mapperProxyFactory.newInstance(sqlSession)卿城,生成MapperProxyFactory代理對象
public <T> T getMapper(Class<T> type) {
return this.configuration.getMapper(type, this);
}
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return this.mapperRegistry.getMapper(type, sqlSession);
}
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
} else {
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception var5) {
throw new BindingException("Error getting mapper instance. Cause: " + var5, var5);
}
}
}
public T newInstance(SqlSession sqlSession) {
MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);
return this.newInstance(mapperProxy);
}
protected T newInstance(MapperProxy<T> mapperProxy) {
return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
}
4 通過MapperProxy調(diào)用Maper中相應(yīng)的方法
MapperProxy.invoke->MapperMethod.execute
先解析參數(shù)枚钓,在調(diào)sqlSession.insert執(zhí)行sql.
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
}
if (this.isDefaultMethod(method)) {
return this.invokeDefaultMethod(proxy, method, args);
}
} catch (Throwable var5) {
throw ExceptionUtil.unwrapThrowable(var5);
}
MapperMethod mapperMethod = this.cachedMapperMethod(method);
return mapperMethod.execute(this.sqlSession, args);
}
// 產(chǎn)生MapperMethod ,這個(gè)對象很重要瑟押,是sql.xml生成的
private MapperMethod cachedMapperMethod(Method method) {
MapperMethod mapperMethod = (MapperMethod)this.methodCache.get(method);
if (mapperMethod == null) {
mapperMethod = new MapperMethod(this.mapperInterface, method, this.sqlSession.getConfiguration());
this.methodCache.put(method, mapperMethod);
}
return mapperMethod;
}
// 最終執(zhí)行sql地方
public Object execute(SqlSession sqlSession, Object[] args) {
Object param;
Object result;
switch(this.command.getType()) {
case INSERT:
param = this.method.convertArgsToSqlCommandParam(args);
result = this.rowCountResult(sqlSession.insert(this.command.getName(), param));
break;
case UPDATE:
param = this.method.convertArgsToSqlCommandParam(args);
result = this.rowCountResult(sqlSession.update(this.command.getName(), param));
break;
case DELETE:
param = this.method.convertArgsToSqlCommandParam(args);
result = this.rowCountResult(sqlSession.delete(this.command.getName(), param));
break;
case SELECT:
if (this.method.returnsVoid() && this.method.hasResultHandler()) {
this.executeWithResultHandler(sqlSession, args);
result = null;
} else if (this.method.returnsMany()) {
result = this.executeForMany(sqlSession, args);
} else if (this.method.returnsMap()) {
result = this.executeForMap(sqlSession, args);
} else if (this.method.returnsCursor()) {
result = this.executeForCursor(sqlSession, args);
} else {
param = this.method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(this.command.getName(), param);
}
break;
case FLUSH:
result = sqlSession.flushStatements();
break;
default:
throw new BindingException("Unknown execution method for: " + this.command.getName());
}
if (result == null && this.method.getReturnType().isPrimitive() && !this.method.returnsVoid()) {
throw new BindingException("Mapper method '" + this.command.getName() + " attempted to return null from a method with a primitive return type (" + this.method.getReturnType() + ").");
} else {
return result;
}
}
5 DefaultSqlSession.update執(zhí)行sql
最終使用的是Executor執(zhí)行sql
public int update(String statement, Object parameter) {
int var4;
try {
this.dirty = true;
MappedStatement ms = this.configuration.getMappedStatement(statement);
var4 = this.executor.update(ms, this.wrapCollection(parameter));
} catch (Exception var8) {
throw ExceptionFactory.wrapException("Error updating database. Cause: " + var8, var8);
} finally {
ErrorContext.instance().reset();
}
return var4;
}