Mybatis执行SQL原理

Mybatis执行SQL时首先从SqlSessionFactory中获取一个SqlSession然后由SqlSession去执行具体的Mapper中映射的SQL方法。

1
2
3
4
5
6
7
8
9
10
String resource = "mybatis-config.xml";
// 将XML配置文件构建为Configuration配置类
Reader reader = Resources.getResourceAsReader(resource);
// 通过加载配置文件流构建一个SqlSessionFactory DefaultSqlSessionFactory
SqlSessionFactory sqlMapper = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sqlMapper.openSession(); // 数据源执行器DefaultSqlSession
User user = session.selectOne("com.eleven.mapper.UserMapper.selectById", 1);
// 还可以通过SqlSession获取具体的Mapper接口然后调用具体的方法。
UserMapper mapper = session.getMapper(UserMapper.class);
mapper.selectById(1L);

首先获取环境变量Environment,从环境变量中获取事务工厂默认的事务工厂是JdbcTransactionFactory,在通过事务工厂创建事务默认是创建JdbcTransaction。然后通过事务创建SQL执行器,默认创建SimpleExecutor。由于默认是开启二级缓存的,故这里会用CachingExecutorSimpleExecutor装饰一遍。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class DefaultSqlSessionFactory implements SqlSessionFactory {
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
final Environment environment = configuration.getEnvironment(); // 获取环境变量
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); // 获取事务工厂
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
// 创建一个sql执行器对象,一般情况下若Mybaits全局配置文件的cacheEnabled默认为ture就返回cacheExecutor,否则返回的就是一个SimpleExecutor
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit); // 创建返回一个DefaultSqlSession对象返回
} 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();
}
}
}
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor 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); // 简单的sql执行器对象
}
if (cacheEnabled) { // 判断mybatis的全局配置文件是否开启缓存,默认开启
executor = new CachingExecutor(executor); //把当前的简单的执行器包装成一个CachingExecutor
}
executor = (Executor) interceptorChain.pluginAll(executor); // 调用所有的拦截器对象plugin方法
return executor;
}

创建Executor时最终会调用超类BaseExecutor的构造方法从而创建类型为PerpetualCache的一级缓存localCache

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class SimpleExecutor extends BaseExecutor {
public SimpleExecutor(Configuration configuration, Transaction transaction) {
super(configuration, transaction);
}
}
public abstract class BaseExecutor implements Executor {
protected BaseExecutor(Configuration configuration, Transaction transaction) {
this.transaction = transaction;
this.deferredLoads = new ConcurrentLinkedQueue<>();
this.localCache = new PerpetualCache("LocalCache");
this.localOutputParameterCache = new PerpetualCache("LocalOutputParameterCache");
this.closed = false;
this.configuration = configuration;
this.wrapper = this;
}
}

Executor分成CacheExecutor普通Executor两大类,普通Executor又分SimpleExecutorReuseExecutorBatchExecutor三种基本的Executor执行器。

  • SimpleExecutor:每执行一次updateselect开启一个Statement对象,用完立刻关闭Statement对象
  • ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在则使用不存在则创建,用完后不关闭Statement对象,而是放置于Map内供下一次使用。可重复使用Statement对象
  • BatchExecutor:JDBC批处理不支持select,执行update,将所有sql都添加到批处理中等待统一执行,它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理,与JDBC批处理相同。

CacheExecutor其实是封装了普通的Executor,和普通Executor区别查询前先会查询缓存中是否存在结果,若存在则使用缓存中的结果,若不存在则使用普通Executor进行查询,再将查询出来的结果存入缓存。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class InterceptorChain {
private final List<Interceptor> interceptors = new ArrayList<>();
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
}
public interface Interceptor {
default Object plugin(Object target) {
return Plugin.wrap(target, this);
}
}
public class Plugin implements InvocationHandler {
private final Object target;
private final Interceptor interceptor;
private final Map<Class<?>, Set<Method>> signatureMap;
private Plugin(Object target, Interceptor interceptor, Map<Class<?>, Set<Method>> signatureMap) {
this.target = target;
this.interceptor = interceptor;
this.signatureMap = signatureMap;
}
public static Object wrap(Object target, Interceptor interceptor) {
Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor); // 获得interceptor配置的@Signature的type
Class<?> type = target.getClass(); // 当前代理类型
Class<?>[] interfaces = getAllInterfaces(type, signatureMap); // 根据当前代理类型和@signature指定的type进行配对,配对成功则可以代理
if (interfaces.length > 0) {
return Proxy.newProxyInstance(type.getClassLoader(), interfaces, new Plugin(target, interceptor, signatureMap));
}
return target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
Set<Method> methods = signatureMap.get(method.getDeclaringClass());
if (methods != null && methods.contains(method)) {
return interceptor.intercept(new Invocation(target, method, args));
}
return method.invoke(target, args);
} catch (Exception e) {
throw ExceptionUtil.unwrapThrowable(e);
}
}
private static Map<Class<?>, Set<Method>> getSignatureMap(Interceptor interceptor) {
Intercepts interceptsAnnotation = interceptor.getClass().getAnnotation(Intercepts.class);
if (interceptsAnnotation == null) {
throw new PluginException("No @Intercepts annotation was found in interceptor " + interceptor.getClass().getName());
}
Signature[] sigs = interceptsAnnotation.value();
Map<Class<?>, Set<Method>> signatureMap = new HashMap<>();
for (Signature sig : sigs) {
Set<Method> methods = signatureMap.computeIfAbsent(sig.type(), k -> new HashSet<>());
try {
Method method = sig.type().getMethod(sig.method(), sig.args());
methods.add(method);
} catch (NoSuchMethodException e) {
throw new PluginException("Could not find method on " + sig.type() + " named " + sig.method() + ". Cause: " + e, e);
}
}
return signatureMap;
}
}

创建好了SQL执行器后,通过InterceptorChain#pluginAll为SQL执行器创建拦截器代理对象,拦截器链是在全局配置文件中通过plugins标签配置的,在XML文件解析是就解析好放到Configuration#interceptorChain中。最后调用时通过责任链的方式依次调用。拦截器示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Intercepts({@Signature(type = Executor.class, method = "query", args = {
MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class
})})
//@Intercepts({@Signature( type= StatementHandler.class, method = "update", args ={Statement.class})})
public class ExamplePlugin implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.out.println("代理");
Object[] args = invocation.getArgs();
MappedStatement ms = (MappedStatement) args[0];
return invocation.proceed();
}
@Override
public Object plugin(Object target) { // new4大对象的时候调用,所以4大对象都会被代理到Plugin
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) { // 加载的时候调用, 设置属性初始化
System.out.println(111);
}
}

sqlSession.getMapper方法,会调用Configration对象的getMapper方法,直接从缓存knownMappers中通过Mapper的class类型得到MapperProxyFactory,通过MapperProxyFactory来创建Mapper接口动态代理类MapperProxy,MapperProxy实现了InvocationHandler接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public <T> T getMapper(Class<T> type) {
return configuration.getMapper(type, this);
}
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession); // mapperRegistry实质上是一个Map,里面注册了启动过程中解析的各种Mapper.xml
}
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
// 直接去缓存knownMappers中通过Mapper的class类型去找mapperProxyFactory
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); // 通过MapperProxyFactory来创建实例
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache); // 创建代理对象
return newInstance(mapperProxy); // 创建Mapper代理对象返回
}
protected T newInstance(MapperProxy<T> mapperProxy) {
// 生成Mapper接口的动态代理类MapperProxy,MapperProxy实现了InvocationHandler接口
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}

调用Mapper接口的所有方法都会先调用到动态代理类MapperProxyinvoke方法,由于Mybatis中Mapper接口没有实现类,故MapperProxy代理对象中没有委托类,MapperProxy干了代理类和委托类的事情。首先从缓存中获取调用方法的信息,若获取不到则将当前方法封装为一个MapperMethod并保存到缓存中,在构造MapperMethodMapper接口及方法进行解析,并保存到SqlCommand中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public class MapperProxy<T> implements InvocationHandler, Serializable {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args); // 判断方法是不是Object类定义的方法,若是直接通过反射调用
} else if (method.isDefault()) { // 是否接口的默认方法
return invokeDefaultMethod(proxy, method, args); // 调用接口中的默认方法
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
final MapperMethod mapperMethod = cachedMapperMethod(method); // 把方法对象封装成一个MapperMethod对象,带有缓存作用的
return mapperMethod.execute(sqlSession, args);
}
private MapperMethod cachedMapperMethod(Method method) {
return methodCache.computeIfAbsent(method, k -> new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
}
}
public class MapperMethod {
private final SqlCommand command; // 用于保存Mapper接口方法信息
private final MethodSignature method;
public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
this.command = new SqlCommand(config, mapperInterface, method); // 创建的SqlCommand对象
this.method = new MethodSignature(config, mapperInterface, method); // 创建的方法签名对象
}
}
public static class SqlCommand { // 用户保存Mapper接口方法信息
private final String name; // 接口的方法名全路径比如:com.eleven.mapper.DeptMapper.findDepts
private final SqlCommandType type; // 对应接口方法操作的sql类型(是insert|update|delte|select)
public SqlCommand(Configuration configuration, Class<?> mapperInterface, Method method) {
final String methodName = method.getName(); //获取的方法的名称
final Class<?> declaringClass = method.getDeclaringClass(); //方法所在接口的类型
// 根据接口,方法名称解析出对应的mapperStatment对象
MappedStatement ms = resolveMappedStatement(mapperInterface, methodName, declaringClass, configuration);
if (ms == null) {
if (method.getAnnotation(Flush.class) != null) {
name = null;
type = SqlCommandType.FLUSH;
} else {
throw new BindingException("Invalid bound statement (not found): " + mapperInterface.getName() + "." + methodName);
}
} else {
name = ms.getId(); //把的mappedStatmentID(com.eleven.mapper.EmpMapper.findEmp)
type = ms.getSqlCommandType(); //sql操作的类型(比如insert|delete|update|select)
if (type == SqlCommandType.UNKNOWN) {
throw new BindingException("Unknown execution method for: " + name);
}
}
}
private MappedStatement resolveMappedStatement(Class<?> mapperInterface, String methodName, Class<?> declaringClass, Configuration configuration) {
String statementId = mapperInterface.getName() + "." + methodName; // 获取的sql对应的statmentId(com.eleven.mapper.DeptMapper.findDepts)
if (configuration.hasStatement(statementId)) { // 根据的statmentId判断的主配置类是否包含了的mapperStatment对象
return configuration.getMappedStatement(statementId); // 存在通过key获取对应的mapperStatment对象返回
} else if (mapperInterface.equals(declaringClass)) {
return null;
}
for (Class<?> superInterface : mapperInterface.getInterfaces()) { // 获取mapper接口的父类接口
if (declaringClass.isAssignableFrom(superInterface)) {//判断方法所在的类是否实现了superInterface
MappedStatement ms = resolveMappedStatement(superInterface, methodName, declaringClass, configuration); //解析父类的MappedStatment对象
if (ms != null) {
return ms;
}
}
}
return null;
}
}

根据解析出的SQL命令类型执行不同的逻辑,但最终都是调用SqlSession中定义的方法来完成具体的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public class MapperMethod {
private final SqlCommand command; // 用于保存Mapper接口方法信息
private final MethodSignature method;
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
switch (command.getType()) { // 判断执行sql命令的类型
case INSERT: { // insert操作
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.insert(command.getName(), param));
break;
}
case UPDATE: { //update操作
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.update(command.getName(), param));
break;
}
case DELETE: { //delete操作
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.delete(command.getName(), param));
break;
}
case SELECT: //select操作
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null; //返回值为空
} else if (method.returnsMany()) {//返回值是一个List
result = executeForMany(sqlSession, args);
} else if (method.returnsMap()) {//返回值是一个map
result = executeForMap(sqlSession, args);
} else if (method.returnsCursor()) {//返回游标
result = executeForCursor(sqlSession, args);
} else {//查询返回单个
Object param = method.convertArgsToSqlCommandParam(args); // 解析参数
result = sqlSession.selectOne(command.getName(), param);
if (method.returnsOptional() && (result == null || !method.getReturnType().equals(result.getClass()))) {
result = Optional.ofNullable(result);
}
}
break;
case FLUSH:
result = sqlSession.flushStatements();
break;
default:
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;
}
}

执行具体的SQL时,首先通过statement获取启动时解析到Configuration#mappedStatements中的MappedStatement,然后调用具体SQL执行器去执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class DefaultSqlSession implements SqlSession {
public <T> T selectOne(String statement, Object parameter) {
List<T> list = this.selectList(statement, parameter); // 这里selectOne调用也是调用selectList方法
if (list.size() == 1) { //若查询出来有且有一个一个对象,直接返回要给
return list.get(0);
} else if (list.size() > 1) { // 查询的有多个,则抛出异常
throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
} else {
return null;
}
}
public <E> List<E> selectList(String statement, Object parameter) {
return this.selectList(statement, parameter, RowBounds.DEFAULT);
}
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
// 第一步:通过statement去全局配置类中获取MappedStatement
MappedStatement ms = configuration.getMappedStatement(statement);
// 通过执行器去执行sql对象 第一步:包装集合类参数 第二步:一般情况下是executor为cacheExetory对象
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();
}
}
}

这里默认是CachingExecutor执行器,在通过执行器执行SQL之前,首先通过MappedStatement#getBoundSql对SQL进行解析,实际调用在解析Mapper文件阶段解析好的SqlSourcegetBoundSql方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class CachingExecutor implements Executor {
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
BoundSql boundSql = ms.getBoundSql(parameterObject); // 通过参数对象解析sql详细信息
CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
}
public final class MappedStatement {
public BoundSql getBoundSql(Object parameterObject) {
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings == null || parameterMappings.isEmpty()) {
boundSql = new BoundSql(configuration, boundSql.getSql(), parameterMap.getParameterMappings(), parameterObject);
}
for (ParameterMapping pm : boundSql.getParameterMappings()) {
String rmId = pm.getResultMapId();
if (rmId != null) {
ResultMap rm = configuration.getResultMap(rmId);
if (rm != null) {
hasNestedResultMaps |= rm.hasNestedResultMaps();
}
}
}
return boundSql;
}
}

对于SqlSource主要是封装动态SQLDynamicSqlSource、封装@SelectProvider等一些类注解方法解析的SQL的ProviderSqlSource封装静态SQL的RawSqlSource封装静态SQL的StaticSqlSource四个实现类。对于静态SQL是使用RawSqlSource来进行封装,但RawSqlSource内部通过SqlSourceBuilder将其转换成了StaticSqlSource,转换过程中会将#{..}解析替换成?,并将参数映射关系保存到StaticSqlSource#parameterMappings中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class RawSqlSource implements SqlSource {
private final SqlSource sqlSource;
public RawSqlSource(Configuration configuration, SqlNode rootSqlNode, Class<?> parameterType) {
this(configuration, getSql(configuration, rootSqlNode), parameterType);
}
public RawSqlSource(Configuration configuration, String sql, Class<?> parameterType) {
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
Class<?> clazz = parameterType == null ? Object.class : parameterType;
sqlSource = sqlSourceParser.parse(sql, clazz, new HashMap<>());
}
private static String getSql(Configuration configuration, SqlNode rootSqlNode) {
DynamicContext context = new DynamicContext(configuration, null);
rootSqlNode.apply(context);
return context.getSql();
}
@Override
public BoundSql getBoundSql(Object parameterObject) {
return sqlSource.getBoundSql(parameterObject);
}
}
public class SqlSourceBuilder extends BaseBuilder {
public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);
GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
String sql = parser.parse(originalSql);
return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
}
}

对于动态SQL被封装为DynamicSqlSource,然后通过SqlNodeapply进行SQL解析,对于动态SQL来说最外层的SqlNode一般为MixedSqlNode,最终遍历调用具体SqlNode的apply方法,主要完成将动态SQL根据传入的参数值确定为静态SQL,且将${...}替换为具体的值,从而完成动态SQL的解析。接下来通过SqlSourceBuilder#parse#{..}解析替换成?,并将参数映射关系保存到StaticSqlSource#parameterMappings中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class DynamicSqlSource implements SqlSource {
private final Configuration configuration;
private final SqlNode rootSqlNode;
public BoundSql getBoundSql(Object parameterObject) {
DynamicContext context = new DynamicContext(configuration, parameterObject);
rootSqlNode.apply(context);
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
context.getBindings().forEach(boundSql::setAdditionalParameter);
return boundSql;
}
}
public class MixedSqlNode implements SqlNode {
public boolean apply(DynamicContext context) {
contents.forEach(node -> node.apply(context));
return true;
}
}

当SQL解析成静态SQL后,则开始通过CachingExecutor先判断是否开启了二级缓存,若开启了二级缓存,先判断是否需要刷新缓存,判断依据是在解析阶段判断SQL的类型是否为SELECT查询,若不为查询则需要刷新缓存,然后从缓存中获取数据,若缓存中没有获取到数据再通过执行器去查询数据,并将数据缓存到二级缓存中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class CachingExecutor implements Executor {
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
Cache cache = ms.getCache(); // 判断mapper中是否开启了二级缓存<cache></cache>
if (cache != null) { // 判断是否配置了cache
flushCacheIfRequired(ms); // 判断是否需要刷新缓存
if (ms.isUseCache() && resultHandler == null) {
ensureNoOutParams(ms, boundSql);
List<E> list = (List<E>) tcm.getObject(cache, key); // 先去二级缓存中获取
if (list == null) { // 二级缓存中没有获取到,通过查询数据库去查询
list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
tcm.putObject(cache, key, list); // 加入到二级缓存中
}
return list;
}
}
return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); // 没有整合二级缓存,直接去查询
}
}

会先判断是否为SELECT查询,若不是则需要清空一级缓存中的数据,然后从一级换中获取数据,若获取不到再真正通过执行器获取数据,且将查询后的数据缓存到一级缓存中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public abstract class BaseExecutor implements Executor {
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
if (closed) { // 已经关闭,则抛出 ExecutorException 异常
throw new ExecutorException("Executor was closed.");
}
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache(); // 清空本地缓存,若queryStack为零,并要求清空本地缓存
}
List<E> list;
try {
queryStack++;
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);
}
} finally {
queryStack--;
}
if (queryStack == 0) {
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
deferredLoads.clear();
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
clearLocalCache();
}
}
return list;
}
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
List<E> list;
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
localCache.removeObject(key);
}
localCache.putObject(key, list);
if (ms.getStatementType() == StatementType.CALLABLE) {
localOutputParameterCache.putObject(key, parameter);
}
return list;
}
}

最终调用SimpleExecutor中的执行方法,首先会先创建一个StatementHandler其封装了JDBC Statement操作,负责对JDBC statement如设置参数将Statement结果集转换成List集合等操作。具体的StatementHandler的创建是委托给RoutingStatementHandler通过statementType去创建具体的StatementHandler。支持SimpleStatementHandlerPreparedStatementHandlerCallableStatementHandler三种StatementHandler。Mybatis默认使用PreparedStatementHandler。创建完成StatementHandler后会为其创建拦截器链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class SimpleExecutor extends BaseExecutor {
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();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
Connection connection = getConnection(statementLog);
stmt = handler.prepare(connection, transaction.getTimeout());
handler.parameterize(stmt);
return stmt;
}
}
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
public class RoutingStatementHandler implements StatementHandler {
private final StatementHandler delegate;
public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
switch (ms.getStatementType()) {
case STATEMENT:
delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case PREPARED:
delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case CALLABLE:
delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
default:
throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
}
}
}
public class PreparedStatementHandler extends BaseStatementHandler {
public PreparedStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
}
}

通过StatementHandlerprepare生成具体的Statement。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public abstract class BaseStatementHandler implements StatementHandler {
protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
this.configuration = mappedStatement.getConfiguration();
this.executor = executor;
this.mappedStatement = mappedStatement;
this.rowBounds = rowBounds;
this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
this.objectFactory = configuration.getObjectFactory();
if (boundSql == null) { // issue #435, get the key before calculating the statement
generateKeys(parameterObject);
boundSql = mappedStatement.getBoundSql(parameterObject);
}
this.boundSql = boundSql;
this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
}
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
ErrorContext.instance().sql(boundSql.getSql());
Statement statement = null;
try {
statement = instantiateStatement(connection);
setStatementTimeout(statement, transactionTimeout);
setFetchSize(statement);
return statement;
} catch (SQLException e) {
closeStatement(statement);
throw e;
} catch (Exception e) {
closeStatement(statement);
throw new ExecutorException("Error preparing statement. Cause: " + e, e);
}
}
}
public class PreparedStatementHandler extends BaseStatementHandler {
protected Statement instantiateStatement(Connection connection) throws SQLException {
String sql = boundSql.getSql();
if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
String[] keyColumnNames = mappedStatement.getKeyColumns();
if (keyColumnNames == null) {
return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
} else {
return connection.prepareStatement(sql, keyColumnNames);
}
} else if (mappedStatement.getResultSetType() == ResultSetType.DEFAULT) {
return connection.prepareStatement(sql);
} else {
return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
}
}
}

对于参数的设置以及结果的处理,StatementHandlerparameterize为Statement设置具体SQL执行的参数,在执行查询方法时对结果进行处理,是通过在实例化具体的StatementHandler时,调用超类BaseStatementHandler中的构造方法去创建ParameterHandlerResultSetHandler分别对参数和结果数据进行处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class PreparedStatementHandler extends BaseStatementHandler {
public PreparedStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
}
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
return resultSetHandler.handleResultSets(ps);
}
}
public abstract class BaseStatementHandler implements StatementHandler {
protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
this.configuration = mappedStatement.getConfiguration();
this.executor = executor;
this.mappedStatement = mappedStatement;
this.rowBounds = rowBounds;
this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
this.objectFactory = configuration.getObjectFactory();
if (boundSql == null) {
generateKeys(parameterObject);
boundSql = mappedStatement.getBoundSql(parameterObject);
}
this.boundSql = boundSql;
this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
}
}

ParameterHandler负责将传递的参数转换成JDBC Statement所需参数,创建ParameterHandler是通过LanguageDriver中的方法来创建的,在进行参数处理时是通过setParameters来完成的,在该方法中会先确定参数类型,最终通过TypeHandler调用具体TypeHandler的setNonNullParameter方法,创建完成后跟执行器一样会创建拦截器链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
public class Configuration {
public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
return parameterHandler;
}
}
public class XMLLanguageDriver implements LanguageDriver {
public ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
return new DefaultParameterHandler(mappedStatement, parameterObject, boundSql);
}
}
public class DefaultParameterHandler implements ParameterHandler {
public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
this.mappedStatement = mappedStatement;
this.configuration = mappedStatement.getConfiguration();
this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
this.parameterObject = parameterObject;
this.boundSql = boundSql;
}
public void setParameters(PreparedStatement ps) {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings != null) {
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
TypeHandler typeHandler = parameterMapping.getTypeHandler();
JdbcType jdbcType = parameterMapping.getJdbcType();
if (value == null && jdbcType == null) {
jdbcType = configuration.getJdbcTypeForNull();
}
try {
typeHandler.setParameter(ps, i + 1, value, jdbcType);
} catch (TypeException | SQLException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
}
}
}
}
}
}
public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
if (parameter == null) {
if (jdbcType == null) {
throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");
}
try {
ps.setNull(i, jdbcType.TYPE_CODE);
} catch (SQLException e) {
throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. Cause: " + e, e);
}
} else {
try {
setNonNullParameter(ps, i, parameter, jdbcType);
} catch (Exception e) {
throw new TypeException("Error setting non null for parameter #" + i + " with JdbcType " + jdbcType + " . Try setting a different JdbcType for this parameter or a different configuration property. Cause: " + e, e);
}
}
}
public class LongTypeHandler extends BaseTypeHandler<Long> {
public void setNonNullParameter(PreparedStatement ps, int i, Long parameter, JdbcType jdbcType) throws SQLException {
ps.setLong(i, parameter);
}
}

ResultSetHandler负责将JDBC返回的ResultSet结果集对象转换成具体设置的对象,创建ResultSetHandler是直接new一个默认的DefaultResultSetHandler,对结果数据的处理是最终会调用handleResultSets来完成,创建完成后同样会创建拦截器链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class Configuration {
public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler, ResultHandler resultHandler, BoundSql boundSql) {
ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
return resultSetHandler;
}
}
public class DefaultResultSetHandler implements ResultSetHandler {
public DefaultResultSetHandler(Executor executor, MappedStatement mappedStatement, ParameterHandler parameterHandler, ResultHandler<?> resultHandler, BoundSql boundSql, RowBounds rowBounds) {
this.executor = executor;
this.configuration = mappedStatement.getConfiguration();
this.mappedStatement = mappedStatement;
this.rowBounds = rowBounds;
this.parameterHandler = parameterHandler;
this.boundSql = boundSql;
this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
this.objectFactory = configuration.getObjectFactory();
this.reflectorFactory = configuration.getReflectorFactory();
this.resultHandler = resultHandler;
}
public List<Object> handleResultSets(Statement stmt) throws SQLException {
ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
final List<Object> multipleResults = new ArrayList<>();
int resultSetCount = 0;
ResultSetWrapper rsw = getFirstResultSet(stmt);
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
int resultMapCount = resultMaps.size();
validateResultMapsCount(rsw, resultMapCount);
while (rsw != null && resultMapCount > resultSetCount) {
ResultMap resultMap = resultMaps.get(resultSetCount);
handleResultSet(rsw, resultMap, multipleResults, null);
rsw = getNextResultSet(stmt);
cleanUpAfterHandlingResultSet();
resultSetCount++;
}
String[] resultSets = mappedStatement.getResultSets();
if (resultSets != null) {
while (rsw != null && resultSetCount < resultSets.length) {
ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
if (parentMapping != null) {
String nestedResultMapId = parentMapping.getNestedResultMapId();
ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
handleResultSet(rsw, resultMap, null, parentMapping);
}
rsw = getNextResultSet(stmt);
cleanUpAfterHandlingResultSet();
resultSetCount++;
}
}
return collapseSingleResultList(multipleResults);
}
}