View Javadoc
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  
18  import java.sql.Connection;
19  import java.sql.SQLException;
20  import java.sql.Statement;
21  
22  import org.apache.ibatis.executor.ErrorContext;
23  import org.apache.ibatis.executor.Executor;
24  import org.apache.ibatis.executor.ExecutorException;
25  import org.apache.ibatis.executor.keygen.KeyGenerator;
26  import org.apache.ibatis.executor.parameter.ParameterHandler;
27  import org.apache.ibatis.executor.resultset.ResultSetHandler;
28  import org.apache.ibatis.mapping.BoundSql;
29  import org.apache.ibatis.mapping.MappedStatement;
30  import org.apache.ibatis.reflection.factory.ObjectFactory;
31  import org.apache.ibatis.session.Configuration;
32  import org.apache.ibatis.session.ResultHandler;
33  import org.apache.ibatis.session.RowBounds;
34  import org.apache.ibatis.type.TypeHandlerRegistry;
35  
36  /**
37   * @author Clinton Begin
38   */
39  public abstract class BaseStatementHandler implements StatementHandler {
40  
41    protected final Configuration configuration;
42    protected final ObjectFactory objectFactory;
43    protected final TypeHandlerRegistry typeHandlerRegistry;
44    protected final ResultSetHandler resultSetHandler;
45    protected final ParameterHandler parameterHandler;
46  
47    protected final Executor executor;
48    protected final MappedStatement mappedStatement;
49    protected final RowBounds rowBounds;
50  
51    protected BoundSql boundSql;
52  
53    protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
54      this.configuration = mappedStatement.getConfiguration();
55      this.executor = executor;
56      this.mappedStatement = mappedStatement;
57      this.rowBounds = rowBounds;
58  
59      this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
60      this.objectFactory = configuration.getObjectFactory();
61  
62      if (boundSql == null) { // issue #435, get the key before calculating the statement
63        generateKeys(parameterObject);
64        boundSql = mappedStatement.getBoundSql(parameterObject);
65      }
66  
67      this.boundSql = boundSql;
68  
69      this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
70      this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
71    }
72  
73    @Override
74    public BoundSql getBoundSql() {
75      return boundSql;
76    }
77  
78    @Override
79    public ParameterHandler getParameterHandler() {
80      return parameterHandler;
81    }
82  
83    @Override
84    public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
85      ErrorContext.instance().sql(boundSql.getSql());
86      Statement statement = null;
87      try {
88        statement = instantiateStatement(connection);
89        setStatementTimeout(statement, transactionTimeout);
90        setFetchSize(statement);
91        return statement;
92      } catch (SQLException e) {
93        closeStatement(statement);
94        throw e;
95      } catch (Exception e) {
96        closeStatement(statement);
97        throw new ExecutorException("Error preparing statement.  Cause: " + e, e);
98      }
99    }
100 
101   protected abstract Statement instantiateStatement(Connection connection) throws SQLException;
102 
103   protected void setStatementTimeout(Statement stmt, Integer transactionTimeout) throws SQLException {
104     Integer queryTimeout = null;
105     if (mappedStatement.getTimeout() != null) {
106       queryTimeout = mappedStatement.getTimeout();
107     } else if (configuration.getDefaultStatementTimeout() != null) {
108       queryTimeout = configuration.getDefaultStatementTimeout();
109     }
110     if (queryTimeout != null) {
111       stmt.setQueryTimeout(queryTimeout);
112     }
113     StatementUtil.applyTransactionTimeout(stmt, queryTimeout, transactionTimeout);
114   }
115 
116   protected void setFetchSize(Statement stmt) throws SQLException {
117     Integer fetchSize = mappedStatement.getFetchSize();
118     if (fetchSize != null) {
119       stmt.setFetchSize(fetchSize);
120       return;
121     }
122     Integer defaultFetchSize = configuration.getDefaultFetchSize();
123     if (defaultFetchSize != null) {
124       stmt.setFetchSize(defaultFetchSize);
125     }
126   }
127 
128   protected void closeStatement(Statement statement) {
129     try {
130       if (statement != null) {
131         statement.close();
132       }
133     } catch (SQLException e) {
134       //ignore
135     }
136   }
137 
138   protected void generateKeys(Object parameter) {
139     KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
140     ErrorContext.instance().store();
141     keyGenerator.processBefore(executor, mappedStatement, null, parameter);
142     ErrorContext.instance().recall();
143   }
144 
145 }