BaseStatementHandler.java

  1. /*
  2.  *    Copyright 2009-2021 the original author or authors.
  3.  *
  4.  *    Licensed under the Apache License, Version 2.0 (the "License");
  5.  *    you may not use this file except in compliance with the License.
  6.  *    You may obtain a copy of the License at
  7.  *
  8.  *       http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  *    Unless required by applicable law or agreed to in writing, software
  11.  *    distributed under the License is distributed on an "AS IS" BASIS,
  12.  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  *    See the License for the specific language governing permissions and
  14.  *    limitations under the License.
  15.  */
  16. package org.apache.ibatis.executor.statement;

  17. import java.sql.Connection;
  18. import java.sql.SQLException;
  19. import java.sql.Statement;

  20. import org.apache.ibatis.executor.ErrorContext;
  21. import org.apache.ibatis.executor.Executor;
  22. import org.apache.ibatis.executor.ExecutorException;
  23. import org.apache.ibatis.executor.keygen.KeyGenerator;
  24. import org.apache.ibatis.executor.parameter.ParameterHandler;
  25. import org.apache.ibatis.executor.resultset.ResultSetHandler;
  26. import org.apache.ibatis.mapping.BoundSql;
  27. import org.apache.ibatis.mapping.MappedStatement;
  28. import org.apache.ibatis.reflection.factory.ObjectFactory;
  29. import org.apache.ibatis.session.Configuration;
  30. import org.apache.ibatis.session.ResultHandler;
  31. import org.apache.ibatis.session.RowBounds;
  32. import org.apache.ibatis.type.TypeHandlerRegistry;

  33. /**
  34.  * @author Clinton Begin
  35.  */
  36. public abstract class BaseStatementHandler implements StatementHandler {

  37.   protected final Configuration configuration;
  38.   protected final ObjectFactory objectFactory;
  39.   protected final TypeHandlerRegistry typeHandlerRegistry;
  40.   protected final ResultSetHandler resultSetHandler;
  41.   protected final ParameterHandler parameterHandler;

  42.   protected final Executor executor;
  43.   protected final MappedStatement mappedStatement;
  44.   protected final RowBounds rowBounds;

  45.   protected BoundSql boundSql;

  46.   protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
  47.     this.configuration = mappedStatement.getConfiguration();
  48.     this.executor = executor;
  49.     this.mappedStatement = mappedStatement;
  50.     this.rowBounds = rowBounds;

  51.     this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
  52.     this.objectFactory = configuration.getObjectFactory();

  53.     if (boundSql == null) { // issue #435, get the key before calculating the statement
  54.       generateKeys(parameterObject);
  55.       boundSql = mappedStatement.getBoundSql(parameterObject);
  56.     }

  57.     this.boundSql = boundSql;

  58.     this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
  59.     this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
  60.   }

  61.   @Override
  62.   public BoundSql getBoundSql() {
  63.     return boundSql;
  64.   }

  65.   @Override
  66.   public ParameterHandler getParameterHandler() {
  67.     return parameterHandler;
  68.   }

  69.   @Override
  70.   public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
  71.     ErrorContext.instance().sql(boundSql.getSql());
  72.     Statement statement = null;
  73.     try {
  74.       statement = instantiateStatement(connection);
  75.       setStatementTimeout(statement, transactionTimeout);
  76.       setFetchSize(statement);
  77.       return statement;
  78.     } catch (SQLException e) {
  79.       closeStatement(statement);
  80.       throw e;
  81.     } catch (Exception e) {
  82.       closeStatement(statement);
  83.       throw new ExecutorException("Error preparing statement.  Cause: " + e, e);
  84.     }
  85.   }

  86.   protected abstract Statement instantiateStatement(Connection connection) throws SQLException;

  87.   protected void setStatementTimeout(Statement stmt, Integer transactionTimeout) throws SQLException {
  88.     Integer queryTimeout = null;
  89.     if (mappedStatement.getTimeout() != null) {
  90.       queryTimeout = mappedStatement.getTimeout();
  91.     } else if (configuration.getDefaultStatementTimeout() != null) {
  92.       queryTimeout = configuration.getDefaultStatementTimeout();
  93.     }
  94.     if (queryTimeout != null) {
  95.       stmt.setQueryTimeout(queryTimeout);
  96.     }
  97.     StatementUtil.applyTransactionTimeout(stmt, queryTimeout, transactionTimeout);
  98.   }

  99.   protected void setFetchSize(Statement stmt) throws SQLException {
  100.     Integer fetchSize = mappedStatement.getFetchSize();
  101.     if (fetchSize != null) {
  102.       stmt.setFetchSize(fetchSize);
  103.       return;
  104.     }
  105.     Integer defaultFetchSize = configuration.getDefaultFetchSize();
  106.     if (defaultFetchSize != null) {
  107.       stmt.setFetchSize(defaultFetchSize);
  108.     }
  109.   }

  110.   protected void closeStatement(Statement statement) {
  111.     try {
  112.       if (statement != null) {
  113.         statement.close();
  114.       }
  115.     } catch (SQLException e) {
  116.       //ignore
  117.     }
  118.   }

  119.   protected void generateKeys(Object parameter) {
  120.     KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
  121.     ErrorContext.instance().store();
  122.     keyGenerator.processBefore(executor, mappedStatement, null, parameter);
  123.     ErrorContext.instance().recall();
  124.   }

  125. }