入门:入门程序代码追踪
【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);
sqlSessionFactory代码
由入口: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类型
sqlSession代码
由入口: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();
}
得到sqlSession为DefaultSqlSession;
- DefaultSqlSessionFactory.openSession返回值均为DefaultSqlSession类型
- 如果SqlMapConfig.xml中没有Transaction,则返回默认的ManagedTransactionFactory
- 其中Environment、TransactionFactory、Executor均被final修饰
Executor
由sqlSession中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(this, transaction);
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()); } } }
sqlSession.selectOne
由sqlSession中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();
}
}