獲取sqlSession流程
- new SqlSessionFactoryBuilder對象
- sqlSessionFactoryBuilder對象new出一個XMLConfigBuilder對象,讀取mybatis-config.xml配置文件信息碱蒙,返回configuration
- sqlsessionFactoryBuilder調(diào)用build(configuration方法)荠瘪,返回defaultSqlSessionFactory
- sqlSessionFactory調(diào)用opensession方法,返回sqlSession
獲取sqlSession流程.png
- openSessionFromDataSource源碼
- 從配置中獲取Environment赛惩;
- 從Environment中取得DataSource哀墓;
- 從Environment中取得TransactionFactory;
- 從DataSource里獲取數(shù)據(jù)庫連接對象Connection喷兼;
- 在取得的數(shù)據(jù)庫連接上創(chuàng)建事務(wù)對象Transaction篮绰;
- 創(chuàng)建Executor對象(該對象非常重要,事實上sqlsession的所有操作都是通過它完成的)褒搔;
- 創(chuàng)建sqlsession對象阶牍;
/**
* 通常一系列openSession方法最終都會調(diào)用本方法
* @param execType
* @param level
* @param autoCommit
* @return
*/
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
//通過Confuguration對象去獲取Mybatis相關(guān)配置信息, Environment對象包含了數(shù)據(jù)源和事務(wù)的配置
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
//之前說了喷面,從表面上來看,咱們是用sqlSession在執(zhí)行sql語句走孽,通過excutor執(zhí)行惧辈, excutor是對于Statement的封裝
final Executor executor = configuration.newExecutor(tx, execType);
//創(chuàng)建了一個DefaultSqlSession對象
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(tx); // may have fetched a connection so lets call close()
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
-
MapperProxy分析
mapperProxy獲取流程.png
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
//獲取代理工廠,在解析配置文件時磕瓷,會在knownMappers中放入key為Class<T>,value為代理工廠類對象
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
protected T newInstance(MapperProxy<T> mapperProxy) {
//jdk動態(tài)代理
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
//代理類
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
//代理類實現(xiàn) jdk動態(tài)代理接口
public class MapperProxy<T> implements InvocationHandler, Serializable {
private static final long serialVersionUID = -6424540398559729838L;
private final SqlSession sqlSession;
private final Class<T> mapperInterface;
private final Map<Method, MapperMethod> methodCache;
public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
this.sqlSession = sqlSession;
this.mapperInterface = mapperInterface;
this.methodCache = methodCache;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Object.class.equals(method.getDeclaringClass())) {
try {
return method.invoke(this, args);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
//通過MapperMethod來真正的實現(xiàn)增刪改查功能
final MapperMethod mapperMethod = cachedMapperMethod(method);
//執(zhí)行增刪改查
return mapperMethod.execute(sqlSession, args);
}
private MapperMethod cachedMapperMethod(Method method) {
MapperMethod mapperMethod = methodCache.get(method);
if (mapperMethod == null) {
mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
methodCache.put(method, mapperMethod);
}
return mapperMethod;
}
}
- excutor分析
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
//根據(jù)不同的sqlCommandType類型盒齿,以及不同的返回類型,調(diào)用不同的方法
if (SqlCommandType.INSERT == command.getType()) {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.insert(command.getName(), param));
} else if (SqlCommandType.UPDATE == command.getType()) {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.update(command.getName(), param));
} else if (SqlCommandType.DELETE == command.getType()) {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.delete(command.getName(), param));
} else if (SqlCommandType.SELECT == command.getType()) {
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null;
} else if (method.returnsMany()) {
result = executeForMany(sqlSession, args);
} else if (method.returnsMap()) {
result = executeForMap(sqlSession, args);
} else {
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
}
} else if (SqlCommandType.FLUSH == command.getType()) {
result = sqlSession.flushStatements();
} else {
throw new BindingException("Unknown execution method for: " + command.getName());
}
if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
throw new BindingException("Mapper method '" + command.getName()
+ " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
}
return result;
}
@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
//獲取mapperStatement信息
MappedStatement ms = configuration.getMappedStatement(statement);
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();
}
}
//最終會調(diào)用這個方法中
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
//獲取statement代理對象 并且或創(chuàng)建resultehander代理對象
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.<E>query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}