mybatis原理----SqlSession的四大对象

匿名 (未验证) 提交于 2019-12-03 00:20:01


一、Executor(接口)

/**  * 执行器  *   */ public interface Executor {    //不需要ResultHandler   ResultHandler NO_RESULT_HANDLER = null;    //更新   int update(MappedStatement ms, Object parameter) throws SQLException;    //查询,带分页,带缓存,BoundSql   <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;    //查询,带分页   <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;    //刷新批处理语句   List<BatchResult> flushStatements() throws SQLException;    //提交和回滚,参数是否要强制   void commit(boolean required) throws SQLException;    void rollback(boolean required) throws SQLException;    //创建CacheKey   CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);    //判断是否缓存了   boolean isCached(MappedStatement ms, CacheKey key);    //清理Session缓存   void clearLocalCache();    //延迟加载   void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType);    Transaction getTransaction();    void close(boolean forceRollback);    boolean isClosed();    void setExecutorWrapper(Executor executor);  }


 //默认为简单执行器   protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;//枚举类,下面提供源码
 public Executor newExecutor(Transaction transaction) {     return newExecutor(transaction, defaultExecutorType);   }    //产生执行器   public Executor newExecutor(Transaction transaction, ExecutorType executorType) {     executorType = executorType == null ? defaultExecutorType : executorType;     //这句再做一下保护,防止粗心大意的人将defaultExecutorType设成null?     executorType = executorType == null ? ExecutorType.SIMPLE : executorType;     Executor executor;     //然后就是简单的3个分支,产生3种执行器BatchExecutor/ReuseExecutor/SimpleExecutor     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);     }     //如果要求缓存,生成另一种CachingExecutor(默认就是有缓存),装饰者模式,所以默认都是返回CachingExecutor     if (cacheEnabled) {       executor = new CachingExecutor(executor);     }     //此处调用插件,通过插件可以改变Executor行为     executor = (Executor) interceptorChain.pluginAll(executor);     return executor;   }
/**  * 执行器的类型  *  */ public enum ExecutorType {     //ExecutorType.SIMPLE     //这个执行器类型不做特殊的事情。它为每个语句的执行创建一个新的预处理语句。     //ExecutorType.REUSE     //这个执行器类型会复用预处理语句。     //ExecutorType.BATCH     //这个执行器会批量执行所有更新语句,如果SELECT在它们中间执行还会标定它们是必须的,来保证一个简单并易于理解的行为。   SIMPLE, REUSE, BATCH } 

如代码注释所说,拦截Executor。构建一层层动态代理对象,我们可以修改在执行真正的Executor方法之前来配置插件的代码,这就是插件的原理。再看看执行Executor的方法,其中有多个类,我们了解一下简单执行器SimpleExecutor的方法:

public class SimpleExecutor extends BaseExecutor {    public SimpleExecutor(Configuration configuration, Transaction transaction) {     super(configuration, transaction);   }    //update   @Override   public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {     Statement stmt = null;     try {       Configuration configuration = ms.getConfiguration();       //新建一个StatementHandler       //这里看到ResultHandler传入的是null       StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);       //准备语句       stmt = prepareStatement(handler, ms.getStatementLog());       //StatementHandler.update       return handler.update(stmt);     } finally {       closeStatement(stmt);     }   }    //select   @Override   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();       //新建一个StatementHandler       //这里看到ResultHandler传入了       StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);       //准备语句       stmt = prepareStatement(handler, ms.getStatementLog());       //StatementHandler.query       return handler.<E>query(stmt, resultHandler);     } finally {       closeStatement(stmt);     }   }    @Override   public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException { 	//doFlushStatements只是给batch用的,所以这里返回空     return Collections.emptyList();   }    private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {     Statement stmt;     Connection connection = getConnection(statementLog);     //调用StatementHandler.prepare     stmt = handler.prepare(connection);     //调用StatementHandler.parameterize     handler.parameterize(stmt);     return stmt;   }  }
  //创建语句处理器   public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {     //创建路由选择语句处理器     StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);     //插件在这里插入     statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);     return statementHandler;   } 

其他的执行器与简单执行器的走法基本差不多,不多赘述,提供相关源码参考(可跳过下面源码部分了解下一个内容StatementHandler):

public class ReuseExecutor extends BaseExecutor {    //可重用的执行器内部用了一个map,用来缓存SQL语句对应的Statement   private final Map<String, Statement> statementMap = new HashMap<String, Statement>();    public ReuseExecutor(Configuration configuration, Transaction transaction) {     super(configuration, transaction);   }    @Override   public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {     Configuration configuration = ms.getConfiguration();     //和SimpleExecutor一样,新建一个StatementHandler     //这里看到ResultHandler传入的是null     StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);     //准备语句     Statement stmt = prepareStatement(handler, ms.getStatementLog());     return handler.update(stmt);   }    @Override   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 stmt = prepareStatement(handler, ms.getStatementLog());     return handler.<E>query(stmt, resultHandler);   }    @Override   public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {     for (Statement stmt : statementMap.values()) {       closeStatement(stmt);     }     statementMap.clear();     return Collections.emptyList();   }    private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {     Statement stmt;     //得到绑定的SQL语句     BoundSql boundSql = handler.getBoundSql();     String sql = boundSql.getSql();     //如果缓存中已经有了,直接得到Statement     if (hasStatementFor(sql)) {       stmt = getStatement(sql);     } else {       //如果缓存没有找到,则和SimpleExecutor处理完全一样,然后加入缓存       Connection connection = getConnection(statementLog);       stmt = handler.prepare(connection);       putStatement(sql, stmt);     }     handler.parameterize(stmt);     return stmt;   }    private boolean hasStatementFor(String sql) {     try {       return statementMap.keySet().contains(sql) && !statementMap.get(sql).getConnection().isClosed();     } catch (SQLException e) {       return false;     }   }    private Statement getStatement(String s) {     return statementMap.get(s);   }    private void putStatement(String sql, Statement stmt) {     statementMap.put(sql, stmt);   }  }
二、StatementHandler(接口)
注意:新的Jar包中prepare中新增一个参数Integer):

StatementHandler有一个抽象实现类BaseStatementHandler和一个实现类RoutingStatementHandler,BaseStatementHandler有三个子类:


在Configuration中生成StatementHandler就三句代码,创建的实际对象为RoutingStatementHandler对象,它也是与Executor一样的,都是用代理对象来封装的。

观察RoutingStatementHandler就会发现其中的巧妙之处:

通过配置来选择具体的StatementHandler对象,我们来查看常用的PreparedStatementHandler(预处理语句处理器),由于其父类已经将prepare方法实现了:

父类BaseStatementHandler

  @Override   public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {     ErrorContext.instance().sql(boundSql.getSql());     Statement statement = null;     try { 		//实例化Statement       statement = instantiateStatement(connection);//对SQL进行预编译等操作 	  //设置超时       setStatementTimeout(statement, transactionTimeout); 	  //设置读取条数       setFetchSize(statement);       return statement;     } catch (SQLException e) {       closeStatement(statement);       throw e;     } catch (Exception e) {       closeStatement(statement);       throw new ExecutorException("Error preparing statement.  Cause: " + e, e);     }   }  //如何实例化Statement,交给子类做   protected abstract Statement instantiateStatement(Connection connection) throws SQLException; 

设置参数是通过ParameterHandler处理的。接下来开始看下一个对象----ParameterHandler。

三、ParameterHandler:

它是对预编译语句进行参数的设置,完成对预编译参数的设置。

/**  * 参数处理器  *   */ public interface ParameterHandler {    //得到参数   Object getParameterObject();    //设置参数   void setParameters(PreparedStatement ps)       throws SQLException;  } 

它仅有一个默认的实现类:DefaultParameterHandler

**  * 默认参数处理器  *   */ public class DefaultParameterHandler implements ParameterHandler {    private final TypeHandlerRegistry typeHandlerRegistry;    private final MappedStatement mappedStatement;   private final Object parameterObject;   private BoundSql boundSql;   private Configuration configuration;    public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {     this.mappedStatement = mappedStatement;     this.configuration = mappedStatement.getConfiguration();     this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();     this.parameterObject = parameterObject;     this.boundSql = boundSql;   }    @Override   public Object getParameterObject() {     return parameterObject;   }    //设置参数   @Override   public void setParameters(PreparedStatement ps) throws SQLException {     ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());     List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();     if (parameterMappings != null) {       //循环设参数       for (int i = 0; i < parameterMappings.size(); i++) {         ParameterMapping parameterMapping = parameterMappings.get(i);         if (parameterMapping.getMode() != ParameterMode.OUT) {           //如果不是OUT,才设进去           Object value;           String propertyName = parameterMapping.getProperty();           if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params             //若有额外的参数, 设为额外的参数             value = boundSql.getAdditionalParameter(propertyName);           } else if (parameterObject == null) {             //若参数为null,直接设null             value = null;           } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {             //若参数有相应的TypeHandler,直接设object             value = parameterObject;           } else {             //除此以外,MetaObject.getValue反射取得值设进去             MetaObject metaObject = configuration.newMetaObject(parameterObject);             value = metaObject.getValue(propertyName);           }           TypeHandler typeHandler = parameterMapping.getTypeHandler();           JdbcType jdbcType = parameterMapping.getJdbcType();           if (value == null && jdbcType == null) {             //不同类型的set方法不同,所以委派给子类的setParameter方法             jdbcType = configuration.getJdbcTypeForNull();           }           typeHandler.setParameter(ps, i + 1, value, jdbcType);         }       }     }   }  } 

把取到的参数(parameterObject)转换后(typeHandler),注册到Configuration中(typeHandler也是在其中配置好的)。

四、ResultSetHandler

/**  * 结果集处理器  *   */ public interface ResultSetHandler {    //处理结果集   <E> List<E> handleResultSets(Statement stmt) throws SQLException;    //处理OUT参数   void handleOutputParameters(CallableStatement cs) throws SQLException;  }

mybatis已经为我们提供了一个默认实现类:DefaultResultSetHandler

由于其源码内容较多,节选部分参考:

  @Override   public void handleOutputParameters(CallableStatement cs) throws SQLException {     final Object parameterObject = parameterHandler.getParameterObject();     final MetaObject metaParam = configuration.newMetaObject(parameterObject);     final List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();     //循环处理每个参数     for (int i = 0; i < parameterMappings.size(); i++) {       final ParameterMapping parameterMapping = parameterMappings.get(i);       //只处理OUT|INOUT       if (parameterMapping.getMode() == ParameterMode.OUT || parameterMapping.getMode() == ParameterMode.INOUT) {         if (ResultSet.class.equals(parameterMapping.getJavaType())) {           //如果是ResultSet型(游标)           //#{result, jdbcType=CURSOR, mode=OUT, javaType=ResultSet, resultMap=userResultMap}           //先用CallableStatement.getObject取得这个游标,作为参数传进去           handleRefCursorOutputParameter((ResultSet) cs.getObject(i + 1), parameterMapping, metaParam);         } else {           //否则是普通型,核心就是CallableStatement.getXXX取得值           final TypeHandler<?> typeHandler = parameterMapping.getTypeHandler();           metaParam.setValue(parameterMapping.getProperty(), typeHandler.getResult(cs, i + 1));         }       }     }   }
 @Override   public List<Object> handleResultSets(Statement stmt) throws SQLException {     ErrorContext.instance().activity("handling results").object(mappedStatement.getId());          final List<Object> multipleResults = new ArrayList<Object>();      int resultSetCount = 0;     ResultSetWrapper rsw = getFirstResultSet(stmt);      List<ResultMap> resultMaps = mappedStatement.getResultMaps();     //一般resultMaps里只有一个元素     int resultMapCount = resultMaps.size();     validateResultMapsCount(rsw, resultMapCount);     while (rsw != null && resultMapCount > resultSetCount) {       ResultMap resultMap = resultMaps.get(resultSetCount);       handleResultSet(rsw, resultMap, multipleResults, null);       rsw = getNextResultSet(stmt);       cleanUpAfterHandlingResultSet();       resultSetCount++;     }      String[] resultSets = mappedStatement.getResulSets();     if (resultSets != null) {       while (rsw != null && resultSetCount < resultSets.length) {         ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);         if (parentMapping != null) {           String nestedResultMapId = parentMapping.getNestedResultMapId();           ResultMap resultMap = configuration.getResultMap(nestedResultMapId);           handleResultSet(rsw, resultMap, null, parentMapping);         }         rsw = getNextResultSet(stmt);         cleanUpAfterHandlingResultSet();         resultSetCount++;       }     }      return collapseSingleResultList(multipleResults);   }

由于实际操作中对它的改变几率低,不再讨论。


总结



-----图片来源于GitHub(nero520)














易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!