View Javadoc
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.mapping;
17  
18  import java.util.ArrayList;
19  import java.util.Collections;
20  import java.util.List;
21  
22  import org.apache.ibatis.cache.Cache;
23  import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
24  import org.apache.ibatis.executor.keygen.KeyGenerator;
25  import org.apache.ibatis.executor.keygen.NoKeyGenerator;
26  import org.apache.ibatis.logging.Log;
27  import org.apache.ibatis.logging.LogFactory;
28  import org.apache.ibatis.scripting.LanguageDriver;
29  import org.apache.ibatis.session.Configuration;
30  
31  /**
32   * @author Clinton Begin
33   */
34  public final class MappedStatement {
35  
36    private String resource;
37    private Configuration configuration;
38    private String id;
39    private Integer fetchSize;
40    private Integer timeout;
41    private StatementType statementType;
42    private ResultSetType resultSetType;
43    private SqlSource sqlSource;
44    private Cache cache;
45    private ParameterMap parameterMap;
46    private List<ResultMap> resultMaps;
47    private boolean flushCacheRequired;
48    private boolean useCache;
49    private boolean resultOrdered;
50    private SqlCommandType sqlCommandType;
51    private KeyGenerator keyGenerator;
52    private String[] keyProperties;
53    private String[] keyColumns;
54    private boolean hasNestedResultMaps;
55    private String databaseId;
56    private Log statementLog;
57    private LanguageDriver lang;
58    private String[] resultSets;
59    private boolean dirtySelect;
60  
61    MappedStatement() {
62      // constructor disabled
63    }
64  
65    public static class Builder {
66      private final MappedStatement mappedStatement = new MappedStatement();
67  
68      public Builder(Configuration configuration, String id, SqlSource sqlSource, SqlCommandType sqlCommandType) {
69        mappedStatement.configuration = configuration;
70        mappedStatement.id = id;
71        mappedStatement.sqlSource = sqlSource;
72        mappedStatement.statementType = StatementType.PREPARED;
73        mappedStatement.resultSetType = ResultSetType.DEFAULT;
74        mappedStatement.parameterMap = new ParameterMap.Builder(configuration, "defaultParameterMap", null,
75            new ArrayList<>()).build();
76        mappedStatement.resultMaps = new ArrayList<>();
77        mappedStatement.sqlCommandType = sqlCommandType;
78        mappedStatement.keyGenerator = configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType)
79            ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;
80        String logId = id;
81        if (configuration.getLogPrefix() != null) {
82          logId = configuration.getLogPrefix() + id;
83        }
84        mappedStatement.statementLog = LogFactory.getLog(logId);
85        mappedStatement.lang = configuration.getDefaultScriptingLanguageInstance();
86      }
87  
88      public Builder resource(String resource) {
89        mappedStatement.resource = resource;
90        return this;
91      }
92  
93      public String id() {
94        return mappedStatement.id;
95      }
96  
97      public Builder parameterMap(ParameterMap parameterMap) {
98        mappedStatement.parameterMap = parameterMap;
99        return this;
100     }
101 
102     public Builder resultMaps(List<ResultMap> resultMaps) {
103       mappedStatement.resultMaps = resultMaps;
104       for (ResultMap resultMap : resultMaps) {
105         mappedStatement.hasNestedResultMaps = mappedStatement.hasNestedResultMaps || resultMap.hasNestedResultMaps();
106       }
107       return this;
108     }
109 
110     public Builder fetchSize(Integer fetchSize) {
111       mappedStatement.fetchSize = fetchSize;
112       return this;
113     }
114 
115     public Builder timeout(Integer timeout) {
116       mappedStatement.timeout = timeout;
117       return this;
118     }
119 
120     public Builder statementType(StatementType statementType) {
121       mappedStatement.statementType = statementType;
122       return this;
123     }
124 
125     public Builder resultSetType(ResultSetType resultSetType) {
126       mappedStatement.resultSetType = resultSetType == null ? ResultSetType.DEFAULT : resultSetType;
127       return this;
128     }
129 
130     public Builder cache(Cache cache) {
131       mappedStatement.cache = cache;
132       return this;
133     }
134 
135     public Builder flushCacheRequired(boolean flushCacheRequired) {
136       mappedStatement.flushCacheRequired = flushCacheRequired;
137       return this;
138     }
139 
140     public Builder useCache(boolean useCache) {
141       mappedStatement.useCache = useCache;
142       return this;
143     }
144 
145     public Builder resultOrdered(boolean resultOrdered) {
146       mappedStatement.resultOrdered = resultOrdered;
147       return this;
148     }
149 
150     public Builder keyGenerator(KeyGenerator keyGenerator) {
151       mappedStatement.keyGenerator = keyGenerator;
152       return this;
153     }
154 
155     public Builder keyProperty(String keyProperty) {
156       mappedStatement.keyProperties = delimitedStringToArray(keyProperty);
157       return this;
158     }
159 
160     public Builder keyColumn(String keyColumn) {
161       mappedStatement.keyColumns = delimitedStringToArray(keyColumn);
162       return this;
163     }
164 
165     public Builder databaseId(String databaseId) {
166       mappedStatement.databaseId = databaseId;
167       return this;
168     }
169 
170     public Builder lang(LanguageDriver driver) {
171       mappedStatement.lang = driver;
172       return this;
173     }
174 
175     public Builder resultSets(String resultSet) {
176       mappedStatement.resultSets = delimitedStringToArray(resultSet);
177       return this;
178     }
179 
180     public Builder dirtySelect(boolean dirtySelect) {
181       mappedStatement.dirtySelect = dirtySelect;
182       return this;
183     }
184 
185     /**
186      * Resul sets.
187      *
188      * @param resultSet
189      *          the result set
190      *
191      * @return the builder
192      *
193      * @deprecated Use {@link #resultSets}
194      */
195     @Deprecated
196     public Builder resulSets(String resultSet) {
197       mappedStatement.resultSets = delimitedStringToArray(resultSet);
198       return this;
199     }
200 
201     public MappedStatement build() {
202       assert mappedStatement.configuration != null;
203       assert mappedStatement.id != null;
204       assert mappedStatement.sqlSource != null;
205       assert mappedStatement.lang != null;
206       mappedStatement.resultMaps = Collections.unmodifiableList(mappedStatement.resultMaps);
207       return mappedStatement;
208     }
209   }
210 
211   public KeyGenerator getKeyGenerator() {
212     return keyGenerator;
213   }
214 
215   public SqlCommandType getSqlCommandType() {
216     return sqlCommandType;
217   }
218 
219   public String getResource() {
220     return resource;
221   }
222 
223   public Configuration getConfiguration() {
224     return configuration;
225   }
226 
227   public String getId() {
228     return id;
229   }
230 
231   public boolean hasNestedResultMaps() {
232     return hasNestedResultMaps;
233   }
234 
235   public Integer getFetchSize() {
236     return fetchSize;
237   }
238 
239   public Integer getTimeout() {
240     return timeout;
241   }
242 
243   public StatementType getStatementType() {
244     return statementType;
245   }
246 
247   public ResultSetType getResultSetType() {
248     return resultSetType;
249   }
250 
251   public SqlSource getSqlSource() {
252     return sqlSource;
253   }
254 
255   public ParameterMap getParameterMap() {
256     return parameterMap;
257   }
258 
259   public List<ResultMap> getResultMaps() {
260     return resultMaps;
261   }
262 
263   public Cache getCache() {
264     return cache;
265   }
266 
267   public boolean isFlushCacheRequired() {
268     return flushCacheRequired;
269   }
270 
271   public boolean isUseCache() {
272     return useCache;
273   }
274 
275   public boolean isResultOrdered() {
276     return resultOrdered;
277   }
278 
279   public String getDatabaseId() {
280     return databaseId;
281   }
282 
283   public String[] getKeyProperties() {
284     return keyProperties;
285   }
286 
287   public String[] getKeyColumns() {
288     return keyColumns;
289   }
290 
291   public Log getStatementLog() {
292     return statementLog;
293   }
294 
295   public LanguageDriver getLang() {
296     return lang;
297   }
298 
299   public String[] getResultSets() {
300     return resultSets;
301   }
302 
303   public boolean isDirtySelect() {
304     return dirtySelect;
305   }
306 
307   /**
308    * Gets the resul sets.
309    *
310    * @return the resul sets
311    *
312    * @deprecated Use {@link #getResultSets()}
313    */
314   @Deprecated
315   public String[] getResulSets() {
316     return resultSets;
317   }
318 
319   public BoundSql getBoundSql(Object parameterObject) {
320     BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
321     List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
322     if (parameterMappings == null || parameterMappings.isEmpty()) {
323       boundSql = new BoundSql(configuration, boundSql.getSql(), parameterMap.getParameterMappings(), parameterObject);
324     }
325 
326     // check for nested result maps in parameter mappings (issue #30)
327     for (ParameterMapping pm : boundSql.getParameterMappings()) {
328       String rmId = pm.getResultMapId();
329       if (rmId != null) {
330         ResultMap rm = configuration.getResultMap(rmId);
331         if (rm != null) {
332           hasNestedResultMaps |= rm.hasNestedResultMaps();
333         }
334       }
335     }
336 
337     return boundSql;
338   }
339 
340   private static String[] delimitedStringToArray(String in) {
341     if (in == null || in.trim().length() == 0) {
342       return null;
343     }
344     return in.split(",");
345   }
346 
347 }