我们把mybatis的架构分为三层
// 将我们的核心配置文件解析成一个字节输入流
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 初始化工作开始
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSessionFactoryBuilder().build(resourceAsStream)做了哪些事?
public SqlSessionFactory build(InputStream inputStream) {
//调用了重载方法
return build(inputStream, null, null);
}
build(inputStream, null, null)
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
// 创建 XMLConfigBuilder, XMLConfigBuilder是专门解析mybatis的核心配置文件的类
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
// 在一次调用build重载方法 parser.parse()返回的是configuration对象
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
parser.parse()
public Configuration parse() {
// 判断是否解析过
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
// 设置为已解析
parsed = true;
///parser是,是核心配置文件中的父标签
// 使用XPathParser解析器对象,读取核心配置文件中 configuration 节点下的节点数据解析
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
parseConfiguration(parser.evalNode("/configuration"));
这个方法就是对configuration标签下的各种节点的解析
private void parseConfiguration(XNode root) {
try {
// 解析 标签
propertiesElement(root.evalNode("properties"));
// 解析 标签
Properties settings = settingsAsProperties(root.evalNode("settings"));
// 加载自定义的 VFS 实现类
loadCustomVfs(settings);
// 解析 标签
typeAliasesElement(root.evalNode("typeAliases"));
// 解析 标签
pluginElement(root.evalNode("plugins"));
// 解析 标签
objectFactoryElement(root.evalNode("objectFactory"));
// 解析 标签
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
// 解析 标签
reflectorFactoryElement(root.evalNode("reflectorFactory"));
// 赋值 到 Configuration 属性
settingsElement(settings);
// 解析 标签
environmentsElement(root.evalNode("environments"));
// 解析 标签
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
// 解析 标签
typeHandlerElement(root.evalNode("typeHandlers"));
// 解析 标签
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
解析之后parser.parse()最终反回了一个configuration对象 并交给了build重载方法
build(parser.parse())
SqlSessionFactory在这里被创建成功
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
SqlSessionFactoryBuilder().build(resourceAsStream)做了哪些事? 1,创建 XMLConfigBuilder解析核心配置文件中的所有内容并返回一个configuration
2,将这个configuration赋值给DefaultSqlSessionFactory中的Configuration对象属性
3,创建SqlSessionFactory实例
// 创建一个sqlSession会话对象,用来实现与数据库的交互
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSessionFactory.openSession();做了什么
// 创建一个sqlSession会话对象,用来实现与数据库的交互
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSessionFactory.openSession();
public SqlSession openSession() {
//第一个参数getDefaultExecutorType()返回的是执行器类型这里类型为SIMPLE
//第二个参数是我们的事务隔离级别,这里赋值为null
//第三个参数就是是否自动提交事务,我们这里默认不提交
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
// 获得 Environment 对象 运行环境对象
final Environment environment = configuration.getEnvironment();
// 创建 Transaction 对象 事务对象
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
// 创建 Executor 对象 执行器对象在此被创建
final Executor executor = configuration.newExecutor(tx, execType);
// 返回一个sqlSession
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(tx);
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
configuration.newExecutor(tx, execType);
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
// 获得执行器类型 我们已经设定为SIMPLE
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
// 创建对应实现的 Executor 对象
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
// 如果开启缓存,创建 CachingExecutor 对象,进行包装
if (cacheEnabled) {
executor = new CachingExecutor(executor);
}
// 应用插件 返回代理对象
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
sqlSessionFactory.openSession();做了什么
1、生成了类型为SIMPLE的执行器代理对象
2、创建了sqlSession,默认不自动提交事务
// 使用JDK动态代理对mapper接口产生代理对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
sqlSession.getMapper(UserMapper.class);做了什么
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
// 获得 MapperProxyFactory 对象
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);
}
}
mapperProxyFactory.newInstance(sqlSession);
public T newInstance(SqlSession sqlSession) {
// 创建了JDK动态代理的invocationHandler接口的实现类mapperProxy
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
// 调用了重载方法返回代理对象
return newInstance(mapperProxy);
}
sqlSession.getMapper(UserMapper.class);做了什么
使用MapperProxyFactory根据jdk动态代理上产了mapper代理对象
//代理对象调用接口中的任意方法,执行的都是动态代理默认实现类MapperProxy的invoke方法
List<User> users = mapper.findAll();
调用查询方法时都做了什么
public 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);
// MapperMethod最终调用了执行的方法并返回执行结果
return mapperMethod.execute(sqlSession, args);
}
mapperMethod.execute(sqlSession, args)
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
//判断mapper中的方法类型 我们是select
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:
// 无返回,并且有 ResultHandler 方法参数,则将查询的结果,提交给 ResultHandler 进行处理
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null;
// 执行查询,返回列表
} else if (method.returnsMany()) {
result = executeForMany(sqlSession, args);
// 执行查询,返回 Map
} else if (method.returnsMap()) {
result = executeForMap(sqlSession, args);
// 执行查询,返回 Cursor
} 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());
}
// 返回结果为 null ,并且返回类型为基本类型,则抛出 BindingException 异常
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;
}
executeForMany(sqlSession, args);
private <E> Object executeForMany(SqlSession sqlSession, Object[] args) {
List<E> result;
// 转换参数
Object param = method.convertArgsToSqlCommandParam(args);
// 执行 SELECT 操作
if (method.hasRowBounds()) {
RowBounds rowBounds = method.extractRowBounds(args);
result = sqlSession.selectList(command.getName(), param, rowBounds);
} else {
result = sqlSession.selectList(command.getName(), param);
}
// 封装 Array 或 Collection 结果
if (!method.getReturnType().isAssignableFrom(result.getClass())) {
if (method.getReturnType().isArray()) {
// 情况一,Array
return convertToArray(result);
} else {
return convertToDeclaredCollection(sqlSession.getConfiguration(), result); // 情况二,Collection
}
}
// 直接返回的结果
return result;
}
sqlSession.selectList(command.getName(), param);
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
// 获得 MappedStatement 对象
MappedStatement ms = configuration.getMappedStatement(statement);
// 执行查询
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();
}
}
executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
//根据传入的参数动态获得SQL语句,最后返回BoundSql
BoundSql boundSql = ms.getBoundSql(parameter);
//为本次查询创建缓存的Key
CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
// 调用重载方法查询
return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
// 判断sqlSession是否关闭
if (closed) {
throw new ExecutorException("Executor was closed.");
}
// 清空本地缓存
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
}
List<E> list;
try {
queryStack++;
// 从一级缓存中,获取查询结果
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
// 获取到,则进行处理返回
if (list != null) {
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
// 获得不到,则从数据库中查询
} else {
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
// queryStack - 1
queryStack--;
}
if (queryStack == 0) {
// 执行延迟加载
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
// 清空 deferredLoads
deferredLoads.clear();
// 如果缓存级别是 LocalCacheScope.STATEMENT ,则进行清理
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
// issue #482
clearLocalCache();
}
}
return list;
}
queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql)
// 从数据库中读取操作
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(ms, parameter, rowBounds, resultHandler, boundSql);
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
// 拿到configuration对象
Configuration configuration = ms.getConfiguration();
// 传入参数创建StatementHanlder对象来执行查询
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
// 参数?占位符处理
stmt = prepareStatement(handler, ms.getStatementLog());
// 调用StatementHandler.query方法进行读操作 并返回查询结果
return handler.query(stmt, resultHandler);
} finally {
// 关闭 StatementHandler 对象
closeStatement(stmt);
}
}
prepareStatement(handler, ms.getStatementLog());
// 初始化 StatementHandler 对象
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
// 获得 Connection 对象
Connection connection = getConnection(statementLog);
// 创建 Statement 或 PrepareStatement 对象
stmt = handler.prepare(connection, transaction.getTimeout());
// 参数处理
handler.parameterize(stmt);
return stmt;
}
handler.parameterize(stmt);
public void setParameters(PreparedStatement ps) {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
// 遍历 ParameterMapping 数组
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings != null) {
for (int i = 0; i < parameterMappings.size(); i++) {
// 获得 ParameterMapping 对象
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
// 获得值
Object value;
String propertyName = parameterMapping.getProperty();
if (boundSql.hasAdditionalParameter(propertyName)) {
// issue #448 ask first for additional params
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
// 获得 typeHandler、jdbcType 属性
TypeHandler typeHandler = parameterMapping.getTypeHandler();
JdbcType jdbcType = parameterMapping.getJdbcType();
if (value == null && jdbcType == null) {
jdbcType = configuration.getJdbcTypeForNull();
}
// 设置 ? 占位符的参数
try {
typeHandler.setParameter(ps, i + 1, value, jdbcType);
} catch (TypeException | SQLException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
}
}
}
}
}
handler.query(stmt, resultHandler);
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
// 执行查询
ps.execute();
// 处理返回结果
return resultSetHandler.handleResultSets(ps);
}
resultSetHandler.handleResultSets(ps);
public List<Object> handleResultSets(Statement stmt) throws SQLException {
ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
// 多 ResultSet 的结果集合
final List<Object> multipleResults = new ArrayList<>();
int resultSetCount = 0;
// 获得首个 ResultSet 对象,并封装成 ResultSetWrapper 对象
ResultSetWrapper rsw = getFirstResultSet(stmt);
// 获得 ResultMap 数组
// 在不考虑存储过程的多 ResultSet 的情况,普通的查询,实际就一个 ResultSet ,也就是说,resultMaps 就一个元素。
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
int resultMapCount = resultMaps.size();
validateResultMapsCount(rsw, resultMapCount); // 校验
while (rsw != null && resultMapCount > resultSetCount) {
// 获得 ResultMap 对象
ResultMap resultMap = resultMaps.get(resultSetCount);
// 处理 ResultSet ,将结果添加到 multipleResults 中
handleResultSet(rsw, resultMap, multipleResults, null);
// 获得下一个 ResultSet 对象,并封装成 ResultSetWrapper 对象
rsw = getNextResultSet(stmt);
// 清理
cleanUpAfterHandlingResultSet();
// resultSetCount ++
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++;
}
}
// 如果是 multipleResults 单元素,则取首元素返回结果
return collapseSingleResultList(multipleResults);
}
调用查询方法时都做了什么
1、执行的动态代理默认实现类MapperProxy的invoke方法
2、invoke判断方法类型是查询方法
3、执行sqlSession中的select方法
4、executor执行查询方法
5、动态解析sql,创建查询的缓存key,
6、executor将查询操作交给statementHandler
7、statementhandler处理参数后查询将查询结果交给resultSetHandler
8、resultSetHandler处理结果后返回List
1、通过mybaits流程分析梳理对近期学习内容进行了贯穿
2、更深层次的理解了mybatis主要构件
3、查询的方法具体怎样实现的sql查询以及结果集的封装
还是需要自己查看源代码学习,层层嵌套,博主整理能力有限