zoukankan      html  css  js  c++  java
  • 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;
          }
        }
  • 相关阅读:
    深入理解PHP原理之变量作用域
    深入理解PHP原理之变量分离/引用
    关于哈希表
    foreach 相关
    Scrapyd-Client的安装
    Scrapyd API的安装
    scrapyd的安装
    快手的小视频爬取
    实现单例模式的几种方式
    京东图书分布式爬虫
  • 原文地址:https://www.cnblogs.com/sunanli/p/13550990.html
Copyright © 2011-2022 走看看