mybatis-SqlSession

时间:2021-11-15 02:20:14

1. 概述

在前面,我们已经详细解析了 MyBatis 执行器 Executor 相关的内容,但是显然,Executor 是不适合直接暴露给用户使用的,而是需要通过 SqlSession 。

流程如下图:

mybatis-SqlSession

示例代码如下:

// 仅仅是示例哈

// 构建 SqlSessionFactory 对象
Reader reader = Resources.getResourceAsReader("org/apache/ibatis/autoconstructor/mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);

// 获得 SqlSession 对象
SqlSession sqlSession = sqlSessionFactory.openSession();

// 获得 Mapper 对象
final AutoConstructorMapper mapper = sqlSession.getMapper(AutoConstructorMapper.class);

// 执行查询
final Object subject = mapper.getSubject(1);

而本文解析的类,都在 session 包下,整体类图如下:

老艿艿:省略了一部分前面已经解析过的类。

mybatis-SqlSession

  • 核心是 SqlSession 。
  • SqlSessionFactory ,负责创建 SqlSession 对象的工厂。
  • SqlSessionFactoryBuilder ,是 SqlSessionFactory 的构建器。

下面,我们按照 SqlSessionFactoryBuilder => SqlSessionFactory => SqlSession 来详细解析。

2. SqlSessionFactoryBuilder

org.apache.ibatis.session.SqlSessionFactoryBuilder ,SqlSessionFactory 构造器。代码如下:

// SqlSessionFactory.java

public class SqlSessionFactoryBuilder {

public SqlSessionFactory build(Reader reader) {
return build(reader, null, null);
}

public SqlSessionFactory build(Reader reader, String environment) {
return build(reader, environment, null);
}

public SqlSessionFactory build(Reader reader, Properties properties) {
return build(reader, null, properties);
}

/**
* 构造 SqlSessionFactory 对象
*
* @param reader Reader 对象
* @param environment 环境
* @param properties Properties 变量
* @return SqlSessionFactory 对象
*/
@SuppressWarnings("Duplicates")
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
// 创建 XMLConfigBuilder 对象
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
// 执行 XML 解析
// 创建 DefaultSqlSessionFactory 对象
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
reader.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}

public SqlSessionFactory build(InputStream inputStream) {
return build(inputStream, null, null);
}

public SqlSessionFactory build(InputStream inputStream, String environment) {
return build(inputStream, environment, null);
}

public SqlSessionFactory build(InputStream inputStream, Properties properties) {
return build(inputStream, null, properties);
}

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
// 创建 XMLConfigBuilder 对象
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
// 执行 XML 解析
// 创建 DefaultSqlSessionFactory 对象
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.
}
}
}

/**
* 创建 DefaultSqlSessionFactory 对象
*
* @param config Configuration 对象
* @return DefaultSqlSessionFactory 对象
*/
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}

}
  • 提供了各种 build 的重载方法,核心的套路都是解析出 Configuration 配置对象,从而创建出 DefaultSqlSessionFactory 对象。

3. SqlSessionFactory

org.apache.ibatis.session.SqlSessionFactory ,SqlSession 工厂接口。代码如下:

// SqlSessionFactory.java

public interface SqlSessionFactory {

SqlSession openSession();

SqlSession openSession(boolean autoCommit);

SqlSession openSession(Connection connection);

SqlSession openSession(TransactionIsolationLevel level);

SqlSession openSession(ExecutorType execType);

SqlSession openSession(ExecutorType execType, boolean autoCommit);

SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);

SqlSession openSession(ExecutorType execType, Connection connection);

Configuration getConfiguration();

}
  • 定义了 #openSession(...) 和 #getConfiguration() 两类方法。

3.1 DefaultSqlSessionFactory

org.apache.ibatis.session.defaults.DefaultSqlSessionFactory ,实现 SqlSessionFactory 接口,默认的 SqlSessionFactory 实现类。

3.1.1 构造方法

// DefaultSqlSessionFactory.java

private final Configuration configuration;

public DefaultSqlSessionFactory(Configuration configuration) {
this.configuration = configuration;
}

@Override
public Configuration getConfiguration() {
return configuration;
}

3.1.2 openSession

// DefaultSqlSessionFactory.java

@Override
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}

@Override
public SqlSession openSession(boolean autoCommit) {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, autoCommit);
}

@Override
public SqlSession openSession(ExecutorType execType) {
return openSessionFromDataSource(execType, null, false);
}

@Override
public SqlSession openSession(TransactionIsolationLevel level) {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), level, false);
}

@Override
public SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level) {
return openSessionFromDataSource(execType, level, false);
}

@Override
public SqlSession openSession(ExecutorType execType, boolean autoCommit) {
return openSessionFromDataSource(execType, null, autoCommit);
}

@Override
public SqlSession openSession(Connection connection) {
return openSessionFromConnection(configuration.getDefaultExecutorType(), connection);
}

@Override
public SqlSession openSession(ExecutorType execType, Connection connection) {
return openSessionFromConnection(execType, connection);
}
  • 调用 #openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) 方法,获得 SqlSession 对象。代码如下:

    // DefaultSqlSessionFactory.java

    private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
    // 获得 Environment 对象
    final Environment environment = configuration.getEnvironment();
    // 创建 Transaction 对象
    final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
    tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
    // 创建 Executor 对象
    final Executor executor = configuration.newExecutor(tx, execType);
    // 创建 DefaultSqlSession 对象
    return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
    // 如果发生异常,则关闭 Transaction 对象
    closeTransaction(tx); // may have fetched a connection so lets call close()
    throw ExceptionFactory.wrapException("Error opening session. Cause: " e, e);
    } finally {
    ErrorContext.instance().reset();
    }
    }
    • DefaultSqlSession 的创建,需要 configurationexecutorautoCommit 三个参数。
  • #openSessionFromConnection(ExecutorType execType, Connection connection) 方法,获得 SqlSession 对象。代码如下:

    // DefaultSqlSessionFactory.java

    private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
    try {
    // 获得是否可以自动提交
    boolean autoCommit;
    try {
    autoCommit = connection.getAutoCommit();
    } catch (SQLException e) {
    // Failover to true, as most poor drivers
    // or databases won‘t support transactions
    autoCommit = true;
    }
    // 获得 Environment 对象
    final Environment environment = configuration.getEnvironment();
    // 创建 Transaction 对象
    final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
    final Transaction tx = transactionFactory.newTransaction(connection);
    // 创建 Executor 对象
    final Executor executor = configuration.newExecutor(tx, execType);
    // 创建 DefaultSqlSession 对象
    return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
    throw ExceptionFactory.wrapException("Error opening session. Cause: " e, e);
    } finally {
    ErrorContext.instance().reset();
    }
    }

3.1.3 getTransactionFactoryFromEnvironment

// DefaultSqlSessionFactory.java

private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) {
// 情况一,创建 ManagedTransactionFactory 对象
if (environment == null || environment.getTransactionFactory() == null) {
return new ManagedTransactionFactory();
}
// 情况二,使用 `environment` 中的
return environment.getTransactionFactory();
}

3.1.4 closeTransaction

// DefaultSqlSessionFactory.java

private void closeTransaction(Transaction tx) {
if (tx != null) {
try {
tx.close();
} catch (SQLException ignore) {
// Intentionally ignore. Prefer previous error.
}
}
}

4. SqlSession

org.apache.ibatis.session.SqlSession ,SQL Session 接口。代码如下:

// SqlSession.java

public interface SqlSession extends Closeable {

<T> T selectOne(String statement);
<T> T selectOne(String statement, Object parameter);

<E> List<E> selectList(String statement);
<E> List<E> selectList(String statement, Object parameter);
<E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);

<K, V> Map<K, V> selectMap(String statement, String mapKey);
<K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey);
<K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);

<T> Cursor<T> selectCursor(String statement);
<T> Cursor<T> selectCursor(String statement, Object parameter);
<T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds);

void select(String statement, Object parameter, ResultHandler handler);
void select(String statement, ResultHandler handler);
void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);

int insert(String statement);
int insert(String statement, Object parameter);

int update(String statement);
int update(String statement, Object parameter);

int delete(String statement);
int delete(String statement, Object parameter);

void commit();
void commit(boolean force);
void rollback();
void rollback(boolean force);

List<BatchResult> flushStatements();

@Override
void close();

void clearCache();

Configuration getConfiguration();

/**
* Retrieves a mapper.
* @param <T> the mapper type
* @param type Mapper interface class
* @return a mapper bound to this SqlSession
*/
<T> T getMapper(Class<T> type);

/**
* Retrieves inner database connection
* @return Connection
*/
Connection getConnection();

}
  • 大体接口上,和 Executor 接口是相似的。

4.1 DefaultSqlSession

org.apache.ibatis.session.defaults.DefaultSqlSession ,实现 SqlSession 接口,默认的 SqlSession 实现类。

4.1.1 构造方法

// DefaultSqlSession.java

private final Configuration configuration;
private final Executor executor;

/**
* 是否自动提交事务
*/
private final boolean autoCommit;
/**
* 是否发生数据变更
*/
private boolean dirty;
/**
* Cursor 数组
*/
private List<Cursor<?>> cursorList;

public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
this.configuration = configuration;
this.executor = executor;
this.dirty = false;
this.autoCommit = autoCommit;
}

public DefaultSqlSession(Configuration configuration, Executor executor) {
this(configuration, executor, false);
}

4.1.2 selectList

// DefaultSqlSession.java

@Override
public <E> List<E> selectList(String statement) {
return this.selectList(statement, null);
}

@Override
public <E> List<E> selectList(String statement, Object parameter) {
return this.selectList(statement, parameter, RowBounds.DEFAULT);
}

@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
// <1> 获得 MappedStatement 对象
MappedStatement ms = configuration.getMappedStatement(statement);
// <2> 执行查询
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " e, e);
} finally {
ErrorContext.instance().reset();
}
}
  • <1> 处,调用 Configuration#getMappedStatement(String id) 方法,获得 MappedStatement 对象。代码如下:

    // DefaultSqlSession.java

    /**
    * MappedStatement 映射
    *
    * KEY:`${namespace}.${id}`
    */
    protected final Map<String, MappedStatement> mappedStatements = new StrictMap<>("Mapped Statements collection");

    public MappedStatement getMappedStatement(String id, boolean validateIncompleteStatements) {
    // 校验,保证所有 MappedStatement 已经构造完毕
    if (validateIncompleteStatements) {
    buildAllStatements();
    }
    // 获取 MappedStatement 对象
    return mappedStatements.get(id);
    }

    protected void buildAllStatements() {
    if (!incompleteResultMaps.isEmpty()) {
    synchronized (incompleteResultMaps) { // 保证 incompleteResultMaps 被解析完
    // This always throws a BuilderException.
    incompleteResultMaps.iterator().next().resolve();
    }
    }
    if (!incompleteCacheRefs.isEmpty()) {
    synchronized (incompleteCacheRefs) { // 保证 incompleteCacheRefs 被解析完
    // This always throws a BuilderException.
    incompleteCacheRefs.iterator().next().resolveCacheRef();
    }
    }
    if (!incompleteStatements.isEmpty()) {
    synchronized (incompleteStatements) { // 保证 incompleteStatements 被解析完
    // This always throws a BuilderException.
    incompleteStatements.iterator().next().parseStatementNode();
    }
    }
    if (!incompleteMethods.isEmpty()) {
    synchronized (incompleteMethods) { // 保证 incompleteMethods 被解析完
    // This always throws a BuilderException.
    incompleteMethods.iterator().next().resolve();
    }
    }
    }
    • 其中,#buildAllStatements() 方法,是用来保证所有 MappedStatement 已经构造完毕。不过艿艿,暂时没想到,什么情况下,会出现 MappedStatement 没被正确构建的情况。猜测有可能是防御性编程。
  • <2> 处,调用 Executor#query(...) 方法,执行查询。

4.1.3 selectOne

// DefaultSqlSession.java

@Override
public <T> T selectOne(String statement) {
return this.selectOne(statement, null);
}

@Override
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.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;
}
}
  • 内部调用 #selectList(String statement, Object parameter) 方法,进行实现。

4.1.4 selectMap

#selectMap(...) 方法,查询结果,并基于 Map 聚合结果。代码如下:

// DefaultSqlSession.java

@Override
public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
return this.selectMap(statement, null, mapKey, RowBounds.DEFAULT);
}

@Override
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
return this.selectMap(statement, parameter, mapKey, RowBounds.DEFAULT);
}

@Override
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
// <1> 执行查询
final List<? extends V> list = selectList(statement, parameter, rowBounds);
// <2> 创建 DefaultMapResultHandler 对象
final DefaultMapResultHandler<K, V> mapResultHandler = new DefaultMapResultHandler<>(mapKey,
configuration.getObjectFactory(), configuration.getObjectWrapperFactory(), configuration.getReflectorFactory());
// <3> 创建 DefaultResultContext 对象
final DefaultResultContext<V> context = new DefaultResultContext<>();
// <4> 遍历查询结果
for (V o : list) {
// 设置 DefaultResultContext 中
context.nextResultObject(o);
// 使用 DefaultMapResultHandler 处理结果的当前元素
mapResultHandler.handleResult(context);
}
// <5> 返回结果
return mapResultHandler.getMappedResults();
}
  • <1> 处,调用 #selectList(String statement, Object parameter, RowBounds rowBounds) 方法,执行查询。
  • <2> 处,创建 DefaultMapResultHandler 对象。
  • <3> 处,创建 DefaultResultContext 对象。
  • <4> 处,遍历查询结果,并调用 DefaultMapResultHandler#handleResult(context) 方法,将结果的当前元素,聚合成 Map 。代码如下:

    // DefaultMapResultHandler.java

    public class DefaultMapResultHandler<K, V> implements ResultHandler<V> {

    /**
    * 结果,基于 Map 聚合
    */
    private final Map<K, V> mappedResults;
    /**
    * {@link #mappedResults} 的 KEY 属性名
    */
    private final String mapKey;
    private final ObjectFactory objectFactory;
    private final ObjectWrapperFactory objectWrapperFactory;
    private final ReflectorFactory reflectorFactory;

    @SuppressWarnings("unchecked")
    public DefaultMapResultHandler(String mapKey, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
    this.objectFactory = objectFactory;
    this.objectWrapperFactory = objectWrapperFactory;
    this.reflectorFactory = reflectorFactory;
    // 创建 Map 对象
    this.mappedResults = objectFactory.create(Map.class);
    this.mapKey = mapKey;
    }

    @Override
    public void handleResult(ResultContext<? extends V> context) {
    // 获得 KEY 对应的属性
    final V value = context.getResultObject();
    final MetaObject mo = MetaObject.forObject(value, objectFactory, objectWrapperFactory, reflectorFactory);
    // TODO is that assignment always true?
    final K key = (K) mo.getValue(mapKey);
    // 添加到 mappedResults 中
    mappedResults.put(key, value);
    }

    public Map<K, V> getMappedResults() {
    return mappedResults;
    }

    }
  • <5> 处,返回结果。

4.1.5 selectCursor

// DefaultSqlSession.java

@Override
public <T> Cursor<T> selectCursor(String statement) {
return selectCursor(statement, null);
}

@Override
public <T> Cursor<T> selectCursor(String statement, Object parameter) {
return selectCursor(statement, parameter, RowBounds.DEFAULT);
}

@Override
public <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) {
try {
// <1> 获得 MappedStatement 对象
MappedStatement ms = configuration.getMappedStatement(statement);
// <2> 执行查询
Cursor<T> cursor = executor.queryCursor(ms, wrapCollection(parameter), rowBounds);
// <3> 添加 cursor 到 cursorList 中
registerCursor(cursor);
return cursor;
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " e, e);
} finally {
ErrorContext.instance().reset();
}
}
  • <1> 处,调用 Configuration#getMappedStatement(String id) 方法,获得 MappedStatement 对象。
  • <2> 处,调用 Executor#queryCursor(...) 方法,执行查询。
  • <3> 处,调用 #registerCursor(Cursor<T> cursor) 方法,添加 cursor 到 cursorList 中。代码如下:

    // DefaultSqlSession.java

    private <T> void registerCursor(Cursor<T> cursor) {
    if (cursorList == null) {
    cursorList = new ArrayList<>();
    }
    cursorList.add(cursor);
    }

4.1.6 select

#select(..., ResultHandler handler) 方法,执行查询,使用传入的 handler 方法参数,对结果进行处理。代码如下:

// DefaultSqlSession.java

@Override
public void select(String statement, Object parameter, ResultHandler handler) {
select(statement, parameter, RowBounds.DEFAULT, handler);
}

@Override
public void select(String statement, ResultHandler handler) {
select(statement, null, RowBounds.DEFAULT, handler);
}

@Override
public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
try {
// 获得 MappedStatement 对象
MappedStatement ms = configuration.getMappedStatement(statement);
// 执行查询
executor.query(ms, wrapCollection(parameter), rowBounds, handler);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " e, e);
} finally {
ErrorContext.instance().reset();
}
}

4.1.7 wrapCollection

在上述的查询方法中,我们都可以看到一个 #wrapCollection(final Object object) 方法,若参数 object 是 Collection、Array、Map 参数类型的情况下,包装成 Map 返回。代码如下:

// DefaultSqlSession.java

private Object wrapCollection(final Object object) {
if (object instanceof Collection) {
// 如果是集合,则添加到 collection 中
StrictMap<Object> map = new StrictMap<>();
map.put("collection", object);
// 如果是 List ,则添加到 list 中
if (object instanceof List) {
map.put("list", object);
}
return map;
} else if (object != null && object.getClass().isArray()) {
// 如果是 Array ,则添加到 array 中
StrictMap<Object> map = new StrictMap<>();
map.put("array", object);
return map;
}
return object;
}

4.1.8 update

// DefaultSqlSession.java

@Override
public int update(String statement) {
return update(statement, null);
}

@Override
public int update(String statement, Object parameter) {
try {
// <1> 标记 dirty ,表示执行过写操作
dirty = true;
// <2> 获得 MappedStatement 对象
MappedStatement ms = configuration.getMappedStatement(statement);
// <3> 执行更新操作
return executor.update(ms, wrapCollection(parameter));
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error updating database. Cause: " e, e);
} finally {
ErrorContext.instance().reset();
}
}
  • <1> 处,标记 dirty ,表示执行过写操作。该参数,会在事务的提交和回滚,产生其用途。
  • <2> 处,获得 MappedStatement 对象。
  • <3> 处,调用 Executor#update(MappedStatement ms, Object parameter) 方法,执行更新操作。

4.1.9 insert

// DefaultSqlSession.java

@Override
public int insert(String statement) {
return insert(statement, null);
}

@Override
public int insert(String statement, Object parameter) {
return update(statement, parameter);
}
  • 基于 #update(...) 方法来实现。

4.1.10 delete

// DefaultSqlSession.java

@Override
public int delete(String statement) {
return update(statement, null);
}

@Override
public int delete(String statement, Object parameter) {
return update(statement, parameter);
}
  • 基于 #update(...) 方法来实现。

4.1.11 flushStatements

#flushStatements() 方法,提交批处理。代码如下:

// DefaultSqlSession.java

@Override
public List<BatchResult> flushStatements() {
try {
return executor.flushStatements();
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error flushing statements. Cause: " e, e);
} finally {
ErrorContext.instance().reset();
}
}

4.1.12 commit

// DefaultSqlSession.java

@Override
public void commit() {
commit(false);
}

@Override
public void commit(boolean force) {
try {
// 提交事务
executor.commit(isCommitOrRollbackRequired(force));
// 标记 dirty 为 false
dirty = false;
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error committing transaction. Cause: " e, e);
} finally {
ErrorContext.instance().reset();
}
}
  • 其中,#isCommitOrRollbackRequired(boolean force) 方法,判断是否执行提交或回滚。代码如下:

    // DefaultSqlSession.java

    private boolean isCommitOrRollbackRequired(boolean force) {
    return (!autoCommit && dirty) || force;
    }
    • 有两种情况需要触发:
    • 1)未开启自动提交,并且数据发生写操作
    • 2)强制提交

4.1.13 rollback

// DefaultSqlSession.java

@Override
public void rollback() {
rollback(false);
}

@Override
public void rollback(boolean force) {
try {
// 回滚事务
executor.rollback(isCommitOrRollbackRequired(force));
// 标记 dirty 为 false
dirty = false;
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error rolling back transaction. Cause: " e, e);
} finally {
ErrorContext.instance().reset();
}
}

4.1.14 close

#close() 方法,关闭会话。代码如下:

// DefaultSqlSession.java

@Override
public void close() {
try {
// <1> 关闭执行器
executor.close(isCommitOrRollbackRequired(false));
// <2> 关闭所有游标
closeCursors();
// <3> 重置 dirty 为 false
dirty = false;
} finally {
ErrorContext.instance().reset();
}
}
  • <1> 处,调用 Executor#close(boolean forceRollback) 方法,关闭执行器。并且,根据 forceRollback 参数,是否进行事务回滚。
  • <2> 处,调用 #closeCursors() 方法,关闭所有游标。代码如下:

    // DefaultSqlSession.java

    private void closeCursors() {
    if (cursorList != null && cursorList.size() != 0) {
    for (Cursor<?> cursor : cursorList) {
    try {
    cursor.close();
    } catch (IOException e) {
    throw ExceptionFactory.wrapException("Error closing cursor. Cause: " e, e);
    }
    }
    cursorList.clear();
    }
    }
  • <3> 处,重置 dirty 为 false 。

4.1.15 getConfiguration

// DefaultSqlSession.java

@Override
public Configuration getConfiguration() {
return configuration;
}

4.1.16 getMapper

// DefaultSqlSession.java

@Override
public <T> T getMapper(Class<T> type) {
return configuration.getMapper(type, this);
}

4.1.17 getConnection

// DefaultSqlSession.java

@Override
public Connection getConnection() {
try {
return executor.getTransaction().getConnection();
} catch (SQLException e) {
throw ExceptionFactory.wrapException("Error getting a new connection. Cause: " e, e);
}
}

4.1.18 clearCache

// DefaultSqlSession.java

@Override
public void clearCache() {
executor.clearLocalCache();
}

5. SqlSessionManager

org.apache.ibatis.session.SqlSessionManager ,实现 SqlSessionFactory、SqlSession 接口,SqlSession 管理器。所以,从这里已经可以看出,SqlSessionManager 是 SqlSessionFactory 和 SqlSession 的职能相加。

5.1 构造方法

// SqlSessionManager.java

private final SqlSessionFactory sqlSessionFactory;
private final SqlSession sqlSessionProxy;

/**
* 线程变量,当前线程的 SqlSession 对象
*/
private final ThreadLocal<SqlSession> localSqlSession = new ThreadLocal<>(); // <1>

private SqlSessionManager(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
// <2> 创建 SqlSession 的代理对象
this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(
SqlSessionFactory.class.getClassLoader(),
new Class[]{SqlSession.class},
new SqlSessionInterceptor());
}
  • 比较有意思的有两点,我们逐条来看。
  • <1> 处,localSqlSession 属性,线程变量,记录当前线程的 SqlSession 对象。
  • <2> 处,创建 SqlSession 的代理对象,而方法的拦截器是 SqlSessionInterceptor 类。详细解析,见 「5.6 SqlSessionInterceptor」 。

5.2 newInstance

#newInstance(...) 静态方法,创建 SqlSessionManager 对象。代码如下:

// SqlSessionManager.java

public static SqlSessionManager newInstance(Reader reader) {
return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, null, null));
}

public static SqlSessionManager newInstance(Reader reader, String environment) {
return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, environment, null));
}

public static SqlSessionManager newInstance(Reader reader, Properties properties) {
return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, null, properties));
}

public static SqlSessionManager newInstance(InputStream inputStream) {
return new SqlSessionManager(new SqlSessionFactoryBuilder().build(inputStream, null, null));
}

public static SqlSessionManager newInstance(InputStream inputStream, String environment) {
return new SqlSessionManager(new SqlSessionFactoryBuilder().build(inputStream, environment, null));
}

public static SqlSessionManager newInstance(InputStream inputStream, Properties properties) {
return new SqlSessionManager(new SqlSessionFactoryBuilder().build(inputStream, null, properties));
}

public static SqlSessionManager newInstance(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionManager(sqlSessionFactory);
}
  • 代码比较简单,胖友自己瞅瞅。

5.3 startManagedSession

#startManagedSession(...) 方法,发起一个可被管理的 SqlSession 。代码如下:

// SqlSessionManager.java

public void startManagedSession() {
this.localSqlSession.set(openSession());
}

public void startManagedSession(boolean autoCommit) {
this.localSqlSession.set(openSession(autoCommit));
}

public void startManagedSession(Connection connection) {
this.localSqlSession.set(openSession(connection));
}

public void startManagedSession(TransactionIsolationLevel level) {
this.localSqlSession.set(openSession(level));
}

public void startManagedSession(ExecutorType execType) {
this.localSqlSession.set(openSession(execType));
}

public void startManagedSession(ExecutorType execType, boolean autoCommit) {
this.localSqlSession.set(openSession(execType, autoCommit));
}

public void startManagedSession(ExecutorType execType, TransactionIsolationLevel level) {
this.localSqlSession.set(openSession(execType, level));
}

public void startManagedSession(ExecutorType execType, Connection connection) {
this.localSqlSession.set(openSession(execType, connection));
}
  • 可能胖友很难理解“可被管理”的 SqlSession 的意思?继续往下看。

5.4 对 SqlSessionFactory 的实现方法

// SqlSessionManager.java

@Override
public SqlSession openSession() {
return sqlSessionFactory.openSession();
}

@Override
public SqlSession openSession(boolean autoCommit) {
return sqlSessionFactory.openSession(autoCommit);
}

@Override
public SqlSession openSession(Connection connection) {
return sqlSessionFactory.openSession(connection);
}

@Override
public SqlSession openSession(TransactionIsolationLevel level) {
return sqlSessionFactory.openSession(level);
}

@Override
public SqlSession openSession(ExecutorType execType) {
return sqlSessionFactory.openSession(execType);
}

@Override
public SqlSession openSession(ExecutorType execType, boolean autoCommit) {
return sqlSessionFactory.openSession(execType, autoCommit);
}

@Override
public SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level) {
return sqlSessionFactory.openSession(execType, level);
}

@Override
public SqlSession openSession(ExecutorType execType, Connection connection) {
return sqlSessionFactory.openSession(execType, connection);
}
  • 直接调用 sqlSessionFactory 对应的方法即可。

5.5 对 SqlSession 的实现方法

// SqlSessionManager.java

@Override
public <T> T selectOne(String statement) {
return sqlSessionProxy.selectOne(statement);
}

@Override
public <T> T selectOne(String statement, Object parameter) {
return sqlSessionProxy.selectOne(statement, parameter);
}

@Override
public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
return sqlSessionProxy.selectMap(statement, mapKey);
}

@Override
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
return sqlSessionProxy.selectMap(statement, parameter, mapKey);
}

@Override
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
return sqlSessionProxy.selectMap(statement, parameter, mapKey, rowBounds);
}

@Override
public <T> Cursor<T> selectCursor(String statement) {
return sqlSessionProxy.selectCursor(statement);
}

@Override
public <T> Cursor<T> selectCursor(String statement, Object parameter) {
return sqlSessionProxy.selectCursor(statement, parameter);
}

@Override
public <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) {
return sqlSessionProxy.selectCursor(statement, parameter, rowBounds);
}

@Override
public <E> List<E> selectList(String statement) {
return sqlSessionProxy.selectList(statement);
}

@Override
public <E> List<E> selectList(String statement, Object parameter) {
return sqlSessionProxy.selectList(statement, parameter);
}

@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
return sqlSessionProxy.selectList(statement, parameter, rowBounds);
}

@Override
public void select(String statement, ResultHandler handler) {
sqlSessionProxy.select(statement, handler);
}

@Override
public void select(String statement, Object parameter, ResultHandler handler) {
sqlSessionProxy.select(statement, parameter, handler);
}

@Override
public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
sqlSessionProxy.select(statement, parameter, rowBounds, handler);
}

@Override
public int insert(String statement) {
return sqlSessionProxy.insert(statement);
}

@Override
public int insert(String statement, Object parameter) {
return sqlSessionProxy.insert(statement, parameter);
}

@Override
public int update(String statement) {
return sqlSessionProxy.update(statement);
}

@Override
public int update(String statement, Object parameter) {
return sqlSessionProxy.update(statement, parameter);
}

@Override
public int delete(String statement) {
return sqlSessionProxy.delete(statement);
}

@Override
public int delete(String statement, Object parameter) {
return sqlSessionProxy.delete(statement, parameter);
}

@Override
public <T> T getMapper(Class<T> type) {
return getConfiguration().getMapper(type, this);
}

@Override
public Connection

相关文章