SQL执行过程
一个例子
1 | public void querytOne() throws IOException { |
sql的执行如下:先根据反射获取一个Mapper对象,代理传入的类;然后根据sql的类型,比如select,返回的是map还是list还是void,选择不同的执行方法,解析参数的信息,判断是否有可以从缓存中获取数据等等,最后将查询的值经过结果处理器处理,将查询的数据放入缓存中,返回。
从1开始,获得一个Manage的代理类:根据配置文件以及sqlSession以及之前的运行状态获取1
2
3
4
5
6
7
8
9
10
11
12
13public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
//获得一个工厂对象
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
//3获取代理对象
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
在3处1
2
3
4
5
6public T newInstance(SqlSession sqlSession) {
//MapperProxy是一个实现了InvocationHandler接口的类
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
//4
return newInstance(mapperProxy);
}
1 | public class MapperProxy<T> implements InvocationHandler, Serializable { |
4 使用jdk反射new Instance1
2
3protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
此时已经拿到了一个Mapper,Mapper中包含:
在2处,接下来执行调用的方法,由于代理,与是调用invoke
方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
//如果是Object或者默认的方法,直接放行,不进行其他操作
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);
}
//否则开始检查是否有MapperMethod对象的缓存,如果有直接获取,否则创建一个。
final MapperMethod mapperMethod = cachedMapperMethod(method);
//5接下来开始执行sql语句
return mapperMethod.execute(sqlSession, args);
}
先了解一下MapperMethod类1
2
3
4public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
this.command = new SqlCommand(config, mapperInterface, method);
this.method = new MethodSignature(config, mapperInterface, method);
}
SqlCommand包含了关于这条sql的信息:1
2
3
4
5
6
7public static class SqlCommand {
//sql语句的name
private final String name;
//sql语句的type,是一个枚举类型,包括:UNKNOWN, INSERT, UPDATE, DELETE, SELECT, FLUSH;
private final SqlCommandType type;
//省略
MethodSignature包含了关于这个方法的详细详细:1
2
3
4
5
6
7
8
9
10
11
12
13
14public static class MethodSignature {
//返回的结果集的类型:many,map,空,游标等等
private final boolean returnsMany;
private final boolean returnsMap;
private final boolean returnsVoid;
private final boolean returnsCursor;
//返回的类的类型
private final Class<?> returnType;
private final String mapKey;
private final Integer resultHandlerIndex;
private final Integer rowBoundsIndex;
//参数节气器
private final ParamNameResolver paramNameResolver;
//省略其他
在5处 execute方法: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
50public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
//判断sql的类型,比如如果是isnert,就使用sqlSession的insert方法
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:
//在select中还需要判断返回的什么
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 if (method.returnsCursor()) {
result = executeForCursor(sqlSession, args);
} else {
//解析传入的参数
Object param = method.convertArgsToSqlCommandParam(args);
//调用selectOne,实际上是调用selectList取第一个
result = sqlSession.selectOne(command.getName(), param);
}
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;
}
1 | public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { |
此时可以看见Mapper对象更新了
最后sqlSession.close();会处理是否提交,是否回滚,是否将一级缓存的值放入二级缓存中等等。