mybatis执行器1

sqlsession详细内容可参见 https://www.cnblogs.com/jian0110/p/9452592.html

 mybatis执行过程:

一个SqlSession只能一个线程使用,所以不是线程安全的,一个线程使用完必须关闭。一个sqlsession可以执行多个sql语句。 

sqlSession只提供sql会话,不会处理具体的请求。由执行器excutor来处理。

excutor也不能跨线程使用,只有查询和更新功能;excutor也不和数据库做交互,最终由statementhandle和数据库直接交互。

statementhandle对应JDBC中的statement/prestatement,callablestatement

创建sqlsession之后就对应创建了一个事务。一般来说不由mybatis来处理事务,由spring来直接处理事务。

 

batch和reuse都可以重用预处理器,但是reuse是重用一次预处理器,设置一次值,发送一次数据库。batch可以重用一次预处理器,多次设值,发送一次数据库。batch不能查询,只能增删改。

batch没有缓存。

reuseexcutor持有一个缓存,(只要sql语句相同就能命中statement)sql语句和对应的statement,找到对应的statement的后直接和jdbc数据库交互。

baseexcutor来实现一级缓存。有两个抽象方法,query和upfate。。doquery都在具体执行器中实现。(simple、reuse、batch)

public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);//获取statement处理器。如preparestament
Statement stmt = prepareStatement(handler, ms.getStatementLog());//编译statement,设置staemnt值
return handler.query(stmt, resultHandler);//执行查询
}

二级缓存采用装饰者模式,其中持有baseexcutor,也就是装饰了baseexcutor。采用装饰者模式不采用纵向继承的方式是因为,继承的话,又需要添加抽象方法,需要具体的执行器(simple、reuse、batch)来实现。
代码会变的很复杂。装饰者模式,只需要持有baseexcutor,给他的抽象方法添加装饰代码,就可以完成缓存。
也就是用户使用时,只需要使用二级缓存,二级缓存相关业务执行完成后,执行baseexcutor的代码即可。

 sqlsession中的select方法:

    参数:

    String:查询的statementid

    Object:查询的参数

    ResultHandle:结果集自定义

   RowBounds:分页用的,查询多少行

重载这么多的方法方便调用。这种设计模式是门面模式。

代码分析:

@Test
    public void sessionTest(){
        SqlSession sqlSession = factory.openSession(ExecutorType.REUSE,true);
        // 降低调用复杂性    门面模式 屏蔽了底层调用的复杂用  统一对接sqlSession
       List<Object> list = sqlSession.selectList("org.coderead.mybatis.UserMapper.selectByid", 10); System.out.println(list.get(0)); }

  1、进入opensession(): 

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

      2、openSessionFromDataSource

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);//根据执行器类型创建执行器。(执行器类型是配置的,所以需要从configuratuion获取)
      return new DefaultSqlSession(configuration, executor, autoCommit);//返回sqlsession
    } 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();
    }

  3、selectList

  @Override
  public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
    try {
      MappedStatement ms = configuration.getMappedStatement(statement);//MappedStatement类位于mybatis包的org.apache.ibatis.mapping目录下,
//是一个final类型也就是说实例化之后就不允许改变MappedStatement对象对应Mapper.xml配置文件中的一个select/update/insert/delete节点,描述的就是一条SQL语句
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);//wrapCollection(parameter),查询对应的参数,该执行器就是缓存执行器
} catch (Exception e) { throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }

   4、query

  public <E> List<E> 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);//二级缓存执行器执行
  }

 5.query

public <E> List<E> 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<E> list = (List<E>) tcm.getObject(cache, key);//以上二级缓存相关逻辑
        if (list == null) {
          list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);//正真的simpleexample执行器。
          tcm.putObject(cache, key, list); // issue #578 and #116
        }
        return list;
      }
    }
原文地址:https://www.cnblogs.com/sunanli/p/13550990.html