后面开始分析sql执行的源码流程
也就是这一部分
重点关注configuration.newExecutor这个方法,获取事务处理器比较简单,就是获取一个jdbc的事务管理器。
执行完成之后最后生成了一个DefaultSqlSession,有关DefaultSqlSession,特别要注意一点,它是一个非线程安全的类。
�
关于knownMappers前面讲过:是一个map,里面存放的是mapper的类型和MapperProxyFactory类。
后面就是调用mapperProxyFactory.newInstance(sqlSession)进行mapper接口的实例化。
最终会拿着mapper接口、代理方法缓存 生成InvokeHandler(用来生成Jdk代理必须要的类,当调用被代理的方法的时候,会调用到InvokeHandler的invokde方法)
最终返回的代理对象就是下图所示:
当我们调用这个查询方法的时候,最终会调用到userProxy的invoke方法
先看cachedInvoker方法,
最终会生成一个PlainMethodInvoker,这个类是MapperProxy的静态内部类
这里会调用到mapperMethod.execute方法, MapperMethod中,command存放的是sql的一些信息,method存放方法的一些信息
public class MapperMethod {
// todo 存放sql的一些信息,其中name属性存放的是“包名、类名、方法名”
private final SqlCommand command;
// todo 方法的签名,主要存放方法的一些信息
private final MethodSignature method;
public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
this.command = new SqlCommand(config, mapperInterface, method);
this.method = new MethodSignature(config, mapperInterface, method);
}
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
switch (command.getType()) {
case INSERT: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.insert(command.getName(), param));
break;
}
case UPDATE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.update(command.getName(), param));
break;
}
case DELETE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.delete(command.getName(), param));
break;
}
case SELECT:
// todo 处理查询操作
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null;
} else if (method.returnsMany()) {
// todo 返回多行记录
result = executeForMany(sqlSession, args);
} else if (method.returnsMap()) {
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;
}
在execute方法里面,会处理 sql 的 INSERT(mapper.xml 中的 insert 标签)、UPDATE(mapper.xml 中的 update 标签)、DELETE(mapper.xml 中的 delete 标签)、SELECT(mapper.xml 中的 select 标签)、FLUSH(针对 BatchExecutor 执行器,执行缓存的 Statement)等操作,这里我们仅关注 select 操作
接下来调用DefaultSqlSession.selectList方法来执行
这里会从configuration里面通过接口对应的MappedStatement,通过执行器调用执行,由于我们默认设置了一级缓存,所以会执行到CacheingExecutor.query方法
这个delegate.query最终调用的是SimpleExecutor.query方法
最终会执行到simpleExecutor.doQuery方法
本文主要介绍了 mybatis 执行 sql 的流程,介绍的内容如下: