“入门:入门程序代码追踪”的版本间差异
第207行: | 第207行: | ||
==== BaseExecutor ==== | ==== BaseExecutor ==== | ||
抽象类BaseExecutor源码如下: | 抽象类BaseExecutor源码如下: | ||
<syntaxhighlight lang="java" line highlight="10,27,45,48,51,54-62,69,80-87"> | |||
package org.apache.ibatis.executor; | package org.apache.ibatis.executor; | ||
第296行: | 第296行: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
# “doQuery(ms, parameter, rowBounds, resultHandler, boundSql)”等方法在实现类中实现(如:BatchExecutor、ReuseExecutor、SimpleExecutor); | |||
# “getConnection(Log statementLog)”用于(使用transaction)获取链接,在SimpleExecutor的 prepareStatement 方法中调用; | |||
# “closeStatement(Statement statement)”用于关闭链接:在在SimpleExecutor的 doQuery 等方法中调用; | |||
* [[Mybatis源码:BaseExecutor解析]] | |||
=== Transaction === | === Transaction === |
2020年10月9日 (五) 21:16的版本
【2020/10/08 01:28:55】
入口代码
public class Mybatis_first {
//会话工厂
private SqlSessionFactory sqlSessionFactory;
@Before
public void createSqlSessionFactory() throws IOException {
// mybatis配置文件
String resource = "SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 使用SqlSessionFactoryBuilder从xml配置文件中创建SqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
public void testFindUserById() {
// 数据库会话实例
SqlSession sqlSession = null;
try {
// 创建数据库会话实例sqlSession
sqlSession = sqlSessionFactory.openSession();
// selectOne查询出一条记录
User user = sqlSession.selectOne("test.findUserById", 1);
SqlSessionFactoryBuilder代码
由入口:sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
:
package org.apache.ibatis.session;
public class SqlSessionFactoryBuilder {
...
public SqlSessionFactory build(InputStream inputStream) {
return build(inputStream, null, null);
}
...
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
...
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
得到sqlSessionFactory为DefaultSqlSessionFactory;
- SqlSessionFactoryBuilder().build返回值均为DefaultSqlSessionFactory类型
sqlSessionFactory代码
由入口:sqlSession = sqlSessionFactory.openSession();
:(由sqlSessionFactory可知,即“DefaultSqlSessionFactory.openSession()”)
package org.apache.ibatis.session.defaults;
public class DefaultSqlSessionFactory implements SqlSessionFactory {
private final Configuration configuration;
public DefaultSqlSessionFactory(Configuration configuration) {
this.configuration = configuration;
}
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
...
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
final Executor executor = configuration.newExecutor(tx, execType);
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();
}
}
...
private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) {
if (environment == null || environment.getTransactionFactory() == null) {
return new ManagedTransactionFactory();
}
return environment.getTransactionFactory();
}
- 根据configuration得到当前环境实例environment;
- 根据environment中的Transaction配置得到TransactionFactory;
- 并由transactionFactory根据environment数据源配置等,创建Transaction实例(tx);
- “TransactionIsolationLevel level”:事务隔离级别
- “boolean autoCommit”:事务自动提交【???】
- 由configuration根据tx实例和execType,创建executor实例;
- “ExecutorType execType”:executor类型(如:BatchExecutor、ReuseExecutor、SimpleExecutor)
- 根据configuration, executor生成DefaultSqlSession对象,并返回;
得到sqlSession为DefaultSqlSession;
- DefaultSqlSessionFactory.openSession返回值均为DefaultSqlSession类型
- 如果SqlMapConfig.xml中没有Transaction,则返回默认的ManagedTransactionFactory
- tx(Transaction)作为参数,用于构造Executor
- 其中Environment、TransactionFactory、Executor均被final修饰
Executor
由DefaultSqlSessionFactory中configuration.getDefaultExecutorType()
、final Executor executor = configuration.newExecutor(tx, execType);
:
package org.apache.ibatis.session;
public class Configuration {
...
protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
...
public ExecutorType getDefaultExecutorType() {
return defaultExecutorType;
}
...
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;
}
得到executor = new SimpleExecutor;
SimpleExecutor
SimpleExecutor源码如下(继承了抽象类BaseExecutor):
package org.apache.ibatis.executor; ... public class SimpleExecutor extends BaseExecutor { public SimpleExecutor(Configuration configuration, Transaction transaction) { super(configuration, transaction); } public int doUpdate(MappedStatement ms, Object parameter) throws SQLException { Statement stmt = null; try { Configuration configuration = ms.getConfiguration(); StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null); stmt = prepareStatement(handler, ms.getStatementLog()); return handler.update(stmt); } finally { closeStatement(stmt); } } 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(); StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql); stmt = prepareStatement(handler, ms.getStatementLog()); return handler.<E>query(stmt, resultHandler); } finally { closeStatement(stmt); } } public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException { return Collections.emptyList(); } 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
抽象类BaseExecutor源码如下:
package org.apache.ibatis.executor;
...
public abstract class BaseExecutor implements Executor {
...
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
BoundSql boundSql = ms.getBoundSql(parameter);
CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
@SuppressWarnings("unchecked")
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 (closed) throw new ExecutorException("Executor was closed.");
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
}
List<E> list;
try {
queryStack++;
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
if (list != null) {
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else {
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
queryStack--;
}
if (queryStack == 0) {
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
deferredLoads.clear(); // issue #601
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
clearLocalCache(); // issue #482
}
}
return list;
}
...
protected abstract int doUpdate(MappedStatement ms, Object parameter)
throws SQLException;
protected abstract List<BatchResult> doFlushStatements(boolean isRollback)
throws SQLException;
protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)
throws SQLException;
protected void closeStatement(Statement statement) {
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
// ignore
}
}
}
...
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
List<E> list;
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
localCache.removeObject(key);
}
localCache.putObject(key, list);
if (ms.getStatementType() == StatementType.CALLABLE) {
localOutputParameterCache.putObject(key, parameter);
}
return list;
}
protected Connection getConnection(Log statementLog) throws SQLException {
Connection connection = transaction.getConnection();
if (statementLog.isDebugEnabled()) {
return ConnectionLogger.newInstance(connection, statementLog, queryStack);
} else {
return connection;
}
}
- “doQuery(ms, parameter, rowBounds, resultHandler, boundSql)”等方法在实现类中实现(如:BatchExecutor、ReuseExecutor、SimpleExecutor);
- “getConnection(Log statementLog)”用于(使用transaction)获取链接,在SimpleExecutor的 prepareStatement 方法中调用;
- “closeStatement(Statement statement)”用于关闭链接:在在SimpleExecutor的 doQuery 等方法中调用;
Transaction
由sqlSession中final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
、return new ManagedTransactionFactory();
有:
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
即“ManagedTransactionFactory.newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit)”:
package org.apache.ibatis.transaction.managed;
public class ManagedTransactionFactory implements TransactionFactory {
...
public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
// Silently ignores autocommit and isolation level, as managed transactions are entirely
// controlled by an external manager. It's silently ignored so that
// code remains portable between managed and unmanaged configurations.
return new ManagedTransaction(ds, level, closeConnection);
}
}
得到Transaction tx = new ManagedTransaction,其源码如下:
package org.apache.ibatis.transaction.managed; ... public class ManagedTransaction implements Transaction { private static final Log log = LogFactory.getLog(ManagedTransaction.class); private DataSource dataSource; private TransactionIsolationLevel level; private Connection connection; private boolean closeConnection; public ManagedTransaction(Connection connection, boolean closeConnection) { this.connection = connection; this.closeConnection = closeConnection; } public ManagedTransaction(DataSource ds, TransactionIsolationLevel level, boolean closeConnection) { this.dataSource = ds; this.level = level; this.closeConnection = closeConnection; } public Connection getConnection() throws SQLException { if (this.connection == null) { openConnection(); } return this.connection; } public void commit() throws SQLException { // Does nothing } public void rollback() throws SQLException { // Does nothing } public void close() throws SQLException { if (this.closeConnection && this.connection != null) { if (log.isDebugEnabled()) { log.debug("Closing JDBC Connection [" + this.connection + "]"); } this.connection.close(); } } protected void openConnection() throws SQLException { if (log.isDebugEnabled()) { log.debug("Opening JDBC Connection"); } this.connection = this.dataSource.getConnection(); if (this.level != null) { this.connection.setTransactionIsolation(this.level.getLevel()); } } }
- “getConnection()”在BaseExecutor的“getConnection(Log statementLog)”方法中调用;
sqlSession代码
以入口“User user = sqlSession.selectOne("test.findUserById", 1);”为例:
由DefaultSqlSessionFactory代码,User user = sqlSession.selectOne("test.findUserById", 1);
即“DefaultSqlSession.selectOne(String statement, Object parameter)”:
package org.apache.ibatis.session.defaults;
public class DefaultSqlSession implements SqlSession {
...
public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
this.configuration = configuration;
this.executor = executor;
this.dirty = false;
this.autoCommit = autoCommit;
}
...
public <T> T selectOne(String statement, Object parameter) {
// Popular vote was to return null on 0 results and throw exception on too many.
List<T> list = this.<T>selectList(statement, parameter);
if (list.size() == 1) {
return list.get(0);
} else if (list.size() > 1) {
throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
} else {
return null;
}
}
...
public <E> List<E> selectList(String statement, Object parameter) {
return this.selectList(statement, parameter, RowBounds.DEFAULT);
}
...
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
MappedStatement ms = configuration.getMappedStatement(statement);
List<E> result = executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
return result;
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
- selectOne也是由selectList实现,“list.size() > 1”则抛出异常
- 操作数据库由executor实现
- 默认的executor是“SimpleExecutor”
- (继承自抽象类BaseExecutor):