• mybatis源码阅读-执行器StatementHandle和ParameterHandler(五)


    StatementHandle

    类图

    各个实现类的作用

    SimpleStatementHandler 用于使用Statement操作数据库(不会使用参数化查询?)

    PreparedStatementHandler 用于使用PreparedStatement操作数据库(会使用参数化查询)

    CallableStatementHandler 用于使用CallableStatement 操作数据库(主要是执行存储过程)

    RoutingStatementHandler 待定

    StatementHandler调用时机

    Executor部分代码

     public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
            Statement stmt = null;
    
            int var6;
            try {
                Configuration configuration = ms.getConfiguration();
                //获得对应的statementHandler 可以是SimpleStatementHandler PreparedStatementHandler CallableStatementHandler
                StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, (ResultHandler)null, (BoundSql)null);
                //通过StaementHandler设置参数
                stmt = this.prepareStatement(handler, ms.getStatementLog());
                //调用update方法获得返回结果 内部使用Statement操作数据库
                var6 = handler.update(stmt);
            } finally {
                this.closeStatement(stmt);
            }
    
            return var6;
        }

    SimpleStatementHandler

    public class SimpleStatementHandler extends BaseStatementHandler {
        public SimpleStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
            super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
        }
    
        /**
         * 通过Staement执行修改
         * @param statement
         * @return
         * @throws SQLException
         */
        public int update(Statement statement) throws SQLException {
            //获得sql语句 boundSql接口 根据MapperStatement获得
            String sql = this.boundSql.getSql();
            Object parameterObject = this.boundSql.getParameterObject();
            KeyGenerator keyGenerator = this.mappedStatement.getKeyGenerator();
            int rows;
            if (keyGenerator instanceof Jdbc3KeyGenerator) {
                statement.execute(sql, 1);
                rows = statement.getUpdateCount();
                keyGenerator.processAfter(this.executor, this.mappedStatement, statement, parameterObject);
            } else if (keyGenerator instanceof SelectKeyGenerator) {
                statement.execute(sql);
                rows = statement.getUpdateCount();
                keyGenerator.processAfter(this.executor, this.mappedStatement, statement, parameterObject);
            } else {
                statement.execute(sql);
                rows = statement.getUpdateCount();
            }
    
            return rows;
        }
    
        public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {
            String sql = this.boundSql.getSql();
            statement.execute(sql);
            return this.resultSetHandler.handleCursorResultSets(statement);
        }
        //根据connection创建Statement
        protected Statement instantiateStatement(Connection connection) throws SQLException {
            return this.mappedStatement.getResultSetType() != null ? connection.createStatement(this.mappedStatement.getResultSetType().getValue(), 1007) : connection.createStatement();
        }
        //设置参数 由于Staement不支持?参数化查询 sql语句写死参数 所以实现是空的
        public void parameterize(Statement statement) throws SQLException {
        }
    }

    PreparedStatementHandler

    public class PreparedStatementHandler extends BaseStatementHandler {
        public PreparedStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
            super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
        }
    
        public int update(Statement statement) throws SQLException {
            PreparedStatement ps = (PreparedStatement)statement;
            ps.execute();
            int rows = ps.getUpdateCount();
            Object parameterObject = this.boundSql.getParameterObject();
            KeyGenerator keyGenerator = this.mappedStatement.getKeyGenerator();
            keyGenerator.processAfter(this.executor, this.mappedStatement, ps, parameterObject);
            return rows;
        }
        //根据connection创建PrepareStatement
        protected Statement instantiateStatement(Connection connection) throws SQLException {
            String sql = this.boundSql.getSql();
            if (this.mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
                String[] keyColumnNames = this.mappedStatement.getKeyColumns();
                return keyColumnNames == null ? connection.prepareStatement(sql, 1) : connection.prepareStatement(sql, keyColumnNames);
            } else {
                return this.mappedStatement.getResultSetType() != null ? connection.prepareStatement(sql, this.mappedStatement.getResultSetType().getValue(), 1007) : connection.prepareStatement(sql);
            }
        }
        //设置参数
        public void parameterize(Statement statement) throws SQLException {
            //交给parameterHandler处理parameterHandler是根据MappedStatement中获得
            this.parameterHandler.setParameters((PreparedStatement)statement);
        }
    }

    参数设置是委托给ParameterHandler处理的

    CallableStatementHandler

    public class CallableStatementHandler extends BaseStatementHandler {
        public CallableStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
            super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
        }
    
        public int update(Statement statement) throws SQLException {
            CallableStatement cs = (CallableStatement)statement;
            cs.execute();
            int rows = cs.getUpdateCount();
            Object parameterObject = this.boundSql.getParameterObject();
            KeyGenerator keyGenerator = this.mappedStatement.getKeyGenerator();
            keyGenerator.processAfter(this.executor, this.mappedStatement, cs, parameterObject);
            this.resultSetHandler.handleOutputParameters(cs);
            return rows;
        }
        //根据连接创建  CallStatement
        protected Statement instantiateStatement(Connection connection) throws SQLException {
            String sql = this.boundSql.getSql();
            return this.mappedStatement.getResultSetType() != null ? connection.prepareCall(sql, this.mappedStatement.getResultSetType().getValue(), 1007) : connection.prepareCall(sql);
        }
        //设置参数
        public void parameterize(Statement statement) throws SQLException {
            this.registerOutputParameters((CallableStatement)statement);
            this.parameterHandler.setParameters((CallableStatement)statement);
        }
    }

    ParameterHandler

    类图

    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;
        }
    
        public Object getParameterObject() {
            return this.parameterObject;
        }
    
        public void setParameters(PreparedStatement ps) {
            ErrorContext.instance().activity("setting parameters").object(this.mappedStatement.getParameterMap().getId());
            //获得BoundSql里面的ParameterMapping 内部保存的是参数的映射
            List<ParameterMapping> parameterMappings = this.boundSql.getParameterMappings();
            if (parameterMappings != null) {
                for(int i = 0; i < parameterMappings.size(); ++i) {
                    ParameterMapping parameterMapping = (ParameterMapping)parameterMappings.get(i);
                    if (parameterMapping.getMode() != ParameterMode.OUT) {
                        String propertyName = parameterMapping.getProperty();
                        Object value;
                        if (this.boundSql.hasAdditionalParameter(propertyName)) {
                            value = this.boundSql.getAdditionalParameter(propertyName);
                        } else if (this.parameterObject == null) {
                            value = null;
                        } else if (this.typeHandlerRegistry.hasTypeHandler(this.parameterObject.getClass())) {
                            value = this.parameterObject;
                        } else {
                            MetaObject metaObject = this.configuration.newMetaObject(this.parameterObject);
                            value = metaObject.getValue(propertyName);
                        }
                        //获得对应的TypeHandler
                        TypeHandler typeHandler = parameterMapping.getTypeHandler();
                        JdbcType jdbcType = parameterMapping.getJdbcType();
                        if (value == null && jdbcType == null) {
                            jdbcType = this.configuration.getJdbcTypeForNull();
                        }
    
                        try {
                            //给Statement设置参数
                            typeHandler.setParameter(ps, i + 1, value, jdbcType);
                        } catch (TypeException var10) {
                            throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + var10, var10);
                        } catch (SQLException var11) {
                            throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + var11, var11);
                        }
                    }
                }
            }
    
        }
    }

    StatementHandler设置

    可选类型

    public enum StatementType {
      STATEMENT, PREPARED, CALLABLE
    }

    xml设置

    <select id="findAllStudents" resultMap="StudentResult" statementType="STATEMENT">
        SELECT * FROM STUDENTS
    </select>
  • 相关阅读:
    mysql5.5 uuid做主键与int做主键的性能实测
    dom4j解析xml字符串实例
    spring自动注入是单例还是多例?单例如何注入多例?
    Spring中Bean的五个作用域
    【总结】瞬时高并发(秒杀/活动)Redis方案
    浅谈分布式事务
    基于Redis实现分布式锁
    MySQL事务隔离级别详解
    Redis学习手册(Sorted-Sets数据类型)
    Redis的快照持久化-RDB与AOF
  • 原文地址:https://www.cnblogs.com/LQBlog/p/10682987.html
Copyright © 2020-2023  润新知