mybatis源码分析三之SqlSession

SqlSession

  1. SqlSession是一个会话,相当于jdbc的Connection对象,生命周期应该是请求数据库处理事务的过程中。它是非线程安全的,在每次创建SqlSession都必须及时关闭它,它长期存在就会使数据库连接池的活动资源减少。

SqlSession下的四大对象

  1. Mapper执行的过程是通过Executor、StatementHandler、ParameterHandler和ResultHandler来完成数据库操作和结果返回的
    • Executor表示执行器,调度相关的handler来执行对应的sql(StatementHandler、ParameterHandler、ResultHandler)
    • StatementHandler的作用是使用数据库的Statement(PreparedStatement)执行操作
    • ParameterHandler用于SQL对参数的处理
    • ResultHandler是进行最后数据集(ResultSet)的封装返回处理的

Executor

  1. Executor是一个真正执行java和数据库交互的东西
    • SIMPLE
    • REUSE
    • BATCH
  2. 创建

    在DefaultSqlSessionFactory中创建DefaultSqlSession之前创建Executor(通过Configuration创建),以下是Configuration中创建Executor的代码。根据配置类型去创建三种执行器中的一种,在创建之后将Executor放到interceptorChain之中
     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;
      }
    
  3. SimpleExecutor

     public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        Statement stmt = null;
        try {
          Configuration configuration = ms.getConfiguration();
          //通过Configuration创建StatementHandler
          StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, rowBounds, resultHandler, boundSql);
          //预编译sql,并对参数进行初始化操作
          stmt = prepareStatement(handler, ms.getStatementLog());
          //resultHandler 组装返回结果
          return handler.<E>query(stmt, resultHandler);
        } finally {
          closeStatement(stmt);
        }
      }
    
      private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
        Statement stmt;
        Connection connection = getConnection(statementLog);
        stmt = handler.prepare(connection);
        //设置参数并执行(预编译sql)
        handler.parameterize(stmt);
        return stmt;
      }
    

StatementHandler

  1. 创建

        /***
        在Executor创建StatementHandler,StatementHandler是在Configuration中创建,代码如下
        **/
          public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
            /**
            RoutingStatementHandler不是真实的服务对象,而是通过适配器找到对应的StatementHandler(对象的适配器模式)
                SimpleStatementHandler
                PreparedStatementHandler
                CallableStatementHandler
            */
            StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
            statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
            return statementHandler;
          }
    

  2. SimpleStatementHandler

    
          public <E> List<E> query(Statement statement, ResultHandler resultHandler)
              throws SQLException {
            String sql = boundSql.getSql();
            statement.execute(sql);
            //使用ResultSetHandler封装结果返回给调用者
            return resultSetHandler.<E>handleResultSets(statement);
          }   
  3. PreparedStatementHandler

      public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
        //sql编译已经在之前都做好了,所以这里直接执行就可以了
        PreparedStatement ps = (PreparedStatement) statement;
        ps.execute();
        return resultSetHandler.<E> handleResultSets(ps);
      }
    
        public void parameterize(Statement statement) throws SQLException {
        KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
        ErrorContext.instance().store();
        keyGenerator.processBefore(executor, mappedStatement, statement, boundSql.getParameterObject());
        ErrorContext.instance().recall();
        rebindGeneratedKey();
        parameterHandler.setParameters((PreparedStatement) statement);
      }

paramsHandler

  1. 代码

    public interface ParameterHandler {
     //返回参数对象   
      Object getParameterObject();
     //设置预编译sql语句的参数
      void setParameters(PreparedStatement ps)
          throws SQLException;
    
    }
    mybatis提供一个默认的DefaultParameterHandler
    public void setParameters(PreparedStatement ps)
          throws SQLException {
        ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        if (parameterMappings != null) {
          //从parameterObject对象中获取参数,然后使用typeHandler进行参数处理
          MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(parameterObject);
          for (int i = 0; i < parameterMappings.size(); i++) {
            ParameterMapping parameterMapping = parameterMappings.get(i);
            if (parameterMapping.getMode() != ParameterMode.OUT) {
              Object value;
              String propertyName = parameterMapping.getProperty();
              PropertyTokenizer prop = new PropertyTokenizer(propertyName);
              if (parameterObject == null) {
                value = null;
              } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
                value = parameterObject;
              } else if (boundSql.hasAdditionalParameter(propertyName)) {
                value = boundSql.getAdditionalParameter(propertyName);
              } else if (propertyName.startsWith(ForEachSqlNode.ITEM_PREFIX)
                  && boundSql.hasAdditionalParameter(prop.getName())) {
                value = boundSql.getAdditionalParameter(prop.getName());
                if (value != null) {
                  value = configuration.newMetaObject(value).getValue(propertyName.substring(prop.getName().length()));
                }
              } else {
                value = metaObject == null ? null : metaObject.getValue(propertyName);
              }
              TypeHandler typeHandler = parameterMapping.getTypeHandler();
              if (typeHandler == null) {
                throw new ExecutorException("There was no TypeHandler found for parameter " + propertyName + " of statement " + mappedStatement.getId());
              }
              JdbcType jdbcType = parameterMapping.getJdbcType();
              if (value == null && jdbcType == null) jdbcType = configuration.getJdbcTypeForNull();
              typeHandler.setParameter(ps, i + 1, value, jdbcType);
            }
          }
        }
      }
    

resultSetHandler

  1. 结果集处理器

     public interface ResultSetHandler {
     //包装结果集
      <E> List<E> handleResultSets(Statement stmt) throws SQLException;
       //处理存储过程输出参数的
      void handleOutputParameters(CallableStatement cs) throws SQLException;
    
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值