initial commit
This commit is contained in:
136
pages/Mybatis源码.md
Normal file
136
pages/Mybatis源码.md
Normal file
@@ -0,0 +1,136 @@
|
||||
- Mybatis初始化过程
|
||||
- 通过InputStream来获取配置文件
|
||||
- ClassLoaderWarpper中的getResourceAsStream可以根据配置的resoutce来获取到配置文件的输入六
|
||||
- 使用ClassLoader是因为类加载器可具有读取外部资源的能力
|
||||
- 
|
||||
- 读取到配置文件后传入SqlSessionFactoryBuilder,内部使用XMLConfigBuilder的parse方法读取配置并set到一个configuration变量中返回一个Configuration对象
|
||||
- 
|
||||
- 使用build方法创建一个DefaultSqlSessionFactory并返回
|
||||
- 在其中会创建一个SqlSession,其中会创建事务工厂之类的
|
||||
- 
|
||||
- 将mapper类传入session,通过session.getMapper方法在mapperRegistry获取到一个该mapper类的代理类MapperProxy
|
||||
- 执行时会执行该代理类的invoke方法
|
||||
- 
|
||||
- 触发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为去掉if,where标签的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将值赋值给对象
|
||||
Reference in New Issue
Block a user