mybatis 所有操作都会通过 sqlSession 来完成
public interface SqlSession extends Closeable {
<T> T selectOne(String var1);
<T> T selectOne(String var1, Object var2);
<E> List<E> selectList(String var1);
<E> List<E> selectList(String var1, Object var2);
<E> List<E> selectList(String var1, Object var2, RowBounds var3);
<K, V> Map<K, V> selectMap(String var1, String var2);
<K, V> Map<K, V> selectMap(String var1, Object var2, String var3);
<K, V> Map<K, V> selectMap(String var1, Object var2, String var3, RowBounds var4);
<T> Cursor<T> selectCursor(String var1);
<T> Cursor<T> selectCursor(String var1, Object var2);
<T> Cursor<T> selectCursor(String var1, Object var2, RowBounds var3);
void select(String var1, Object var2, ResultHandler var3);
void select(String var1, ResultHandler var2);
void select(String var1, Object var2, RowBounds var3, ResultHandler var4);
int insert(String var1);
int insert(String var1, Object var2);
int update(String var1);
int update(String var1, Object var2);
int delete(String var1);
int delete(String var1, Object var2);
void commit();
void commit(boolean var1);
void rollback();
void rollback(boolean var1);
List<BatchResult> flushStatements();
void close();
void clearCache();
Configuration getConfiguration();
<T> T getMapper(Class<T> var1);
Connection getConnection();
}
-
获取 SqlSessionFactory(SqlSessionFactory 初始化)
org.apache.ibatis.session.SqlSessionFactoryBuilder#build(java.io.InputStream)
,返回的是 DefaultSqlSessionFactory- 里面再调用 parse 方法解析配置文件,构建一个 Configuration 对象(包括全局配置文件和mapper.xml映射文件)
- mapper 映射文件中的每个增删改查都会封装成一个 MappedStatement 对象,然后放到 mappedStatements里。mappedStatements 是一个 map,key 是 id,value 是 MappedStatement(configruation.mappedStatements)
- 所有的 mapper 接口文件解析后的信息都放在 configruation.mapperRegistry 里。 mapperRegistry 里面还有个 knownMappers,这是一个 map 放着每个 mapper 接口和其代理对象的工厂对象,后面会根据这个创建 mapper 接口的代理对象(configruation.mapperRegistry.knownMappers)
-
获取 SqlSession,里面包含了 Executor 和 Configuration
-
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSession()
,返回的是 DefaultSqlSession -
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; DefaultSqlSession var8; try { Environment environment = this.configuration.getEnvironment(); TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment); tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); // 这个是关键,所有数据库操作都是 Executor 完成的 Executor executor = this.configuration.newExecutor(tx, execType); var8 = new DefaultSqlSession(this.configuration, executor, autoCommit); } catch (Exception var12) { Exception e = var12; this.closeTransaction(tx); throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } return var8; }
-
org.apache.ibatis.session.Configuration#newExecutor(org.apache.ibatis.transaction.Transaction, org.apache.ibatis.session.ExecutorType)
public Executor newExecutor(Transaction transaction, ExecutorType executorType) { executorType = executorType == null ? this.defaultExecutorType : executorType; executorType = executorType == null ? ExecutorType.SIMPLE : executorType; // 根据条件创建不同的 executor,默认是 Simple Object 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); } // 如果开启了缓存,再把 executor 包装一下,最终都是通过包装后的 executor 执行 db 操作 if (this.cacheEnabled) { executor = new CachingExecutor((Executor)executor); } // 如果有插件,再包装一下,同上最终使用还是还是包装后的 executor Executor executor = (Executor)this.interceptorChain.pluginAll(executor); return executor; }
-
-
getMapper 获取代理对象
-
org.apache.ibatis.session.defaults.DefaultSqlSession#getMapper
public <T> T getMapper(Class<T> type) { return this.configuration.getMapper(type, this); }
-
org.apache.ibatis.session.Configuration#getMapper
public <T> T getMapper(Class<T> type, SqlSession sqlSession) { // 刚才说了初始化 SqlSessionFactoryBuilder 的时候设置了 configruation.mapperRegistry 并维护了 knownMappers // 这里 getMapper 的就是调用 MapperRegistry 的方法 return this.mapperRegistry.getMapper(type, sqlSession); }
-
org.apache.ibatis.binding.MapperRegistry#getMapper
public <T> T getMapper(Class<T> type, SqlSession sqlSession) { MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type); if (mapperProxyFactory == null) { throw new BindingException("Type " + type + " is not known to the MapperRegistry."); } else { try { // 调用 newInstance 创建对象,这里就不继续点了 // 后面步骤也很清晰:通过JDK动态代理创建对象;代理对象里面含有 sqlSession(sqlSession 里面有 executor) return mapperProxyFactory.newInstance(sqlSession); } catch (Exception var5) { Exception e = var5; throw new BindingException("Error getting mapper instance. Cause: " + e, e); } } }
-
-
根据 Mapper 获取到了对象,就该调用里面的方法了,比如 selectById,现根据方法名判断是否是 Object 的方法,比如 toString、equlas 等,不是 Object 的方法,就把当前方法包装成一个 MapperMethod,传入 SqlSession 来执行这个方法
mapperMethod.execute(this.sqlSession, args)
public Object execute(SqlSession sqlSession, Object[] args) { Object result; Object param; // command 有两个属性 // 属性1 String name:mapper xml 的 id,也就是 MappedStatement 的 id,也就是 mapper 接口的方法全限定名 // 属性2 SqlCommandType type:语句的类型,增删改成哪一种,是一个枚举 switch (this.command.getType()) { case INSERT: param = this.method.convertArgsToSqlCommandParam(args); result = this.rowCountResult(sqlSession.insert(this.command.getName(), param)); break; case UPDATE: param = this.method.convertArgsToSqlCommandParam(args); result = this.rowCountResult(sqlSession.update(this.command.getName(), param)); break; case DELETE: param = this.method.convertArgsToSqlCommandParam(args); result = this.rowCountResult(sqlSession.delete(this.command.getName(), param)); break; case SELECT: if (this.method.returnsVoid() && this.method.hasResultHandler()) { // 没有返回值怎么执行 this.executeWithResultHandler(sqlSession, args); result = null; } else if (this.method.returnsMany()) { // 返回多个怎么执行 result = this.executeForMany(sqlSession, args); } else if (this.method.returnsMap()) { // 返回 map 怎么执行 result = this.executeForMap(sqlSession, args); } else if (this.method.returnsCursor()) { // 返回游标怎么执行 result = this.executeForCursor(sqlSession, args); } else { // 处理参数,如果只有一个参数直接返回,如果是多个就返回一个 map,param 里面都是参数信息 param = this.method.convertArgsToSqlCommandParam(args); // 参数参数 sqlSession 方法并调用(底层还是会调用 sqlSession.selectList,返回第一个) result = sqlSession.selectOne(this.command.getName(), param); if (this.method.returnsOptional() && (result == null || !this.method.getReturnType().equals(result.getClass()))) { result = Optional.ofNullable(result); } } break; case FLUSH: result = sqlSession.flushStatements(); break; default: throw new BindingException("Unknown execution method for: " + this.command.getName()); } if (result == null && this.method.getReturnType().isPrimitive() && !this.method.returnsVoid()) { throw new BindingException("Mapper method '" + this.command.getName() + " attempted to return null from a method with a primitive return type (" + this.method.getReturnType() + ")."); } else { return result; } }
-
org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { List var5; try { // 先拿到 MappedStatement,也就是 xml 定义的东西 MappedStatement ms = this.configuration.getMappedStatement(statement); // MappedStatement 传给 executor 的 query 方法。this.wrapCollection(parameter):再次包装参数,集合,map,还是单个参数 var5 = this.executor.query(ms, this.wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); } catch (Exception var9) { Exception e = var9; throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } return var5; }
-
org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
这个 query 做了什么public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { // 这个里面是所有 sql 信息的对象,参数是什么,值是什么,语句是什么(boundSql.getSql能拿到真正执行的sql,这里调试比较有用) BoundSql boundSql = ms.getBoundSql(parameter); // 构建一个缓存 key,下面查询的时候用这个缓存 key 去查,有就返回,没有就查库 CacheKey key = this.createCacheKey(ms, parameter, rowBounds, boundSql); // 再调用 query 方法 return this.query(ms, parameter, rowBounds, resultHandler, key, boundSql); }
-
org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.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()); if (this.closed) { throw new ExecutorException("Executor was closed."); } else { if (this.queryStack == 0 && ms.isFlushCacheRequired()) { this.clearLocalCache(); } List list; try { ++this.queryStack; // 先到缓存中拿 list = resultHandler == null ? (List)this.localCache.getObject(key) : null; if (list != null) { this.handleLocallyCachedOutputParameters(ms, key, parameter, boundSql); } else { // 如果缓存中没有,就查数据库 list = this.queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql); } } finally { --this.queryStack; } if (this.queryStack == 0) { Iterator var8 = this.deferredLoads.iterator(); while(var8.hasNext()) { DeferredLoad deferredLoad = (DeferredLoad)var8.next(); deferredLoad.load(); } this.deferredLoads.clear(); if (this.configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) { this.clearLocalCache(); } } return list; } }
-
queryFromDatabase 方法又调用了 doQuery 方法
org.apache.ibatis.executor.SimpleExecutor#doQuery
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { // java.sql 这个包下面的,再接近 jdbc 了 Statement stmt = null; List var9; try { Configuration configuration = ms.getConfiguration(); // 先创建 Statement 处理器 StatementHandler handler = configuration.newStatementHandler(this.wrapper, ms, parameter, rowBounds, resultHandler, boundSql); // 根据 Statement 处理器拿到 Statement stmt = this.prepareStatement(handler, ms.getStatementLog()); // 再把 Statement 传给 query var9 = handler.query(stmt, resultHandler); } finally { this.closeStatement(stmt); } return var9; }
-
然后参数处理,执行查询,结果映射,关闭连接等