BaseStatementHandler.java

  1. /*
  2.  *    Copyright 2009-2023 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.  *       https://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,
  47.       RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
  48.     this.configuration = mappedStatement.getConfiguration();
  49.     this.executor = executor;
  50.     this.mappedStatement = mappedStatement;
  51.     this.rowBounds = rowBounds;

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

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

  58.     this.boundSql = boundSql;

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

  63.   @Override
  64.   public BoundSql getBoundSql() {
  65.     return boundSql;
  66.   }

  67.   @Override
  68.   public ParameterHandler getParameterHandler() {
  69.     return parameterHandler;
  70.   }

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

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

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

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

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

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

  127. }