Mybatis日记
SqlSession build:
ExecutorType :SIMPLE ,REUSE, BATCH,
SIMPLE 为默认执行器;
REUSE 为可重用执行器,重用Statement,执行器会缓存同一个sql Statement,不重复创建。
BTACH 为批量更新执行器。会重用重用预处理语句,该模式下insert,update,delete的返回值将无意义,也可通过设置修改。
生命周期及作用域:
SqlSessionFactoryBuilder: 方法作用域,该类用于创建SQLSessionFactory,一旦创建完后,就可以丢弃。
SQLSessionFactory:应用作用域,创建后可在应用运行期间一直存在。不需要重复创建。适用于单例模式。
SqlSession:请求或方法作用域,该类的实例是线程不安全的,因此用完之后即销毁;
SQL执行流程:
这里通过SQLSession中的selectList("statementId")方法查看主要的方法栈:
其中包含了mybatis缓存处理、Intercepter(拦截器)的处理等操作。最终执行jdbc的Sql操作是由StatementHandler来完成。mybatis中sql mapper会转化为BoundSql,BoundSql包含了可执行sql,参数、参数类型等信息。
StatementType : STATEMENT,PREPARED,CALLABLE
STATEMENT: 直接执行sql,非预编译; 处理类:SimpleStatementHandler
PREPARED:预编译处理;处理类:PreparedStatementHandler
CALLABLE:执行存储过程;处理类:CallableStatementHandler
StatementHandler:该接口有BaseStatementHandler和RoutingStatementHandler两个实现类。BaseStatementHandler 存在3个子类,分别对应StatementType的三种类型;BaseStatementHandler 中包含了ResultSetHandler和ParameterHandler
StatementHandler执行sql后,会把结果交给ResultHandler来把查询结果转化为java对应的对象集合。handleResultSets()
1 //处理ResultSet结果集 2 @Override 3 public List<Object> handleResultSets(Statement stmt) throws SQLException { 4 ErrorContext.instance().activity("handling results").object(mappedStatement.getId()); 5 //用于存放查询的结果对象结合,多个ResultSet集合;每个Object对应一个ResultSet,每个Object对应的是一个List<Object>对象 6 //一般的查询只存在一个ResultSet,执行存储过程时会有多个ResultSet的情况,一般情况下multipleResults只有一个元素。 7 final List<Object> multipleResults = new ArrayList<Object>(); 8 9 int resultSetCount = 0; 10 //获得第一个ResultSet对象 封装成ResultSetWrapper,主要包含了columnName、classNames、jdbcTypes 11 ResultSetWrapper rsw = getFirstResultSet(stmt); 12 //结构与multipleResults一致。 13 List<ResultMap> resultMaps = mappedStatement.getResultMaps(); 14 //resultMapCount = 1 15 int resultMapCount = resultMaps.size(); 16 validateResultMapsCount(rsw, resultMapCount); 17 while (rsw != null && resultMapCount > resultSetCount) { 18 //获得ResultMap对象 19 ResultMap resultMap = resultMaps.get(resultSetCount); 20 //处理ResultSet,将结果添加到multipleResults中 21 handleResultSet(rsw, resultMap, multipleResults, null); 22 //获取下一个ResultSet,并封装成ResultSetWrapper 23 rsw = getNextResultSet(stmt); 24 //清理 25 cleanUpAfterHandlingResultSet(); 26 resultSetCount++; 27 } 28 //多个ResultSet结合情况下,执行存储过程时会使用 29 String[] resultSets = mappedStatement.getResultSets(); 30 if (resultSets != null) { 31 while (rsw != null && resultSetCount < resultSets.length) { 32 ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]); 33 if (parentMapping != null) { 34 String nestedResultMapId = parentMapping.getNestedResultMapId(); 35 ResultMap resultMap = configuration.getResultMap(nestedResultMapId); 36 handleResultSet(rsw, resultMap, null, parentMapping); 37 } 38 rsw = getNextResultSet(stmt); 39 cleanUpAfterHandlingResultSet(); 40 resultSetCount++; 41 } 42 } 43 44 return collapseSingleResultList(multipleResults); 45 }
handleResultSet()
1 //处理 2 private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException { 3 try { 4 if (parentMapping != null) { 5 //适用于存储过程,多个ResultSet的情况 6 handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping); 7 } else { 8 //如果没有自定义ResultHandler,则使用DefaultResultHandler 9 if (resultHandler == null) { 10 DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory); 11 handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null); 12 multipleResults.add(defaultResultHandler.getResultList()); 13 } else { 14 //处理ResultSet的每一行结果 15 handleRowValues(rsw, resultMap, resultHandler, rowBounds, null); 16 } 17 } 18 } finally { 19 // issue #228 (close resultsets) 20 closeResultSet(rsw.getResultSet()); 21 } 22 }