Files
logseq/pages/Mybatis源码.md

136 lines
6.2 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
- Mybatis初始化过程
- 通过InputStream来获取配置文件
- ClassLoaderWarpper中的getResourceAsStream可以根据配置的resoutce来获取到配置文件的输入六
- 使用ClassLoader是因为类加载器可具有读取外部资源的能力
- ![image.png](../assets/image_1714227673997_0.png)
- 读取到配置文件后传入SqlSessionFactoryBuilder内部使用XMLConfigBuilder的parse方法读取配置并set到一个configuration变量中返回一个Configuration对象
- ![image.png](../assets/image_1714228148958_0.png)
- 使用build方法创建一个DefaultSqlSessionFactory并返回
- 在其中会创建一个SqlSession其中会创建事务工厂之类的
- ![image.png](../assets/image_1714228719703_0.png)
- 将mapper类传入session通过session.getMapper方法在mapperRegistry获取到一个该mapper类的代理类MapperProxy
- 执行时会执行该代理类的invoke方法
- ![image.png](../assets/image_1714230626595_0.png)
- 触发mapperMethod的execute方法
- ```java
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*:
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);
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方法查询list会执行executeForMany方法
- ```java
private <E> Object executeForMany(SqlSession sqlSession, Object[] args) {
List<E> result;
Object param = method.convertArgsToSqlCommandParam(args);
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 {
return convertToDeclaredCollection(sqlSession.getConfiguration(), result);
}
}
return result;
}
```
- selectList获取MappedStatement再执行executor.query方法
- ```java
@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
BoundSql boundSql = ms.getBoundSql(parameterObject);
CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
```
- BoundSql为去掉ifwhere标签的sql语句Cachekey为缓存key
- 查询时先从缓存获取获取不到或list为null就执行delegate.query方法查询
- 检查executor是否被关闭是否清理缓存
- 通过queryFromDatabase先在缓存中放一个占位符接着使用doQuery方法查询然后把缓存中的占位符换成真正的结果
- ```java
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;
}
```
- 执行doQuery方法为BatchExecutor类的方法
- ```java
public <E> List<E> doQuery(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)
throws SQLException {
Statement stmt = null;
try {
flushStatements();
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameterObject, rowBounds, resultHandler, boundSql);
Connection connection = getConnection(ms.getStatementLog());
stmt = handler.prepare(connection, transaction.getTimeout());
handler.parameterize(stmt);
return handler.query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}
```
- 通过Statement执行静态语句获取结果
- 执行的是PrepareStatementHandler.query方法获取结果后交给ResultSetHandler处理通过resultMap将值赋值给对象