mybatis四大神器之StatementHandler

2020-07-25  本文已影响0人  ajajaj

Statementhandler是四大神器中最重要的一个对象,负责操作Statement与数据库进行交流.在工作时
还会使用ParameterHandler进行参数配置,使用ResultHandler将查询结果与实体类对象进行绑定

我们使用原生jdbc的时候会有statement相关的操作

Statement stmt = conn.createStatement();

StatementHandler的构成

源码如下

public interface StatementHandler {
    Statement prepare(Connection var1, Integer var2) throws SQLException;

    void parameterize(Statement var1) throws SQLException;

    void batch(Statement var1) throws SQLException;

    int update(Statement var1) throws SQLException;

    <E> List<E> query(Statement var1, ResultHandler var2) throws SQLException;

    <E> Cursor<E> queryCursor(Statement var1) throws SQLException;

    BoundSql getBoundSql();

    ParameterHandler getParameterHandler();
}

StatementHandler继承结构

image

可以看出StatementHandler的继承体现和上一篇文章中的Executor的继承体系很类似

StatementHandler是顶级的接口,下面有两个直接实现类

StatementHandler对象创建

StatementHandler对象是在SqlSession对象接收到操作命令时,由Configuraion中newStatementHandler方法负责调用的; Configuration 中的 newStatementHandler 是由执行器中的查询、更新方法来提供的,StatementHandler 其实就是由 Executor 负责管理和创建的

下面是SimpleExecutor中的update方法

public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
        Statement stmt = null;

        int var6;
        try {
            Configuration configuration = ms.getConfiguration();
            //创建StatementHandler,解析sql
            StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, (ResultHandler)null, (BoundSql)null);
            stmt = this.prepareStatement(handler, ms.getStatementLog());
           //handler解析sql
            var6 = handler.update(stmt);
        } finally {
            this.closeStatement(stmt);
        }

        return var6;
    }
image

由上图可以看出RoutingStatementHandler构造方法,将会根据Executor的类型决定创建SimpleStatementHandler,PreparedStatementHandler,CallableStatementHandler实例对象

StatementHandler接口方法

prepare

public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
        ErrorContext.instance().sql(this.boundSql.getSql());
        Statement statement = null;

        try {
            statement = this.instantiateStatement(connection);
            this.setStatementTimeout(statement, transactionTimeout);
            this.setFetchSize(statement);
            return statement;
        } catch (SQLException var5) {
            this.closeStatement(statement);
            throw var5;
        } catch (Exception var6) {
            this.closeStatement(statement);
            throw new ExecutorException("Error preparing statement.  Cause: " + var6, var6);
        }
    }

prepare方法只在BaseStatementHandler被实现.在其三个子类中没有被重写.用于三个子类调用获得对应的Statement接口对象.

prepare方法依靠instantiateStatement(connection)方法来返回具体Statement接口对象.
这个方法是BaseStatementHandler中定义的抽象方法,由三个子类来具体实现.

 protected abstract Statement instantiateStatement(Connection var1) throws SQLException;

SimpleStatementHandler中的instantiateStatement 方法

  protected Statement instantiateStatement(Connection connection) throws SQLException {
        return this.mappedStatement.getResultSetType() != null ? connection.createStatement(this.mappedStatement.getResultSetType().getValue(), 1007) : connection.createStatement();
    }

PreparedStatementHandler中的instantiateStatement方法

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);
        }
    }

CallableStatementHandler中的instantiateStatement方法

  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);
    }

parameterize方法

主要为PreparedStatement和CallableStatement传参.因此只在PreparedStatementHandler和CallableStatementHandler中被重写PreparedStatementHandler中的parameterize

PreparedStatementHandler中的parameterize

 public void parameterize(Statement statement) throws SQLException {
        this.parameterHandler.setParameters((PreparedStatement)statement);
    }

CallableStatementHandler中的parameterize

public void parameterize(Statement statement) throws SQLException {
        this.registerOutputParameters((CallableStatement)statement);
        this.parameterHandler.setParameters((CallableStatement)statement);
    }

在这两个方法中,可以看到都是"ParameterHandler"对象进行参数赋值的

query方法

输送查询查询语句,并将查询结果转换对应的实体类对象

SimpleStatementHandler 中的 query 方法

 public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
        String sql = this.boundSql.getSql();
        statement.execute(sql);
        return this.resultSetHandler.handleResultSets(statement);
    }

PreparedStatementHandler中的query方法

   public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
        PreparedStatement ps = (PreparedStatement)statement;
        ps.execute();
        return this.resultSetHandler.handleResultSets(ps);
    }

可以看到在得到查询结果后,都是使用[ResultSetHandler]对结果进行转换

update

输送insert,update,delete语句并返回处理数据行

SimpleStatementHandler中的update方法

  public int update(Statement statement) throws SQLException {
        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;
    }

PreparedStatementHandler中update方法

 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;
    }

CallableStatementHandler中update方法

 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;
    }

原文地址

http://cbaj.gitee.io/blog/2020/07/25/mybatis%E5%9B%9B%E5%A4%A7%E7%A5%9E%E5%99%A8%E4%B9%8BStatementHandler/#more

上一篇 下一篇

猜你喜欢

热点阅读