ReuseExecutor.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;

  17. import java.sql.Connection;
  18. import java.sql.SQLException;
  19. import java.sql.Statement;
  20. import java.util.Collections;
  21. import java.util.HashMap;
  22. import java.util.List;
  23. import java.util.Map;

  24. import org.apache.ibatis.cursor.Cursor;
  25. import org.apache.ibatis.executor.statement.StatementHandler;
  26. import org.apache.ibatis.logging.Log;
  27. import org.apache.ibatis.mapping.BoundSql;
  28. import org.apache.ibatis.mapping.MappedStatement;
  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.transaction.Transaction;

  33. /**
  34.  * @author Clinton Begin
  35.  */
  36. public class ReuseExecutor extends BaseExecutor {

  37.   private final Map<String, Statement> statementMap = new HashMap<>();

  38.   public ReuseExecutor(Configuration configuration, Transaction transaction) {
  39.     super(configuration, transaction);
  40.   }

  41.   @Override
  42.   public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
  43.     Configuration configuration = ms.getConfiguration();
  44.     StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
  45.     Statement stmt = prepareStatement(handler, ms.getStatementLog());
  46.     return handler.update(stmt);
  47.   }

  48.   @Override
  49.   public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler,
  50.       BoundSql boundSql) throws SQLException {
  51.     Configuration configuration = ms.getConfiguration();
  52.     StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler,
  53.         boundSql);
  54.     Statement stmt = prepareStatement(handler, ms.getStatementLog());
  55.     return handler.query(stmt, resultHandler);
  56.   }

  57.   @Override
  58.   protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql)
  59.       throws SQLException {
  60.     Configuration configuration = ms.getConfiguration();
  61.     StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
  62.     Statement stmt = prepareStatement(handler, ms.getStatementLog());
  63.     return handler.queryCursor(stmt);
  64.   }

  65.   @Override
  66.   public List<BatchResult> doFlushStatements(boolean isRollback) {
  67.     for (Statement stmt : statementMap.values()) {
  68.       closeStatement(stmt);
  69.     }
  70.     statementMap.clear();
  71.     return Collections.emptyList();
  72.   }

  73.   private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
  74.     Statement stmt;
  75.     BoundSql boundSql = handler.getBoundSql();
  76.     String sql = boundSql.getSql();
  77.     if (hasStatementFor(sql)) {
  78.       stmt = getStatement(sql);
  79.       applyTransactionTimeout(stmt);
  80.     } else {
  81.       Connection connection = getConnection(statementLog);
  82.       stmt = handler.prepare(connection, transaction.getTimeout());
  83.       putStatement(sql, stmt);
  84.     }
  85.     handler.parameterize(stmt);
  86.     return stmt;
  87.   }

  88.   private boolean hasStatementFor(String sql) {
  89.     try {
  90.       Statement statement = statementMap.get(sql);
  91.       return statement != null && !statement.getConnection().isClosed();
  92.     } catch (SQLException e) {
  93.       return false;
  94.     }
  95.   }

  96.   private Statement getStatement(String s) {
  97.     return statementMap.get(s);
  98.   }

  99.   private void putStatement(String sql, Statement stmt) {
  100.     statementMap.put(sql, stmt);
  101.   }

  102. }