共计 5387 个字符,预计需要花费 14 分钟才能阅读完成。
这篇文章主要介绍“如何理解 SqlSession 技术”,在日常操作中,相信很多人在如何理解 SqlSession 技术问题上存在疑惑,丸趣 TV 小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何理解 SqlSession 技术”的疑惑有所帮助!接下来,请跟着丸趣 TV 小编一起来学习吧!
老规矩,先上案例代码,我们按照这个案例一步一步的搞定 Mybatis 源码。
public class MybatisApplication { public static final String URL = jdbc:mysql://localhost:3306/mblog public static final String USER = root public static final String PASSWORD = 123456 public static void main(String[] args) { String resource = mybatis-config.xml InputStream inputStream = null; SqlSession sqlSession = null; try { inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); sqlSession = sqlSessionFactory.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); System.out.println(userMapper.selectById(1)); } catch (Exception e) { e.printStackTrace(); } finally { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } sqlSession.close(); } }
由于很多小伙伴在催,说 Mybatis 源码系列好像何时才有下文了,为此老田熬夜写了这篇。
继续开撸~~
SqlSession sqlSession = sqlSessionFactory.openSession();
前面那篇文章已经分析了,这里的 sqlSessionFactory 其实就是 DefaultSqlSessionFactory。
所以这里,我们就从 DefaultSqlSessionFactory 里的 openSession 方法开始。
public class DefaultSqlSessionFactory implements SqlSessionFactory { private final Configuration configuration; public DefaultSqlSessionFactory(Configuration configuration) { this.configuration = configuration; } // 创建 session,这个方法直接调用本类中的另外一个方法 @Override public SqlSession openSession() { return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false); } // 其实是调用这个方法 private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; try { // 对应 xml 标签 environments , 这个在配置文件解析的时候就已经存放到 configuration 中了。 final Environment environment = configuration.getEnvironment(); final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); // 创建一个 executor 来执行 SQL final Executor executor = configuration.newExecutor(tx, execType); // 这里也说明了,为什么我们代码里的 SqlSession 是 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(); } } private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) { if (environment == null || environment.getTransactionFactory() == null) { return new ManagedTransactionFactory(); } return environment.getTransactionFactory(); }
这个方法中的主要内容有:
下面我们就来逐个攻破。
创建事务 Transaction
事务工厂类型可以配置为 JDBC 类型或者 MANAGED 类型。
JdbcTransactionFactory 生产 JdbcTransaction。
ManagedTransactionFactory 生产 ManagedTransaction。
如果配置的 JDBC,则会使用 Connection 对象的 commit()、rollback()、close() 方法来管理事务。
如果我们配置的是 MANAGED,会把事务交给容器来管理,比如 JBOSS,Weblogic。因为我们是本地跑的程序,如果配置成 MANAGED 就会不有任何事务。
但是,如果我们项目中是 Spring 集成 Mybatis,则没有必要配置事务,因为我们会直接在 applicationContext.xml 里配置数据源和事务管理器,从而覆盖 Mybatis 的配置。
创建执行器 Executor
调用 configuration 的 newExecutor 方法创建 Executor。
final Executor executor = configuration.newExecutor(tx, execType); //Configuration 中 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 的基本类型有三种:
public enum ExecutorType { SIMPLE, REUSE, BATCH }
SIMPLE 为默认类型。
为什么要让抽象类 BaseExecutor 实现 Executor 接口,然后让具体实现类继承抽象类呢?
这就是模板方法模式的实现。
模板方法模式就是定义一个算法骨架,并允许子类为一个或者多个步骤提供实现。模板方法是得子类可以再不改变算法结构的情况下,重新定义算法的某些步骤。
抽象方法是在子类汇总实现的,每种执行器自己实现自己的逻辑,BaseExecutor 最终会调用到具体的子类中。
抽象方法
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 abstract E Cursor E doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException;
第二步:缓存装饰
在上面代码中的第二步
if (cacheEnabled) { executor = new CachingExecutor(executor); }
如果 cacheEnabled=true,会用装饰器设计模式对 Executor 进行装饰。
第三步:插件代理缓存装饰完后,就会执行
executor = (Executor) interceptorChain.pluginAll(executor);
这里会对 Executor 植入插件逻辑。
比如:分页插件中就需要把插件植入的 Executor
好了,到此,执行器创建的就搞定了。
创建 DefaultSqlSession 对象
把前面解析配置文件创建的 Configuration 对象和创建的执行器 Executor 赋给 DefaultSqlSession 中的属性。
public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) { this.configuration = configuration; this.executor = executor; this.dirty = false; this.autoCommit = autoCommit; }
到这里,SqlSession(DefaultSqlSession) 对象就创建完毕。
到此,关于“如何理解 SqlSession 技术”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注丸趣 TV 网站,丸趣 TV 小编会继续努力为大家带来更多实用的文章!