• java
  • go
  • 数据库
  • linux
  • 中间件
  • 书
  • 源码
  • 夕拾

  • java
  • go
  • 数据库
  • linux
  • 中间件
  • 书
  • 源码
  • 夕拾

mybatis-sqlSession

目录

  • 目录
  • 前言
  • sqlSessionFactory的创建
  • 获取sqlSession
  • mapper代理的创建
    • list查询
  • sqlSession
    • 属性
    • executor查询
      • result映射

前言

前文 configuration

sqlSessionFactory的创建

在mybatis-configuration中的示例代码中,通过SqlSessionFactoryBuilder的build方法,使用XMLConfigBuilder解析配置文件,创建configuration,然后创建在创建DefaultSqlSessionFactory时将Configuration传了进去

获取sqlSession

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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);
// 获取执行器
final Executor executor = configuration.newExecutor(tx, execType);
// 构建sqlSession
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();
}
}

mapper代理的创建

sqlSession中的getMapper,是通过configuration中的registerMapper容器获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>)
//前文中configuration中的bindMapperForNamespace,parser方法链中将类信息放入到了knownMapper.
knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
// jdk动态代理创建对象
// 实际上是代理方法,之前看spring-mybatis这块代码已经看过了.
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
public class MapperProxyFactory<T> {

private final Class<T> mapperInterface;
private final Map<Method, MapperMethodInvoker> methodCache = new ConcurrentHashMap<>();

public MapperProxyFactory(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}

public Class<T> getMapperInterface() {
return mapperInterface;
}

public Map<Method, MapperMethodInvoker> getMethodCache() {
return methodCache;
}

@SuppressWarnings("unchecked")
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}

public T newInstance(SqlSession sqlSession) {
// method cache是一个concurrentHashmap的MapperMethodInvoker缓存
// 后续的invoke方法也会加入这个缓存
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}

}

public class MapperProxy<T> implements InvocationHandler, Serializable {
....
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {
// object的方法,直接执行,mapper是接口
return method.invoke(this, args);
} else {
// 传入method invoker缓存
// 最终必然会通过sqlSession去执行sql,因此不出意外也会传入sqlSession.
return cachedInvoker(method).invoke(proxy, method, args, sqlSession);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}

private MapperMethodInvoker cachedInvoker(Method method) throws Throwable {
try {
// A workaround for https://bugs.openjdk.java.net/browse/JDK-8161372
// It should be removed once the fix is backported to Java 8 or
// MyBatis drops Java 8 support. See gh-1929
// 如果缓存有,直接返回
MapperMethodInvoker invoker = methodCache.get(method);
if (invoker != null) {
return invoker;
}

return methodCache.computeIfAbsent(method, m -> {
// 默认方法,jdk8与9不太一样,返回个DefaultMethodInovker即可
if (m.isDefault()) {
try {
if (privateLookupInMethod == null) {
return new DefaultMethodInvoker(getMethodHandleJava8(method));
} else {
return new DefaultMethodInvoker(getMethodHandleJava9(method));
}
} catch (IllegalAccessException | InstantiationException | InvocationTargetException
| NoSuchMethodException e) {
throw new RuntimeException(e);
}
} else {
// 非默认方法
// 创建PlainMethodInvoker
return new PlainMethodInvoker(new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
}
});
} catch (RuntimeException re) {
Throwable cause = re.getCause();
throw cause == null ? re : cause;
}
}
....
interface MapperMethodInvoker {
Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable;
}
// 内部类
private static class PlainMethodInvoker implements MapperMethodInvoker {
private final MapperMethod mapperMethod;

public PlainMethodInvoker(MapperMethod mapperMethod) {
super();
this.mapperMethod = mapperMethod;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {
return mapperMethod.execute(sqlSession, args);
}
}
}



//MapperMethod#execute方法
public class MapperMethod {
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);
// rowCountResult将根据返回类型来设置result,会做相应的类型转换
// Integer,Long,boolean类型则根据rowCount>0,void返回null
// 其他类型抛出异常
result = rowCountResult(sqlSession.insert(command.getName(), param));
break;
}
case UPDATE: {
// 同insert
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.update(command.getName(), param));
break;
}
case DELETE: {
// 同insert
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.delete(command.getName(), param));
break;
}
case SELECT:

if (method.returnsVoid() && method.hasResultHandler()) {
// 返回void,且入参设置了ResultHandler
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()) {
// 返回位cursor
result = executeForCursor(sqlSession, args);
} else {
// 返回单个bean或optional
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());
}
// 返回类型为基础类型,不包含void
// 但是结果为null
//
// isPrimitive,Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE,
// Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE
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;
}
}

list查询

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
private <E> Object executeForMany(SqlSession sqlSession, Object[] args) {
List<E> result;
// 转换参数
Object param = method.convertArgsToSqlCommandParam(args);
// 如果如参包含RowBounds对象,分页
if (method.hasRowBounds()) {
RowBounds rowBounds = method.extractRowBounds(args);
result = sqlSession.selectList(command.getName(), param, rowBounds);
} else {
// 非分页
result = sqlSession.selectList(command.getName(), param);
}
// issue #510 Collections & arrays support
if (!method.getReturnType().isAssignableFrom(result.getClass())) {

if (method.getReturnType().isArray()) {
// 如果返回数组
return convertToArray(result);
} else {
// 其他的集合对象
// 这段写法着实有意思....处理了返回类型的泛型
// 源码涉及好几个类,不粘贴了,大体流程如下
// 通过DefaultObjectFactory创建了集合类型,object
// 然后创建MetaObject类型,将DefaultObjectFactory创建的object包装成ObjectWrapper
// objectWrapper实现类有CollectionWrapper,BeanWrapper等
// 然后再通过包装类来进行add,set等操作将result复制给ObjectFacotry创建的object
// 比较优雅的处理了所有的类型,也避免了泛型强转之类的...值得学习
return convertToDeclaredCollection(sqlSession.getConfiguration(), result);
}
}
return result;
}
// executeForMap直接使用sqlSession

sqlSession

sqlSession的实现类,选择DefaultSqlSession查看源码(源码不多,300多行,具体执行主要靠Executor).

属性

1
2
3
4
5
6
7
8
9
private final Configuration configuration;
// 执行器
private final Executor executor;
// 自动提交
private final boolean autoCommit;

private boolean dirty;

private List<Cursor<?>> cursorList;

executor查询

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
// 从configuration中的mappedStatements获取MappedStatement
MappedStatement ms = configuration.getMappedStatement(statement);
// 执行器执行 ,传入空的ResultHandler
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();
}
}

进入BaseExecutor#query方法.debug的时候注意默认会走CacheExecutor,需要配置关闭缓存,关闭之后创建的Executor为SimpleExecutor.

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

@Override
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
// 封装下sql及其参数,同时会将动态sql,即${}替换(改为静态)
BoundSql boundSql = ms.getBoundSql(parameter);
// 缓存用的key
CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
// 涉及一堆缓存,先略过不管了.分支太多.
// 通过queryFromDatabase方法进入doQuery方法
return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}

@Override
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();
// statemetHandler对象
// 根据stateMentType选择不同的handler.
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);
// 获取statement
stmt = handler.prepare(connection, transaction.getTimeout());
// 设置handler参数
// 调用handler的setParameters方法
// 最后调用的就是DefaultParameterHandler#setParameters
// 具体源码不粘贴了,大体功能及流程
// 主要功能就是处理入参,将paramter的参数放到sql的?里.
// 类型处理器(typeHandler去处理参数)
// 指定了jdbc但是入参为空的处理等.
handler.parameterize(stmt);
return stmt;
}


result映射

PreparedStatementHandler#query

1
2
3
4
5
6
7
8
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
// 直接执行
ps.execute();
// 结果映射
return resultSetHandler.handleResultSets(ps);
}

DeafultResultHandler#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
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
@Override
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;
// 获取第一个ResultSet
ResultSetWrapper rsw = getFirstResultSet(stmt);
// 获取当前语句所有的ResultMap
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
// resultMap总数
int resultMapCount = resultMaps.size();
// 非空校验
validateResultMapsCount(rsw, resultMapCount);
// 根据结果集和ResultMap一一映射.
while (rsw != null && resultMapCount > resultSetCount) {
ResultMap resultMap = resultMaps.get(resultSetCount);
// 映射,并将生成的对象放入multipleResults
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);
}
private List<Object> collapseSingleResultList(List<Object> multipleResults) {
return multipleResults.size() == 1 ? (List<Object>) multipleResults.get(0) : multipleResults;
}


public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
if (resultMap.hasNestedResultMaps()) {
ensureNoRowBounds();
checkResultHandler();
handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
} else {
handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
}
}
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
throws SQLException {
DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
ResultSet resultSet = rsw.getResultSet();
// 万恶的内存= =分页
skipRows(resultSet, rowBounds);
while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);
// 值放进hashMap里,返回bean
Object rowValue = getRowValue(rsw, discriminatedResultMap, null);
// 加入resultHandler.resultList中
storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
}
}


private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
final ResultLoaderMap lazyLoader = new ResultLoaderMap();
// 使用ObjectFacotry创建出bean.类型是ResultMap.getType()
Object rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);
if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
final MetaObject metaObject = configuration.newMetaObject(rowValue);
boolean foundValues = this.useConstructorMappings;
if (shouldApplyAutomaticMappings(resultMap, false)) {
// 映射
foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
}
foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;
foundValues = lazyLoader.size() > 0 || foundValues;
rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
}
return rowValue;
}

private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
List<UnMappedColumnAutoMapping> autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);
boolean foundValues = false;
if (!autoMapping.isEmpty()) {
for (UnMappedColumnAutoMapping mapping : autoMapping) {
final Object value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column);
if (value != null) {
foundValues = true;
}
if (value != null || (configuration.isCallSettersOnNulls() && !mapping.primitive)) {
// gcode issue #377, call setter on nulls (value is not 'found')
metaObject.setValue(mapping.property, value);
}
}
}
return foundValues;
}

可以自己传ResultHandler,但是返回结果需要改为void.

mybatis的一些用法
es mapping
  1. 1. 目录
  2. 2. 前言
  3. 3. sqlSessionFactory的创建
  4. 4. 获取sqlSession
  5. 5. mapper代理的创建
    1. 5.1. list查询
  6. 6. sqlSession
    1. 6.1. 属性
    2. 6.2. executor查询
      1. 6.2.1. result映射
© 2023 haoxp
Hexo theme