/* * Copyright 2009-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.ibatis.executor; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.logging.Log; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; import org.apache.ibatis.transaction.Transaction; /** * @author Clinton Begin */ /** * 可重用的执行器 */ public class ReuseExecutor extends BaseExecutor { //可重用的执行器内部用了一个map,用来缓存SQL语句对应的Statement private final Map<String, Statement> statementMap = new HashMap<String, Statement>(); public ReuseExecutor(Configuration configuration, Transaction transaction) { super(configuration, transaction); } @Override public int doUpdate(MappedStatement ms, Object parameter) throws SQLException { Configuration configuration = ms.getConfiguration(); //和SimpleExecutor一样,新建一个StatementHandler //这里看到ResultHandler传入的是null StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null); //准备语句 Statement stmt = prepareStatement(handler, ms.getStatementLog()); return handler.update(stmt); } @Override public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { Configuration configuration = ms.getConfiguration(); StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql); Statement stmt = prepareStatement(handler, ms.getStatementLog()); return handler.<E>query(stmt, resultHandler); } @Override public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException { for (Statement stmt : statementMap.values()) { closeStatement(stmt); } statementMap.clear(); return Collections.emptyList(); } private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Statement stmt; //得到绑定的SQL语句 BoundSql boundSql = handler.getBoundSql(); String sql = boundSql.getSql(); //如果缓存中已经有了,直接得到Statement if (hasStatementFor(sql)) { stmt = getStatement(sql); } else { //如果缓存没有找到,则和SimpleExecutor处理完全一样,然后加入缓存 Connection connection = getConnection(statementLog); stmt = handler.prepare(connection); putStatement(sql, stmt); } handler.parameterize(stmt); return stmt; } private boolean hasStatementFor(String sql) { try { return statementMap.keySet().contains(sql) && !statementMap.get(sql).getConnection().isClosed(); } catch (SQLException e) { return false; } } private Statement getStatement(String s) { return statementMap.get(s); } private void putStatement(String sql, Statement stmt) { statementMap.put(sql, stmt); } }