前言
上一章节我们学习了SqlSessionFactory的源码,SqlSessionFactory中的方法都是围绕着SqlSession来的.,那么SqlSession又是什么东东呢?这一章节我们就来揭开它的真面目吧!
1. SqlSession源码详解
SqlSession是一个接口类,文档上注明它是mybatis的一个主要的java 接口.官方都说很重要了,那肯定是非常重要.它的主要功能是执行命令,获取mapper和管理事务.
SqlSession有两个实现类,分别是DefaultSqlSession和SqlSessionManager,上一章节也出现过SqlSessionManager,大家还记得吗?SqlSessionManager既实现了SqlSession也实现了SqlSessionFactory.话不多说,详细学习以下两个类的源码吧!
2. DefaultSqlSession源码详解
2.1DefaultSqlSession源码
public class DefaultSqlSession implements SqlSession {
/**
* 全局配置对象
*/
private final Configuration configuration;
/**
* sql执行器
*/
private final Executor executor;
/**
* 是否自动提交
*/
private final boolean autoCommit;
/**
* 是否脏数据
*/
private boolean dirty;
/**
* 游标列表
*/
private List<Cursor<?>> cursorList;
/**构造函数
* @param configuration 核心配置对象
* @param executor sql执行器
* @param autoCommit 是否自动提交
*/
public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
this.configuration = configuration;
this.executor = executor;
this.dirty = false;
this.autoCommit = autoCommit;
}
/**构造函数
* @param configuration 核心配置对象
* @param executor sql执行器
*/
public DefaultSqlSession(Configuration configuration, Executor executor) {
this(configuration, executor, false);
}
/**查询单条数据并返回对象
* @param statement the statement
* @param <T> 返回对象类型
* @return 对象
*/
@Override
public <T> T selectOne(String statement) {
return this.selectOne(statement, null);
}
/**查询单条数据并返回对象
* @param statement the statement
* @param parameter sql语句参数
* @param <T> 返回对象类型
* @return 对象
*/
@Override
public <T> T selectOne(String statement, Object parameter) {
// Popular vote was to return null on 0 results and throw exception on too many.
//调用selectList
List<T> list = this.selectList(statement, parameter);
if (list.size() == 1) {
//结果为1条数据时,返回第0条
return list.get(0);
} else if (list.size() > 1) {
//结果数大于1时,抛出异常
throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
} else {
//返回null
return null;
}
}
/**map查询
* @param statement Unique identifier matching the statement to use.
* @param mapKey The property to use as key for each value in the list.
* @param <K> 返回的map的key的泛型
* @param <V> 返回的map的值的泛型
* @return 返回map<K,V>
*/
@Override
public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
//调用selectMap
return this.selectMap(statement, null, mapKey, RowBounds.DEFAULT);
}
/**map查询
* @param statement Unique identifier matching the statement to use.
* @param parameter A parameter object to pass to the statement.
* @param mapKey The property to use as key for each value in the list.
* @param <K> 返回的map的key的泛型
* @param <V> 返回的map的值的泛型
* @return 返回map<K,V>
*/
@Override
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
//调用selectMap
return this.selectMap(statement, parameter, mapKey, RowBounds.DEFAULT);
}
/**map查询
* @param statement Unique identifier matching the statement to use.
* @param parameter A parameter object to pass to the statement.
* @param mapKey The property to use as key for each value in the list.
* @param rowBounds Bounds to limit object retrieval
* @param <K> 返回的map的key的泛型
* @param <V> 返回的map的值的泛型
* @return 返回map<K,V>
*/
@Override
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
//调用selectList获取结果
final List<? extends V> list = selectList(statement, parameter, rowBounds);
//初始化一个默认的Map结果处理器
final DefaultMapResultHandler<K, V> mapResultHandler = new DefaultMapResultHandler<>(mapKey,
configuration.getObjectFactory(), configuration.getObjectWrapperFactory(), configuration.getReflectorFactory());
//初始化一个默认的结果上下文对象
final DefaultResultContext<V> context = new DefaultResultContext<>();
for (V o : list) {
//遍历结果列表,放入context中
context.nextResultObject(o);
//使用Map结果处理器处理上下文
mapResultHandler.handleResult(context);
}
//从结果处理器中获取处理完的map<K,V>返回
return mapResultHandler.getMappedResults();
}
/**游标查询
* @param statement Unique identifier matching the statement to use.
* @param <T> 返回对象类型
* @return 对象
*/
@Override
public <T> Cursor<T> selectCursor(String statement) {
return selectCursor(statement, null);
}
/**游标查询
* @param statement Unique identifier matching the statement to use.
* @param parameter A parameter object to pass to the statement.
* @param <T> 返回对象类型
* @return 对象
*/
@Override
public <T> Cursor<T> selectCursor(String statement, Object parameter) {
return selectCursor(statement, parameter, RowBounds.DEFAULT);
}
/**游标查询
* @param statement Unique identifier matching the statement to use.
* @param parameter A parameter object to pass to the statement.
* @param rowBounds Bounds to limit object retrieval
* @param <T> 返回对象类型
* @return 对象
*/
@Override
public <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) {
try {
//使用全局配置对象中的mappedStatements获取MappedStatement对象
MappedStatement ms = configuration.getMappedStatement(statement);
//调用sql处理器查询
Cursor<T> cursor = executor.queryCursor(ms, wrapCollection(parameter), rowBounds);
//把游标注册到游标列表中,方便后续统一管理游标
registerCursor(cursor);
return cursor;
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
/**查询列表
* @param statement Unique identifier matching the statement to use.
* @param <E> 结果的泛型
* @return 结果列表
*/
@Override
public <E> List<E> selectList(String statement) {
return this.selectList(statement, null);
}
/**查询列表
* @param statement Unique identifier matching the statement to use.
* @param parameter A parameter object to pass to the statement.
* @param <E> 结果的泛型
* @return 结果列表
*/
@Override
public <E> List<E> selectList(String statement, Object parameter) {
//调用selectList
return this.selectList(statement, parameter, RowBounds.DEFAULT);
}
/**查询列表
* @param statement Unique identifier matching the statement to use.
* @param parameter A parameter object to pass to the statement.
* @param rowBounds Bounds to limit object retrieval
* @param <E> 结果的泛型
* @return 结果列表
*/
@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
//使用全局配置对象中的mappedStatements获取MappedStatement对象
MappedStatement ms = configuration.getMappedStatement(statement);
//调用sql处理器查询
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();
}
}
/**带结果处理器的查询
* @param statement Unique identifier matching the statement to use.
* @param parameter A parameter object to pass to the statement.
* @param handler ResultHandler that will handle each retrieved row
*/
@Override
public void select(String statement, Object parameter, ResultHandler handler) {
//调用select
select(statement, parameter, RowBounds.DEFAULT, handler);
}
/**带结果处理器的查询
* @param statement Unique identifier matching the statement to use.
* @param handler ResultHandler that will handle each retrieved row
*/
@Override
public void select(String statement, ResultHandler handler) {
select(statement, null, RowBounds.DEFAULT, handler);
}
/**带结果处理器的查询
* @param statement Unique identifier matching the statement to use.
* @param parameter the parameter
* @param rowBounds RowBound instance to limit the query results
* @param handler
*/
@Override
public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
try {
//使用全局配置对象中的mappedStatements获取MappedStatement对象
MappedStatement ms = configuration.getMappedStatement(statement);
//调用sql处理器查询
executor.query(ms, wrapCollection(parameter), rowBounds, handler);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
/**插入数据
* @param statement Unique identifier matching the statement to execute.
* @return 影响的行数
*/
@Override
public int insert(String statement) {
//调用insert
return insert(statement, null);
}
/**插入数据
* @param statement Unique identifier matching the statement to execute.
* @param parameter A parameter object to pass to the statement.
* @return 影响的行数
*/
@Override
public int insert(String statement, Object parameter) {
//调用update
return update(statement, parameter);
}
/**更新数据
* @param statement Unique identifier matching the statement to execute.
* @return 影响的行数
*/
@Override
public int update(String statement) {
//调用update
return update(statement, null);
}
/**更新数据
* @param statement Unique identifier matching the statement to execute.
* @param parameter A parameter object to pass to the statement.
* @return 影响的行数
*/
@Override
public int update(String statement, Object parameter) {
try {
//设置脏数据状态为true
dirty = true;
//使用全局配置对象中的mappedStatements获取MappedStatement对象
MappedStatement ms = configuration.getMappedStatement(statement);
//调用sql处理器更新
return executor.update(ms, wrapCollection(parameter));
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error updating database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
/**删除数据
* @param statement Unique identifier matching the statement to execute.
* @return 影响的行数
*/
@Override
public int delete(String statement) {
//调用update
return update(statement, null);
}
/**删除数据
* @param statement Unique identifier matching the statement to execute.
* @param parameter A parameter object to pass to the statement.
* @return 影响的行数
*/
@Override
public int delete(String statement, Object parameter) {
//调用更新
return update(statement, parameter);
}
/**
* 提交事务
*/
@Override
public void commit() {
commit(false);
}
/**提交事务
* @param force 是否强制提交
*/
@Override
public void commit(boolean force) {
try {
//调用执行器提交事务
executor.commit(isCommitOrRollbackRequired(force));
//设置脏数据状态为false
dirty = false;
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error committing transaction. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
/**
* 回滚事务
*/
@Override
public void rollback() {
rollback(false);
}
/**回滚事务
* @param force forces connection rollback
*/
@Override
public void rollback(boolean force) {
try {
//调用执行器回滚事务
executor.rollback(isCommitOrRollbackRequired(force));
//设置脏数据状态为false
dirty = false;
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error rolling back transaction. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
/**批量处理
* @return 返回批量处理的结果
*/
@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();
}
}
/**
* 关闭sqlsession
*/
@Override
public void close() {
try {
//调用执行器进行关闭
executor.close(isCommitOrRollbackRequired(false));
//关闭所有游标
closeCursors();
//设置脏数据状态为false
dirty = false;
} finally {
ErrorContext.instance().reset();
}
}
/**
* 关闭全部游标
*/
private void closeCursors() {
if (cursorList != null && !cursorList.isEmpty()) {
for (Cursor<?> cursor : cursorList) {
//遍历游标列表,进行关闭操作
try {
cursor.close();
} catch (IOException e) {
throw ExceptionFactory.wrapException("Error closing cursor. Cause: " + e, e);
}
}
//清空游标
cursorList.clear();
}
}
/**获取全局配置对象
* @return 全局配置对象
*/
@Override
public Configuration getConfiguration() {
return configuration;
}
/**获取Mapper<T>的动态代理类
* @param type Mapper interface class
* @param <T> 返回对象的泛型
* @return Mapper接口的动态代理类
*/
@Override
public <T> T getMapper(Class<T> type) {
//从核心配置对象中获取mapper, 实际是从mapperRegistry中获取mapper接口的代理工厂,使用代理工厂创建的动态代理类
return configuration.getMapper(type, this);
}
/**获取数据库连接
* @return 数据库连接
*/
@Override
public Connection getConnection() {
try {
//调用执行器获取连接
return executor.getTransaction().getConnection();
} catch (SQLException e) {
throw ExceptionFactory.wrapException("Error getting a new connection. Cause: " + e, e);
}
}
/**
* 清除缓存
*/
@Override
public void clearCache() {
//调用执行器清除本地缓存
executor.clearLocalCache();
}
/**注册游标
* @param cursor 游标对象
* @param <T> 泛型
*/
private <T> void registerCursor(Cursor<T> cursor) {
if (cursorList == null) {
cursorList = new ArrayList<>();
}
//把游标加入到cursorList
cursorList.add(cursor);
}
/**判断是否需求提交或者回滚
* @param force 是否强制提交或回滚
* @return 是否需求提交或者回滚
*/
private boolean isCommitOrRollbackRequired(boolean force) {
//如果不是自动提交并且有脏数据返回true
//如果强制提交或回滚返回true
return (!autoCommit && dirty) || force;
}
/**将Collection或者数组类型的参数转换成Map
* @param object 参数对象
* @return 包装后的对象
*/
private Object wrapCollection(final Object object) {
return ParamNameResolver.wrapToMapIfCollection(object, null);
}
/**
* @deprecated Since 3.5.5
*/
@Deprecated
public static class StrictMap<V> extends HashMap<String, V> {
private static final long serialVersionUID = -5741767162221585340L;
@Override
public V get(Object key) {
if (!super.containsKey(key)) {
throw new BindingException("Parameter '" + key + "' not found. Available parameters are " + this.keySet());
}
return super.get(key);
}
}
}
DefaultSqlSession的方法分类
1.selectOne(),selectMap(),selectList()为一类,它们的实现都是通过selectList()得到的结构进行处理的
2.selectCursor()
3.select()
4.insert(),update(),delete()为一类,它们的实现都是通过update()
5.实现的事务相关的和其他方法
2.2 configuration.getMappedStatement(statement)
configuration的内部是维护了一个Map<String, MappedStatement> mappedStatements
在获取之前如果还有未完成的Statements,会先执行buildAllStatements()
public MappedStatement getMappedStatement(String id, boolean validateIncompleteStatements) {
if (validateIncompleteStatements) {
buildAllStatements();
}
return mappedStatements.get(id);
}
那这个Map是什么时候插入值的呢,我们进行代码的跟踪,有没有很眼熟,是上一章的最后一节我们说到的解析所有的Mapper配置
在解析的过程里,会把MappedStatement的id属性作为key,MappedStatement作为值放入到mappedStatements中
ps: 查看调用关系快捷键 Ctrl + Alt + H
2.3 Executor
我们通过调用栈来看下Executor到底是什么时候进行初始化的呢
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);
//通过configuration创建一个Executor
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 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;
}
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
final Transaction tx = transactionFactory.newTransaction(connection);
//通过configuration创建一个Executor
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
public Executor newExecutor(Transaction transaction, ExecutorType executorType)代码
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
//为空返回默认的executorType ExecutorType.SIMPLE
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor 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;
}
interceptorChain.pluginAll(executor)
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
interceptor.plugin(target)
default Object plugin(Object target) {
return Plugin.wrap(target, this);
}
Plugin.wrap(target, this)
public static Object wrap(Object target, Interceptor interceptor) {
//获取当前的interceptor上的注解中定义的Signature[],把需要代理的类和方法放入Map中
Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
Class<?> type = target.getClass();
//匹配当前类有没有需要被代理的接口,有则返回代理对象,无返回原对象
Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
if (interfaces.length > 0) {
return Proxy.newProxyInstance(
type.getClassLoader(),
interfaces,
new Plugin(target, interceptor, signatureMap));
}
return target;
}
MyInterceptor和PageInterceptor类上的@Intercepts注解
此处定义的都是对Executor类的下面两个方法进行代理
query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql)
query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler)
最后代理两次后返回的Executor类
3. SqlSessionManager源码详解
3.1 私有的构造方法
//内部的SqlSessionFactory,为实现SqlSessionFactory相关接口而使用
private final SqlSessionFactory sqlSessionFactory;
//内部的SqlSession代理类,为实现SqlSession相关接口而使用
private final SqlSession sqlSessionProxy;
//ThreadLocal<SqlSession> 事务相关等方法操作是使用
private final ThreadLocal<SqlSession> localSqlSession = new ThreadLocal<>();
//私有构造函数
private SqlSessionManager(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(
SqlSessionFactory.class.getClassLoader(),
new Class[]{SqlSession.class},
new SqlSessionInterceptor());
}
3.2 SqlSession的代理类SqlSessionInterceptor
private class SqlSessionInterceptor implements InvocationHandler {
public SqlSessionInterceptor() {
// Prevent Synthetic Access
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//从LocalThread中获取SqlSession
final SqlSession sqlSession = SqlSessionManager.this.localSqlSession.get();
if (sqlSession != null) {
//LocalThread中有SqlSession,则使用
try {
return method.invoke(sqlSession, args);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
} else {
//LocalThread中无SqlSession,获取一个SqlSession
try (SqlSession autoSqlSession = openSession()) {
try {
final Object result = method.invoke(autoSqlSession, args);
//手动提交
autoSqlSession.commit();
return result;
} catch (Throwable t) {
//手动回滚
autoSqlSession.rollback();
throw ExceptionUtil.unwrapThrowable(t);
}
}
}
}
}
3.3 其他事务等方法
以下方法都是通过LocalThread中的SqlSession进行操作的
@Override
public void clearCache() {
final SqlSession sqlSession = localSqlSession.get();
if (sqlSession == null) {
throw new SqlSessionException("Error: Cannot clear the cache. No managed session is started.");
}
sqlSession.clearCache();
}
@Override
public void commit() {
final SqlSession sqlSession = localSqlSession.get();
if (sqlSession == null) {
throw new SqlSessionException("Error: Cannot commit. No managed session is started.");
}
sqlSession.commit();
}
@Override
public void commit(boolean force) {
final SqlSession sqlSession = localSqlSession.get();
if (sqlSession == null) {
throw new SqlSessionException("Error: Cannot commit. No managed session is started.");
}
sqlSession.commit(force);
}
@Override
public void rollback() {
final SqlSession sqlSession = localSqlSession.get();
if (sqlSession == null) {
throw new SqlSessionException("Error: Cannot rollback. No managed session is started.");
}
sqlSession.rollback();
}
@Override
public void rollback(boolean force) {
final SqlSession sqlSession = localSqlSession.get();
if (sqlSession == null) {
throw new SqlSessionException("Error: Cannot rollback. No managed session is started.");
}
sqlSession.rollback(force);
}
@Override
public List<BatchResult> flushStatements() {
final SqlSession sqlSession = localSqlSession.get();
if (sqlSession == null) {
throw new SqlSessionException("Error: Cannot rollback. No managed session is started.");
}
return sqlSession.flushStatements();
}
@Override
public void close() {
final SqlSession sqlSession = localSqlSession.get();
if (sqlSession == null) {
throw new SqlSessionException("Error: Cannot close. No managed session is started.");
}
try {
sqlSession.close();
} finally {
localSqlSession.set(null);
}
}
总结
SqlSession的两个实现类DefaultSqlSession和SqlSessionManager.SqlSessionManager是通过DefaultSqlSession实现功能的.而DefaultSqlSession是通过内部的Executor实现的.后续章节我们再对Executor相关的代码进行详细的学习
喜欢的小伙伴请动动小手关注和点赞吧,也可留言一起探讨怎样更好的学习源码!!!
文章链接
Mybatis源码学习(一)初探执行流程
Mybatis源码学习(二)配置文件解析到SqlSessionFactory构建
Mybatis源码学习(三)SqlSession详解
Mybatis源码学习(四)自定义Mapper方法执行流程
Mybatis源码学习(五)Executor和StatementHandler详解
Mybatis源码学习(六)结果集自动封装机制
Mybatis源码学习(七)mybatis缓存详解
Mybatis源码学习(八)Mybatis设计模式总结
学习资料整理
本人作为Java开发菜鸡,平时也收集了很多学习视频,在此分享给大家一起学习
整套VIP学习视频
架构师相关视频
扫码领取
更多资料链接
Java免费学习视频下载
Python免费学习视频下载
Web前端免费学习视频下载
人工智能免费学习视频下载
大数据免费学习视频下载
UI设计免费学习视频下载