1. 程式人生 > >Mybatis工作機制原始碼分析—一次insert請求處理流程

Mybatis工作機制原始碼分析—一次insert請求處理流程

      本文從原始碼分析的角度分析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);
}