欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

Mybatis源码分析(三)Executor&缓存

时间:2023-07-01

Executor 执行器使用
配置

使用

String resource = "mybatis-config.xml";//将XML配置文件构建为Configuration配置类Reader reader = Resources.getResourceAsReader(resource);// 通过加载配置文件流构建一个SqlSessionFactory 解析xml文件SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);Configuration configuration = sqlSessionFactory.getConfiguration();Connection connection = configuration.getEnvironment().getDataSource().getConnection();Transaction transaction = configuration.getEnvironment().getTransactionFactory().newTransaction(connection);SimpleExecutor simpleExecutor = new SimpleExecutor(configuration, transaction);//ReuseExecutor executor = new ReuseExecutor(configuration, transaction);MappedStatement mappedStatement = configuration.getMappedStatement("com.mx.mapper.UserMapper.selectById");List list = simpleExecutor.doQuery(mappedStatement, 1, RowBounds.DEFAULT, SimpleExecutor.NO_RESULT_HANDLER, mappedStatement.getBoundSql(1));list = simpleExecutor.doQuery(mappedStatement, 1, RowBounds.DEFAULT, SimpleExecutor.NO_RESULT_HANDLER, mappedStatement.getBoundSql(1));System.out.println(list.get(0));


Executor

baseExecutor(一级缓存)batchExecutor(批量执行器)ReUseExecutor(可重用的)SimpleExecutor简单的CacheExecutor(加入了二级缓存)

源码 DefaultSqlSession.openSession() 数据源 执行器
SqlSession session = sqlSessionFactory.openSession();

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(); } }

创建一个sql执行器

默认 ExecutorType.SIMPLE

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 { //简单的sql执行器对象 executor = new SimpleExecutor(this, transaction); } //判断mybatis的全局配置文件是否开启缓存 if (cacheEnabled) { //把当前的简单的执行器包装成一个CachingExecutor executor = new CachingExecutor(executor); } executor = (Executor) interceptorChain.pluginAll(executor); return executor; }

执行操作 User user = session.selectOne("com.mx.mapper.UserMapper.selectById", 1);

@Override public List selectList(String statement, Object parameter, RowBounds rowBounds) { try { MappedStatement ms = configuration.getMappedStatement(statement); 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(); } }

转发给执行器操作 executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER)

@Override public List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { BoundSql boundSql = ms.getBoundSql(parameterObject); CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql); return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); }

首先二级缓存查

@Override public List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { Cache cache = ms.getCache(); if (cache != null) { //判断是否需要刷新缓存 flushCacheIfRequired(ms); if (ms.isUseCache() && resultHandler == null) { ensureNoOutParams(ms, boundSql); @SuppressWarnings("unchecked") List list = (List) tcm.getObject(cache, key); if (list == null) { //通过查询数据库去查询 list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); //加入到二级缓存中 tcm.putObject(cache, key, list); // issue #578 and #116 } return list; } } //没有整合二级缓存,直接去查询 return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); }

一级缓存delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);

PerpetualCache localCache 一级缓存

@Override public List 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()); //已经关闭,则抛出 ExecutorException 异常 if (closed) { throw new ExecutorException("Executor was closed."); } // <2> 清空本地缓存,如果 queryStack 为零,并且要求清空本地缓存。 if (queryStack == 0 && ms.isFlushCacheRequired()) { clearLocalCache(); } List list; try { // <4.1> 从一级缓存中,获取查询结果 queryStack++; list = resultHandler == null ? (List) localCache.getObject(key) : null; // <4.2> 获取到,则进行处理 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(); } // issue #601 deferredLoads.clear(); if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) { // issue #482 clearLocalCache(); } } return list; }

二级缓存-》一级缓存都查不到到数据库查queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql)
SimpleExecutor.doQuery

@Override public List 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); // 拿到连接和statement stmt = prepareStatement(handler, ms.getStatementLog()); return handler.query(stmt, resultHandler); } finally { closeStatement(stmt); } }

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。