
一、前提条件
Configuration
MapperStatement:服务启动时,从Mapper中读出MapperStatement并缓存到Configuration中。
protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection");
SqlSession
生成代理类MapperProxy时,需将提前生成的SqlSession传入MapperProxy。此处的SqlSession为mybatis-spring包提供的SqlSessionTemplate类,而不是DefaultSqlSession类。
public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
this.sqlSession = sqlSession;
this.mapperInterface = mapperInterface;
this.methodCache = methodCache;
}
二、MapperProxy代理dao接口
触发MapperProxy代理类的invoke方法,MapperProxy从methodCache中查找mapper对应的MapperMethod,并交由MapperMethod执行具体的方法。
private final Map<Method, MapperMethod> methodCache;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
} else if (isDefaultMethod(method)) {
return invokeDefaultMethod(proxy, method, args);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
}
三、MapperMethod执行mapper方法
MapperMethod引用SqlSessionTemplate执行查询
public Object execute(SqlSession sqlSession, Object[] args) {
......
result = executeForMany(sqlSession, args);
......
}
private <E> Object executeForMany(SqlSession sqlSession, Object[] args) {
List<E> result;
......
result = sqlSession.<E>selectList(command.getName(), param);
......
return result;
}
四、SqlSessionTemplate通过动态代理调用DefaultSqlSession执行查询
1、SqlSessionTemplate动态代理SqlSession
2、SqlSessionInterceptor实现InvocationHandler接口,当调用代理对象的接口selectList时,触发SqlSessionInterceptor的invoke方法。
3、SqlSessionInterceptor在invoke中通过DefaultSqlSession执行查询
@Override
public <E> List<E> selectList(String statement, Object parameter) {
return this.sqlSessionProxy.<E> selectList(statement, parameter);
}
this.sqlSessionProxy = (SqlSession) newProxyInstance(
SqlSessionFactory.class.getClassLoader(),
new Class[] { SqlSession.class },
new SqlSessionInterceptor());
private class SqlSessionInterceptor implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
SqlSession sqlSession = getSqlSession(
SqlSessionTemplate.this.sqlSessionFactory,
SqlSessionTemplate.this.executorType,
SqlSessionTemplate.this.exceptionTranslator);
try {
Object result = method.invoke(sqlSession, args);
if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
// force commit even on non-dirty sessions because some databases require
// a commit/rollback before calling close()
sqlSession.commit(true);
}
......
五、DefaultSqlSession委托Executor执行
@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
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();
}
}
六、Executor执行查询
先从一级缓存查询,查询不到再从数据库查询
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
if (list != null) {
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else {
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
网友评论