mybatis工作流程
基本使用方法
// 获取mybatis配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
// 新建SqlSessionFactory创建器
SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
// 通过SqlSessionFactoryBuilder 创建SqlSessionFactory ,并传入配置文件流
SqlSessionFactory ssf= sfb.build(is);
// 通过工厂获取sqlSession
SqlSession sqlSession = ssf.openSession();
// sqlSession获取mapper
DatasourceMapper mapper = sqlSession.getMapper(xxxMapper.class);
// 在通过mapper调用相关方法
String s = mapper.getXxx();
System.out.println(s);
解析
SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
SqlSessionFactory ssf= sfb.build(is);
public SqlSessionFactory build(InputStream inputStream) {
return build(inputStream, null, null);
}
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
// xml解析器
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
// parser.parse() 获取配置文件信息,并封装成Configuration对象
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
reader.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
// DefaultSqlSessionFactory 是 SqlSessionFactory的一个实现类
public DefaultSqlSessionFactory(Configuration configuration) {
this.configuration = configuration;
}
SqlSession sqlSession = ssf.openSession();
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
/**
* @Param execType 执行器 默认SIMPLE (SIMPLE, REUSE, BATCH)
* @Param level 事务等级
* @Param autoCommit 自动提交事务 false
*/
private SqlSession openSessionFromDataSource(ExecutorType execType,
TransactionIsolationLevel level,
boolean autoCommit) {
Transaction tx = null;
try {
// 通过配置文件中的<Encironment>标签中的数据,获取数据库配置信息。
final Environment environment = configuration.getEnvironment();
// 通过environment中创建事务工厂
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
// 通过事务工厂创建事务 【数据源,数据库隔离等级,是否自动提交】
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
// 创建执行器 相当于JDBC中的statement
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();
}
}
DatasourceMapper mapper = sqlSession.getMapper(xxxMapper.class);
<T> T getMapper(Class<T> type);
@Override
public <T> T getMapper(Class<T> type) {
return getConfiguration().getMapper(type, this);
}
// 实际上就是通过 mapperRegistry 帮我们存储了所有的mapper对象,mapperRegistry 底层封装了HashMap。
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
// private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<>();
//
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
// class MapperProxyFactory<T>
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
// 类下的成员变量
// private final Class<T> mapperInterface;
// private final Map<Method, MapperMethodInvoker> methodCache = new ConcurrentHashMap<>();
protected T newInstance(MapperProxy<T> mapperProxy) {
// JDK 动态代理
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
String s = mapper.getXxx();
其实是通过调用 MapperProxy
的invoke方法。
public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {
return mapperMethod.execute(sqlSession, args);
}
execute
方法
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;
}
查询流程
public <E> List<E> query(MappedStatement ms, Object parameterObject,
RowBounds rowBounds, ResultHandler resultHandler,
CacheKey key, BoundSql boundSql)
throws SQLException {
// 从二级缓存中获取
Cache cache = ms.getCache();
// 如果有 则从缓存中取
if (cache != null) {
flushCacheIfRequired(ms);
if (ms.isUseCache() && resultHandler == null) {
ensureNoOutParams(ms, boundSql);
@SuppressWarnings("unchecked")
List<E> list = (List<E>) tcm.getObject(cache, key);
if (list == null) {
list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
tcm.putObject(cache, key, list); // issue #578 and #116
}
return list;
}
}
// 查询一级缓存
return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
总结
- 获取配置文件,转成流。(
InputStream is = Resources.getResourceAsStream("mybatis-config.xml")
) - 解析流得到 configuration
- 通过SqlSessionFactoryBuilder 创建 SqlSessionFactory
- 通过SqlSessionFactory 获取 SqlSession
- 使用SqlSession 执行SQL (MapperProxy)
- CachingExecutor 判断是否开启二级缓存
- 如果没有开启二级缓存,则调用 BaseExecutor 调用一级缓存
- 如果一级缓存有,则返回,否则,请往下
- RountingStatementHandle 选中sql执行方式
- 选则预编译方式,PreparedStatementHandle
- 最后,通过DefaultResultSetHandle返回结果。
参考:https://blog.csdn.net/qq_38270106/article/details/93398694