- SqlSession
- SqlSession下的四大對象
- Executor
- StatementHandler
- paramsHandler
- resultSetHandler
SqlSession
- SqlSession是一個會話,相當于jdbc的Connection對象,生命周期應該是請求資料庫處理事務的過程中。它是非線程安全的,在每次建立SqlSession都必須及時關閉它,它長期存在就會使資料庫連接配接池的活動資源減少。
SqlSession下的四大對象
- Mapper執行的過程是通過Executor、StatementHandler、ParameterHandler和ResultHandler來完成資料庫操作和結果傳回的
- Executor表示執行器,排程相關的handler來執行對應的sql(StatementHandler、ParameterHandler、ResultHandler)
- StatementHandler的作用是使用資料庫的Statement(PreparedStatement)執行操作
- ParameterHandler用于SQL對參數的處理
- ResultHandler是進行最後資料集(ResultSet)的封裝傳回處理的
Executor
- Executor是一個真正執行java和資料庫互動的東西
- SIMPLE
- REUSE
- BATCH
- 建立
在DefaultSqlSessionFactory中建立DefaultSqlSession之前建立Executor(通過Configuration建立),以下是Configuration中建立Executor的代碼。根據配置類型去建立三種執行器中的一種,在建立之後将Executor放到interceptorChain之中 public Executor newExecutor(Transaction transaction, ExecutorType executorType) { executorType = executorType == null ? defaultExecutorType : executorType; executorType = executorType == null ? ExecutorType.SIMPLE : executorType; 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); } if (cacheEnabled) { executor = new CachingExecutor(executor); } executor = (Executor) interceptorChain.pluginAll(executor); return executor; }
- SimpleExecutor
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { Statement stmt = null; try { Configuration configuration = ms.getConfiguration(); //通過Configuration建立StatementHandler StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, rowBounds, resultHandler, boundSql); //預編譯sql,并對參數進行初始化操作 stmt = prepareStatement(handler, ms.getStatementLog()); //resultHandler 組裝傳回結果 return handler.<E>query(stmt, resultHandler); } finally { closeStatement(stmt); } } private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Statement stmt; Connection connection = getConnection(statementLog); stmt = handler.prepare(connection); //設定參數并執行(預編譯sql) handler.parameterize(stmt); return stmt; }
StatementHandler
- 建立
/*** 在Executor建立StatementHandler,StatementHandler是在Configuration中建立,代碼如下 **/ public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { /** RoutingStatementHandler不是真實的服務對象,而是通過擴充卡找到對應的StatementHandler(對象的擴充卡模式) SimpleStatementHandler PreparedStatementHandler CallableStatementHandler */ StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql); statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler); return statementHandler; }
- SimpleStatementHandler
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException { String sql = boundSql.getSql(); statement.execute(sql); //使用ResultSetHandler封裝結果傳回給調用者 return resultSetHandler.<E>handleResultSets(statement); }
- PreparedStatementHandler
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException { //sql編譯已經在之前都做好了,是以這裡直接執行就可以了 PreparedStatement ps = (PreparedStatement) statement; ps.execute(); return resultSetHandler.<E> handleResultSets(ps); } public void parameterize(Statement statement) throws SQLException { KeyGenerator keyGenerator = mappedStatement.getKeyGenerator(); ErrorContext.instance().store(); keyGenerator.processBefore(executor, mappedStatement, statement, boundSql.getParameterObject()); ErrorContext.instance().recall(); rebindGeneratedKey(); parameterHandler.setParameters((PreparedStatement) statement); }
paramsHandler
- 代碼
public interface ParameterHandler { //傳回參數對象 Object getParameterObject(); //設定預編譯sql語句的參數 void setParameters(PreparedStatement ps) throws SQLException; }
mybatis提供一個預設的DefaultParameterHandler public void setParameters(PreparedStatement ps) throws SQLException { ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId()); List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); if (parameterMappings != null) { //從parameterObject對象中擷取參數,然後使用typeHandler進行參數處理 MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(parameterObject); for (int i = 0; i < parameterMappings.size(); i++) { ParameterMapping parameterMapping = parameterMappings.get(i); if (parameterMapping.getMode() != ParameterMode.OUT) { Object value; String propertyName = parameterMapping.getProperty(); PropertyTokenizer prop = new PropertyTokenizer(propertyName); if (parameterObject == null) { value = null; } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { value = parameterObject; } else if (boundSql.hasAdditionalParameter(propertyName)) { value = boundSql.getAdditionalParameter(propertyName); } else if (propertyName.startsWith(ForEachSqlNode.ITEM_PREFIX) && boundSql.hasAdditionalParameter(prop.getName())) { value = boundSql.getAdditionalParameter(prop.getName()); if (value != null) { value = configuration.newMetaObject(value).getValue(propertyName.substring(prop.getName().length())); } } else { value = metaObject == null ? null : metaObject.getValue(propertyName); } TypeHandler typeHandler = parameterMapping.getTypeHandler(); if (typeHandler == null) { throw new ExecutorException("There was no TypeHandler found for parameter " + propertyName + " of statement " + mappedStatement.getId()); } JdbcType jdbcType = parameterMapping.getJdbcType(); if (value == null && jdbcType == null) jdbcType = configuration.getJdbcTypeForNull(); typeHandler.setParameter(ps, i + 1, value, jdbcType); } } } }
resultSetHandler
- 結果集處理器
public interface ResultSetHandler { //包裝結果集 <E> List<E> handleResultSets(Statement stmt) throws SQLException; //處理存儲過程輸出參數的 void handleOutputParameters(CallableStatement cs) throws SQLException; }