Mybatis工作機制原始碼分析—一次insert請求處理流程
阿新 • • 發佈:2019-02-19
本文從原始碼分析的角度分析Mybatis一次insert請求處理流程。
insert整體處理流程
時序圖
相關原始碼
/** SqlSessionTemplate.java */ public int insert(String statement, Object parameter) { return this.sqlSessionProxy.insert(statement, parameter); } // jdk動態代理 private class SqlSessionInterceptor implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 獲取SqlSession SqlSession sqlSession = getSqlSession( SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator); try { // 請求(select|insert|update|delete)處理,這裡採用動態代理 Object result = method.invoke(sqlSession, args); if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) { // force commit even on non-dirty sessions because some databases require // a commit/rollback before calling close() sqlSession.commit(true); // 非Spring管理的事務,手工提交 } return result; } catch (Throwable t) { Throwable unwrapped = unwrapThrowable(t); if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) { // release the connection to avoid a deadlock if the translator is no loaded. See issue #22 closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); sqlSession = null; Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped); if (translated != null) { unwrapped = translated; } } throw unwrapped; } finally { if (sqlSession != null) { // 請求處理完成後,sqlSession釋放或保留 closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); } } } } // 對使用後的SqlSession進行相關處理 public static void closeSqlSession(SqlSession session, SqlSessionFactory sessionFactory) { notNull(session, NO_SQL_SESSION_SPECIFIED); notNull(sessionFactory, NO_SQL_SESSION_FACTORY_SPECIFIED); SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); if ((holder != null) && (holder.getSqlSession() == session)) { // Spring Transactional下的SqlSession,不真正關閉sqlSession if (LOGGER.isDebugEnabled()) { LOGGER.debug("Releasing transactional SqlSession [" + session + "]"); } // 只進行sqlSessionHolder的referenceCount-- holder.released(); } else { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Closing non transactional SqlSession [" + session + "]"); } // 非Spring Transactional下的SqlSession,則SqlSession——>Executor——>Transaction——>DataSource——>Connection的close操作 session.close(); } }
SqlSessionUtils.getSqlSession工作流程
時序圖
相關類結構圖
SqlSession類結構圖:
Executor類結構圖:
Transaction類結構圖:
SqlSession構建過程中的元件支援
相關原始碼
/** SqlSessionUtils.java */ public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) { notNull(sessionFactory, NO_SQL_SESSION_FACTORY_SPECIFIED); notNull(executorType, NO_EXECUTOR_TYPE_SPECIFIED); // 先從TransactionSynchronizationManager的事務資源快取resources獲取sessionFactory對應的SqlSessionHolder SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); // 從SqlSessionHolder中提取SqlSession SqlSession session = sessionHolder(executorType, holder); if (session != null) { return session; } if (LOGGER.isDebugEnabled()) { LOGGER.debug("Creating a new SqlSession"); } // 開啟新的SqlSession session = sessionFactory.openSession(executorType); // SpringManagedTransactionFactory下,快取sessionHolder,進行Transaction synchronizations準備工作 registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session); return session; } // 從SqlSessionHolder中提取SqlSession,與Spring事務同步條件下才能提取 private static SqlSession sessionHolder(ExecutorType executorType, SqlSessionHolder holder) { SqlSession session = null; if (holder != null && holder.isSynchronizedWithTransaction()) { // sqlSessionHolder與Spring事務同步 if (holder.getExecutorType() != executorType) { throw new TransientDataAccessResourceException("Cannot change the ExecutorType when there is an existing transaction"); } holder.requested(); // 引用次數加1 if (LOGGER.isDebugEnabled()) { LOGGER.debug("Fetched SqlSession [" + holder.getSqlSession() + "] from current transaction"); } session = holder.getSqlSession(); // 獲取sqlSession } return session; } /** TransactionSynchronizationManager.java */ public static Object getResource(Object key) { Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key); Object value = doGetResource(actualKey); if (value != null && logger.isTraceEnabled()) { logger.trace("Retrieved value [" + value + "] for key [" + actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]"); } return value; } // 從TransactionSynchronizationManager的事務資源快取ThreadLocal<Map<Object, Object>> resources獲取actualKey對應的資源 // ThreadLocal模式,執行緒安全 private static Object doGetResource(Object actualKey) { Map<Object, Object> map = resources.get(); if (map == null) { return null; } Object value = map.get(actualKey); // Transparently remove ResourceHolder that was marked as void... if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) { map.remove(actualKey); // Remove entire ThreadLocal if empty... if (map.isEmpty()) { resources.remove(); } value = null; } return value; } /** DefaultSqlSessionFactory.java */ public SqlSession openSession(ExecutorType execType) { return openSessionFromDataSource(execType, null, false); } private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; try { // configuration屬性獲取environment final Environment environment = configuration.getEnvironment(); // 從environment獲取transactionFactory final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); // 開啟新transaction,基於environment的dataSource tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); // 基於transaction、execType例項化executor final Executor executor = configuration.newExecutor(tx, execType); // 基於configuration、executor建立DefaultSqlSession 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(); } } // environment獲取TransactionFactory private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) { if (environment == null || environment.getTransactionFactory() == null) { // 預設為ManagedTransactionFactory return new ManagedTransactionFactory(); } return environment.getTransactionFactory(); } /** SpringManagedTransactionFactory.java */ // Spring容器管理下的transaction public Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit) { return new SpringManagedTransaction(dataSource); } /** Configuration.java */ 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; } /** SqlSessionUtils.java */ // 對於SpringManagedTransactionFactory,構建SqlSessionHolder,將其快取到Transactional resources,且進行Transaction synchronizations標識 // 以便Spring容器進行事務管理 private static void registerSessionHolder(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator, SqlSession session) { SqlSessionHolder holder; if (TransactionSynchronizationManager.isSynchronizationActive()) { // Transaction synchronizations至少已經初始化 Environment environment = sessionFactory.getConfiguration().getEnvironment(); // SpringManagedTransactionFactory才進行register SessionHolder工作 if (environment.getTransactionFactory() instanceof SpringManagedTransactionFactory) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Registering transaction synchronization for SqlSession [" + session + "]"); } // 構建SqlSessionHolder holder = new SqlSessionHolder(session, executorType, exceptionTranslator); // Transactional resources新增sessionFactory、holder鍵值對,resources為ThreadLocal<Map<Object, Object>> TransactionSynchronizationManager.bindResource(sessionFactory, holder); // Transaction synchronizations新增SqlSessionSynchronization,synchronizations為ThreadLocal<Set<TransactionSynchronization>> TransactionSynchronizationManager.registerSynchronization(new SqlSessionSynchronization(holder, sessionFactory)); holder.setSynchronizedWithTransaction(true); // holder標識synchronizedWithTransaction為true holder.requested(); } else { if (TransactionSynchronizationManager.getResource(environment.getDataSource()) == null) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("SqlSession [" + session + "] was not registered for synchronization because DataSource is not transactional"); } } else { throw new TransientDataAccessResourceException( "SqlSessionFactory must be using a SpringManagedTransactionFactory in order to use Spring transaction synchronization"); } } } else { if (LOGGER.isDebugEnabled()) { LOGGER.debug("SqlSession [" + session + "] was not registered for synchronization because synchronization is not active"); } } }
DefaultSqlSession.insert工作流程
時序圖
相關類結構圖
ObjectWrapper類結構圖:
相關Handler類結構圖:
TypeHandler類結構圖:
Mybatis一次請求處理核心流程(select|insert|update|delete)
相關原始碼
/** DefaultSqlSession.java */ // 處理insert請求 // @param statement:statement id;@param parameter:輸入引數 public int insert(String statement, Object parameter) { // 轉給update進行處理 return update(statement, parameter); } // 處理sql寫的請求,包括insert、update、delete public int update(String statement, Object parameter) { try { dirty = true; // 根據id獲取MappedStatement MappedStatement ms = configuration.getMappedStatement(statement); // return executor.update(ms, wrapCollection(parameter)); } catch (Exception e) { throw ExceptionFactory.wrapException("Error updating database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } } /** Configuration.java */ // 從configuration Map<String, MappedStatement> mappedStatements,根據獲取id獲取MappedStatement; public MappedStatement getMappedStatement(String id) { return this.getMappedStatement(id, true); } public MappedStatement getMappedStatement(String id, boolean validateIncompleteStatements) { if (validateIncompleteStatements) { buildAllStatements(); } return mappedStatements.get(id); } // 解析快取中未處理的statement nodes,提供fail-fast statement驗證 protected void buildAllStatements() { if (!incompleteResultMaps.isEmpty()) { synchronized (incompleteResultMaps) { // This always throws a BuilderException. incompleteResultMaps.iterator().next().resolve(); } } if (!incompleteCacheRefs.isEmpty()) { synchronized (incompleteCacheRefs) { // This always throws a BuilderException. incompleteCacheRefs.iterator().next().resolveCacheRef(); } } if (!incompleteStatements.isEmpty()) { synchronized (incompleteStatements) { // This always throws a BuilderException. incompleteStatements.iterator().next().parseStatementNode(); } } if (!incompleteMethods.isEmpty()) { synchronized (incompleteMethods) { // This always throws a BuilderException. incompleteMethods.iterator().next().resolve(); } } } /** DefaultSqlSession.java */ // 對Collection、List、Array進行StrictMap的wrap處理 private Object wrapCollection(final Object object) { if (object instanceof Collection) { StrictMap<Object> map = new StrictMap<Object>(); map.put("collection", object); if (object instanceof List) { map.put("list", object); } return map; } else if (object != null && object.getClass().isArray()) { StrictMap<Object> map = new StrictMap<Object>(); map.put("array", object); return map; } return object; } /** CachingExecutor.java */ // CachingExecutor update public int update(MappedStatement ms, Object parameterObject) throws SQLException { flushCacheIfRequired(ms); return delegate.update(ms, parameterObject); } // flush MappedStatement cache private void flushCacheIfRequired(MappedStatement ms) { Cache cache = ms.getCache(); if (cache != null && ms.isFlushCacheRequired()) { tcm.clear(cache); } } /** TransactionalCacheManager.java */ public void clear(Cache cache) { getTransactionalCache(cache).clear(); } private TransactionalCache getTransactionalCache(Cache cache) { TransactionalCache txCache = transactionalCaches.get(cache); if (txCache == null) { txCache = new TransactionalCache(cache); transactionalCaches.put(cache, txCache); } return txCache; } /** TransactionalCache.java */ public void clear() { clearOnCommit = true; entriesToAddOnCommit.clear(); } /** BaseExecutor.java(SimpleExecutor) */ public int update(MappedStatement ms, Object parameter) throws SQLException { ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId()); if (closed) { throw new ExecutorException("Executor was closed."); } // 清空BaseExecutor下的localCache、localOutputParameterCache,其均為PerpetualCache // PerpetualCache實際快取為HashMap<Object, Object> clearLocalCache(); return doUpdate(ms, parameter); } public void clearLocalCache() { if (!closed) { localCache.clear(); localOutputParameterCache.clear(); } } /** SimpleExecutor.java */ // 實際處理update請求 public int doUpdate(MappedStatement ms, Object parameter) throws SQLException { Statement stmt = null; try { // 獲取MappedStatement的Configuration Configuration configuration = ms.getConfiguration(); // 建立StatementHandler StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null); stmt = prepareStatement(handler, ms.getStatementLog()); return handler.update(stmt); } finally { closeStatement(stmt); } } /** Configuration.java */ public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql); statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler); return statementHandler; } /** RoutingStatementHandler.java */ // RoutingStatementHandler採用靜態代理機制 // 對SimpleStatementHandler、PreparedStatementHandler、CallableStatementHandler進行代理 public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { switch (ms.getStatementType()) { case STATEMENT: delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql); break; case PREPARED: delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql); break; case CALLABLE: delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql); break; default: throw new ExecutorException("Unknown statement type: " + ms.getStatementType()); } } /** PreparedStatementHandler.java */ // 建立PreparedStatementHandler public PreparedStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { // 進入BaseStatementHandler super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql); } /** BaseStatementHandler.java */ // BaseStatementHandler建構函式 protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { // 用mappedStatement的configuration設定configuration屬性 this.configuration = mappedStatement.getConfiguration(); // 設定executor屬性,用於獲取sql connection this.executor = executor; // 設定mappedStatement屬性,用於獲取boundSql this.mappedStatement = mappedStatement; // 設定rowBounds屬性,用於限定獲取表中記錄的行數offset、limit this.rowBounds = rowBounds; // 設定typeHandlerRegistry屬性,用於獲取typeHandler,對映java type——jdbc type this.typeHandlerRegistry = configuration.getTypeHandlerRegistry(); // 設定objectFactory屬性 this.objectFactory = configuration.getObjectFactory(); if (boundSql == null) { // issue #435, get the key before calculating the statement generateKeys(parameterObject); // mappedStatement基於輸入引數parameterObject建立BoundSql // 實際是利用sqlSource屬性建立的 boundSql = mappedStatement.getBoundSql(parameterObject); } this.boundSql = boundSql; // 構建parameterHandler,用於設定PreparedStatement的引數 this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql); // 構建resultSetHandler,用於處理結果集和輸出引數 this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql); } /** MappedStatement.java */ public BoundSql getBoundSql(Object parameterObject) { // sqlSource建立BoundSql BoundSql boundSql = sqlSource.getBoundSql(parameterObject); List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); if (parameterMappings == null || parameterMappings.isEmpty()) { boundSql = new BoundSql(configuration, boundSql.getSql(), parameterMap.getParameterMappings(), parameterObject); } // check for nested result maps in parameter mappings (issue #30) // 確定hasNestedResultMaps for (ParameterMapping pm : boundSql.getParameterMappings()) { String rmId = pm.getResultMapId(); if (rmId != null) { ResultMap rm = configuration.getResultMap(rmId); if (rm != null) { hasNestedResultMaps |= rm.hasNestedResultMaps(); } } } return boundSql; } /** RawSqlSource.java */ public BoundSql getBoundSql(Object parameterObject) { return sqlSource.getBoundSql(parameterObject); } /** StaticSqlSource.java */ public BoundSql getBoundSql(Object parameterObject) { return new BoundSql(configuration, sql, parameterMappings, parameterObject); } /** BoundSql.java */ public BoundSql(Configuration configuration, String sql, List<ParameterMapping> parameterMappings, Object parameterObject) { this.sql = sql; this.parameterMappings = parameterMappings; this.parameterObject = parameterObject; this.additionalParameters = new HashMap<String, Object>(); this.metaParameters = configuration.newMetaObject(additionalParameters); } /** Configuration.java */ // 用LanguageDriver建立ParameterHandler public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) { ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql); parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler); return parameterHandler; } /** XMLLanguageDriver.java */ public ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) { return new DefaultParameterHandler(mappedStatement, parameterObject, boundSql); } /** DefaultParameterHandler.java */ public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) { this.mappedStatement = mappedStatement; this.configuration = mappedStatement.getConfiguration(); this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry(); this.parameterObject = parameterObject; this.boundSql = boundSql; } /** Configuration.java */ // 構建DefaultResultSetHandler public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler, ResultHandler resultHandler, BoundSql boundSql) { ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds); resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler); return resultSetHandler; } /** DefaultResultSetHandler.java */ public DefaultResultSetHandler(Executor executor, MappedStatement mappedStatement, ParameterHandler parameterHandler, ResultHandler<?> resultHandler, BoundSql boundSql, RowBounds rowBounds) { this.executor = executor; this.configuration = mappedStatement.getConfiguration(); this.mappedStatement = mappedStatement; this.rowBounds = rowBounds; this.parameterHandler = parameterHandler; this.boundSql = boundSql; this.typeHandlerRegistry = configuration.getTypeHandlerRegistry(); this.objectFactory = configuration.getObjectFactory(); this.reflectorFactory = configuration.getReflectorFactory(); this.resultHandler = resultHandler; } /** SimpleExecutor.java */ private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Statement stmt; Connection connection = getConnection(statementLog); stmt = handler.prepare(connection); handler.parameterize(stmt); return stmt; } /** BaseExecutor.java */ // BaseExecutor獲取Connection,實際用transaction來獲取Connection protected Connection getConnection(Log statementLog) throws SQLException { Connection connection = transaction.getConnection(); if (statementLog.isDebugEnabled()) { return ConnectionLogger.newInstance(connection, statementLog, queryStack); } else { return connection; } } /** SpringManagedTransaction.java */ public Connection getConnection() throws SQLException { if (this.connection == null) { openConnection(); } return this.connection; } // SpringManagedTransaction中新建sql connection private void openConnection() throws SQLException { this.connection = DataSourceUtils.getConnection(this.dataSource); this.autoCommit = this.connection.getAutoCommit(); this.isConnectionTransactional = DataSourceUtils.isConnectionTransactional(this.connection, this.dataSource); if (LOGGER.isDebugEnabled()) { LOGGER.debug( "JDBC Connection [" + this.connection + "] will" + (this.isConnectionTransactional ? " " : " not ") + "be managed by Spring"); } } /** org.springframework.jdbc.datasource.DataSourceUtils.java */ public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException { try { return doGetConnection(dataSource); } catch (SQLException ex) { throw new CannotGetJdbcConnectionException("Could not get JDBC Connection", ex); } } public static Connection doGetConnection(DataSource dataSource) throws SQLException { Assert.notNull(dataSource, "No DataSource specified"); // 先從TransactionSynchronizationManager的事務資源快取resources獲取dataSource對應的conHolder ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource); if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) { // TransactionSynchronizationManager的事務資源快取中有conHolder,則直接返回Connection conHolder.requested(); if (!conHolder.hasConnection()) { logger.debug("Fetching resumed JDBC Connection from DataSource"); conHolder.setConnection(dataSource.getConnection()); } return conHolder.getConnection(); } // Else we either got no holder or an empty thread-bound holder here. logger.debug("Fetching JDBC Connection from DataSource"); // 從DataSource獲取JDBC Connection Connection con = dataSource.getConnection(); if (TransactionSynchronizationManager.isSynchronizationActive()) { // 為JDBC Connection註冊Transaction synchronizations logger.debug("Registering transaction synchronization for JDBC Connection"); // Use same Connection for further JDBC actions within the transaction. // Thread-bound object will get removed by synchronization at transaction completion. ConnectionHolder holderToUse = conHolder; if (holderToUse == null) { holderToUse = new ConnectionHolder(con); } else { holderToUse.setConnection(con); } holderToUse.requested(); TransactionSynchronizationManager.registerSynchronization( new ConnectionSynchronization(holderToUse, dataSource)); holderToUse.setSynchronizedWithTransaction(true); if (holderToUse != conHolder) { // 繫結Transactional resources TransactionSynchronizationManager.bindResource(dataSource, holderToUse); } } return con; } /** ConnectionHolder.java */ protected boolean hasConnection() { return (this.connectionHandle != null); } public Connection getConnection() { Assert.notNull(this.connectionHandle, "Active Connection is required"); if (this.currentConnection == null) { this.currentConnection = this.connectionHandle.getConnection(); } return this.currentConnection; } /** DataSourceUtils.java */ // 判斷con是否來自TransactionSynchronizationManager中resources的key為dataSource的conHolder的Connection public static boolean isConnectionTransactional(Connection con, DataSource dataSource) { if (dataSource == null) { return false; } ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource); return (conHolder != null && connectionEquals(conHolder, con)); } private static boolean connectionEquals(ConnectionHolder conHolder, Connection passedInCon) { if (!conHolder.hasConnection()) { return false; } Connection heldCon = conHolder.getConnection(); // Explicitly check for identity too: for Connection handles that do not implement // "equals" properly, such as the ones Commons DBCP exposes). return (heldCon == passedInCon || heldCon.equals(passedInCon) || getTargetConnection(heldCon).equals(passedInCon)); } /** ConnectionLogger.java */ public static Connection newInstance(Connection conn, Log statementLog, int queryStack) { InvocationHandler handler = new ConnectionLogger(conn, statementLog, queryStack); ClassLoader cl = Connection.class.getClassLoader(); return (Connection) Proxy.newProxyInstance(cl, new Class[]{Connection.class}, handler); } /** RoutingStatementHandler.java */ public Statement prepare(Connection connection) throws SQLException { return delegate.prepare(connection); } /** BaseStatementHandler.java */ // 用connection.prepareStatement獲取預編譯的PreparedStatement // 且設定其queryTimeout、fetchSize屬性 public Statement prepare(Connection connection) throws SQLException { ErrorContext.instance().sql(boundSql.getSql()); Statement statement = null; try { // 用connection獲取PreparedStatement statement = instantiateStatement(connection); // 用mappedStatement的queryTimeout屬性設定statement的queryTimeout setStatementTimeout(statement); // 用mappedStatement的fetchSize屬性設定statement的fetchSize setFetchSize(statement); return statement; } catch (SQLException e) { closeStatement(statement); throw e; } catch (Exception e) { closeStatement(statement); throw new ExecutorException("Error preparing statement. Cause: " + e, e); } } /** PreparedStatementHandler.java */ // connection.prepareStatement,獲取預編譯的sql語句,PreparedStatement protected Statement instantiateStatement(Connection connection) throws SQLException { String sql = boundSql.getSql(); if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) { String[] keyColumnNames = mappedStatement.getKeyColumns(); if (keyColumnNames == null) { return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS); } else { return connection.prepareStatement(sql, keyColumnNames); } } else if (mappedStatement.getResultSetType() != null) { return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY); } else { return connection.prepareStatement(sql); } } /** BaseStatementHandler.java */ protected void setStatementTimeout(Statement stmt) throws SQLException { Integer timeout = mappedStatement.getTimeout(); Integer defaultTimeout = configuration.getDefaultStatementTimeout(); if (timeout != null) { stmt.setQueryTimeout(timeout); } else if (defaultTimeout != null) { stmt.setQueryTimeout(defaultTimeout); } } protected void setFetchSize(Statement stmt) throws SQLException { Integer fetchSize = mappedStatement.getFetchSize(); if (fetchSize != null) { stmt.setFetchSize(fetchSize); return; } Integer defaultFetchSize = configuration.getDefaultFetchSize(); if (defaultFetchSize != null) { stmt.setFetchSize(defaultFetchSize); } } /** RoutingStatementHandler.java */ public void parameterize(Statement statement) throws SQLException { delegate.parameterize(statement); } /** PreparedStatementHandler.java */ public void parameterize(Statement statement) throws SQLException { parameterHandler.setParameters((PreparedStatement) statement); } /** DefaultParameterHandler.java */ // PreparedStatement設定佔位符引數值 public void setParameters(PreparedStatement ps) { ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId()); List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); if (parameterMappings != null) { for (int i = 0; i < parameterMappings.size(); i++) { 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 typeHandler = parameterMapping.getTypeHandler(); JdbcType jdbcType = parameterMapping.getJdbcType(); if (value == null && jdbcType == null) { jdbcType = configuration.getJdbcTypeForNull(); } try { // 採用匹配value, jdbcType型別的typeHandler,便於PreparedStatement設定佔位符引數值 typeHandler.setParameter(ps, i + 1, value, jdbcType); } catch (TypeException e) { throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e); } catch (SQLException e) { throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e); } } } } } /** BaseTypeHandler.java */ public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException { if (parameter == null) { if (jdbcType == null) { throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters."); } try { ps.setNull(i, jdbcType.TYPE_CODE); } catch (SQLException e) { throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . " + "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. " + "Cause: " + e, e); } } else { try { setNonNullParameter(ps, i, parameter, jdbcType); } catch (Exception e) { throw new TypeException("Error setting non null for parameter #" + i + " with JdbcType " + jdbcType + " . " + "Try setting a different JdbcType for this parameter or a different configuration property. " + "Cause: " + e, e); } } } /** UnknownTypeHandler.java */ public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException { // 基於value, jdbcType型別獲取匹配的typeHandler TypeHandler handler = resolveTypeHandler(parameter, jdbcType); // PreparedStatement設定佔位符引數值 handler.setParameter(ps, i, parameter, jdbcType); } private TypeHandler<? extends Object> resolveTypeHandler(Object parameter, JdbcType jdbcType) { TypeHandler<? extends Object> handler; if (parameter == null) { handler = OBJECT_TYPE_HANDLER; } else { handler = typeHandlerRegistry.getTypeHandler(parameter.getClass(), jdbcType); // check if handler is null (issue #270) if (handler == null || handler instanceof UnknownTypeHandler) { handler = OBJECT_TYPE_HANDLER; } } return handler; } /** TypeHandlerRegistry.java */ public <T> TypeHandler<T> getTypeHandler(Class<T> type, JdbcType jdbcType) { return getTypeHandler((Type) type, jdbcType); } private <T> TypeHandler<T> getTypeHandler(Type type, JdbcType jdbcType) { Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = TYPE_HANDLER_MAP.get(type); TypeHandler<?> handler = null; if (jdbcHandlerMap != null) { handler = jdbcHandlerMap.get(jdbcType); if (handler == null) { handler = jdbcHandlerMap.get(null); } } if (handler == null && type != null && type instanceof Class && Enum.class.isAssignableFrom((Class<?>) type)) { handler = new EnumTypeHandler((Class<?>) type); } // type drives generics here return (TypeHandler<T>) handler; } /** StringTypeHandler.java */ public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, parameter); } /** RoutingStatementHandler.java */ public int update(Statement statement) throws SQLException { return delegate.update(statement); } /** PreparedStatementHandler.java */ // 真正執行PreparedStatement public int update(Statement statement) throws SQLException { PreparedStatement ps = (PreparedStatement) statement; // 執行PreparedStatement ps.execute(); // 獲取寫的記錄行數 int rows = ps.getUpdateCount(); Object parameterObject = boundSql.getParameterObject(); KeyGenerator keyGenerator = mappedStatement.getKeyGenerator(); keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject); return rows; } /** SqlSessionUtils.java */ // 用session與Transactional resources的sessionFactory所關聯的SqlSessionHolder的SqlSession進行比較 // 判斷是否為Spring transactional public static boolean isSqlSessionTransactional(SqlSession session, SqlSessionFactory sessionFactory) { notNull(session, NO_SQL_SESSION_SPECIFIED); notNull(sessionFactory, NO_SQL_SESSION_FACTORY_SPECIFIED); SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); return (holder != null) && (holder.getSqlSession() == session); }