1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.ibatis.sqlmap.engine.config;
17
18 import com.ibatis.common.beans.Probe;
19 import com.ibatis.common.beans.ProbeFactory;
20 import com.ibatis.common.resources.Resources;
21 import com.ibatis.sqlmap.client.SqlMapException;
22 import com.ibatis.sqlmap.engine.cache.CacheModel;
23 import com.ibatis.sqlmap.engine.impl.SqlMapClientImpl;
24 import com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate;
25 import com.ibatis.sqlmap.engine.mapping.parameter.InlineParameterMapParser;
26 import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMap;
27 import com.ibatis.sqlmap.engine.mapping.result.AutoResultMap;
28 import com.ibatis.sqlmap.engine.mapping.result.ResultMap;
29 import com.ibatis.sqlmap.engine.mapping.sql.Sql;
30 import com.ibatis.sqlmap.engine.mapping.sql.SqlText;
31 import com.ibatis.sqlmap.engine.mapping.sql.dynamic.DynamicSql;
32 import com.ibatis.sqlmap.engine.mapping.sql.simple.SimpleDynamicSql;
33 import com.ibatis.sqlmap.engine.mapping.sql.stat.StaticSql;
34 import com.ibatis.sqlmap.engine.mapping.statement.CachingStatement;
35 import com.ibatis.sqlmap.engine.mapping.statement.InsertStatement;
36 import com.ibatis.sqlmap.engine.mapping.statement.MappedStatement;
37 import com.ibatis.sqlmap.engine.mapping.statement.SelectKeyStatement;
38 import com.ibatis.sqlmap.engine.scope.ErrorContext;
39 import com.ibatis.sqlmap.engine.type.TypeHandlerFactory;
40
41 import java.sql.ResultSet;
42 import java.util.Arrays;
43 import java.util.List;
44
45
46
47
48 public class MappedStatementConfig {
49
50
51 private static final Probe PROBE = ProbeFactory.getProbe();
52
53
54 private static final InlineParameterMapParser PARAM_PARSER = new InlineParameterMapParser();
55
56
57 private ErrorContext errorContext;
58
59
60 private SqlMapClientImpl client;
61
62
63 private TypeHandlerFactory typeHandlerFactory;
64
65
66 private MappedStatement mappedStatement;
67
68
69 private MappedStatement rootStatement;
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109 MappedStatementConfig(SqlMapConfiguration config, String id, MappedStatement statement, SqlSource processor,
110 String parameterMapName, Class parameterClass, String resultMapName, String[] additionalResultMapNames,
111 Class resultClass, Class[] additionalResultClasses, String cacheModelName, String resultSetType,
112 Integer fetchSize, boolean allowRemapping, Integer timeout, Integer defaultStatementTimeout,
113 String xmlResultName) {
114 this.errorContext = config.getErrorContext();
115 this.client = config.getClient();
116 SqlMapExecutorDelegate delegate = client.getDelegate();
117 this.typeHandlerFactory = config.getTypeHandlerFactory();
118 errorContext.setActivity("parsing a mapped statement");
119 errorContext.setObjectId(id + " statement");
120 errorContext.setMoreInfo("Check the result map name.");
121 if (resultMapName != null) {
122 statement.setResultMap(client.getDelegate().getResultMap(resultMapName));
123 if (additionalResultMapNames != null) {
124 for (String additionalResultMapName : additionalResultMapNames) {
125 statement.addResultMap(client.getDelegate().getResultMap(additionalResultMapName));
126 }
127 }
128 }
129 errorContext.setMoreInfo("Check the parameter map name.");
130 if (parameterMapName != null) {
131 statement.setParameterMap(client.getDelegate().getParameterMap(parameterMapName));
132 }
133 statement.setId(id);
134 statement.setResource(errorContext.getResource());
135 if (resultSetType != null) {
136 switch (resultSetType) {
137 case "FORWARD_ONLY":
138 statement.setResultSetType(Integer.valueOf(ResultSet.TYPE_FORWARD_ONLY));
139 break;
140 case "SCROLL_INSENSITIVE":
141 statement.setResultSetType(Integer.valueOf(ResultSet.TYPE_SCROLL_INSENSITIVE));
142 break;
143 case "SCROLL_SENSITIVE":
144 statement.setResultSetType(Integer.valueOf(ResultSet.TYPE_SCROLL_SENSITIVE));
145 break;
146 default:
147 break;
148 }
149 }
150 if (fetchSize != null) {
151 statement.setFetchSize(fetchSize);
152 }
153
154
155 ParameterMap parameterMap = statement.getParameterMap();
156 if (parameterMap == null) {
157 statement.setParameterClass(parameterClass);
158 } else {
159 statement.setParameterClass(parameterMap.getParameterClass());
160 }
161
162
163 errorContext.setMoreInfo("Check the SQL statement.");
164 Sql sql = processor.getSql();
165 setSqlForStatement(statement, sql);
166
167
168 ResultMap resultMap = statement.getResultMap();
169 if (resultMap == null && resultClass == null) {
170 statement.setResultMap(null);
171 } else if (resultMap == null) {
172 resultMap = buildAutoResultMap(allowRemapping, statement, resultClass, xmlResultName);
173 statement.setResultMap(resultMap);
174 if (additionalResultClasses != null) {
175 for (Class additionalResultClass : additionalResultClasses) {
176 statement.addResultMap(buildAutoResultMap(allowRemapping, statement, additionalResultClass, xmlResultName));
177 }
178 }
179
180 }
181 statement.setTimeout(defaultStatementTimeout);
182 if (timeout != null) {
183 try {
184 statement.setTimeout(timeout);
185 } catch (NumberFormatException e) {
186 throw new SqlMapException(
187 "Specified timeout value for statement " + statement.getId() + " is not a valid integer");
188 }
189 }
190 errorContext.setMoreInfo(null);
191 errorContext.setObjectId(null);
192 statement.setSqlMapClient(client);
193 if (cacheModelName != null && !cacheModelName.isEmpty() && client.getDelegate().isCacheModelsEnabled()) {
194 CacheModel cacheModel = client.getDelegate().getCacheModel(cacheModelName);
195 mappedStatement = new CachingStatement(statement, cacheModel);
196 } else {
197 mappedStatement = statement;
198 }
199 rootStatement = statement;
200 delegate.addMappedStatement(mappedStatement);
201 }
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217 public void setSelectKeyStatement(SqlSource processor, String resultClassName, String keyPropName,
218 boolean runAfterSQL, String type) {
219 if (!(rootStatement instanceof InsertStatement)) {
220 throw new SqlMapException("You cant set a select key statement on statement named " + rootStatement.getId()
221 + " because it is not an InsertStatement.");
222 }
223 InsertStatement insertStatement = (InsertStatement) rootStatement;
224 Class parameterClass = insertStatement.getParameterClass();
225 errorContext.setActivity("parsing a select key");
226 SelectKeyStatement selectKeyStatement = new SelectKeyStatement();
227 resultClassName = typeHandlerFactory.resolveAlias(resultClassName);
228 Class resultClass = null;
229
230
231 selectKeyStatement.setSqlMapClient(client);
232 selectKeyStatement.setId(insertStatement.getId() + "-SelectKey");
233 selectKeyStatement.setResource(errorContext.getResource());
234 selectKeyStatement.setKeyProperty(keyPropName);
235 selectKeyStatement.setRunAfterSQL(runAfterSQL);
236
237 if (type != null) {
238 selectKeyStatement.setRunAfterSQL("post".equals(type));
239 }
240 try {
241 if (resultClassName != null) {
242 errorContext.setMoreInfo("Check the select key result class.");
243 resultClass = Resources.classForName(resultClassName);
244 } else if (keyPropName != null && parameterClass != null) {
245 resultClass = PROBE.getPropertyTypeForSetter(parameterClass, selectKeyStatement.getKeyProperty());
246 }
247 } catch (ClassNotFoundException e) {
248 throw new SqlMapException("Error. Could not set result class. Cause: " + e, e);
249 }
250 if (resultClass == null) {
251 resultClass = Object.class;
252 }
253
254
255 errorContext.setMoreInfo("Check the select key SQL statement.");
256 Sql sql = processor.getSql();
257 setSqlForStatement(selectKeyStatement, sql);
258 ResultMap resultMap = new AutoResultMap(client.getDelegate(), false);
259 resultMap.setId(selectKeyStatement.getId() + "-AutoResultMap");
260 resultMap.setResultClass(resultClass);
261 resultMap.setResource(selectKeyStatement.getResource());
262 selectKeyStatement.setResultMap(resultMap);
263 errorContext.setMoreInfo(null);
264 insertStatement.setSelectKeyStatement(selectKeyStatement);
265 }
266
267
268
269
270
271
272
273
274
275 private void setSqlForStatement(MappedStatement statement, Sql sql) {
276 if (sql instanceof DynamicSql) {
277 statement.setSql(sql);
278 } else {
279 applyInlineParameterMap(statement, sql.getSql(null, null));
280 }
281 }
282
283
284
285
286
287
288
289
290
291 private void applyInlineParameterMap(MappedStatement statement, String sqlStatement) {
292 String newSql = sqlStatement;
293 errorContext.setActivity("building an inline parameter map");
294 ParameterMap parameterMap = statement.getParameterMap();
295 errorContext.setMoreInfo("Check the inline parameters.");
296 if (parameterMap == null) {
297 ParameterMap map;
298 map = new ParameterMap(client.getDelegate());
299 map.setId(statement.getId() + "-InlineParameterMap");
300 map.setParameterClass(statement.getParameterClass());
301 map.setResource(statement.getResource());
302 statement.setParameterMap(map);
303 SqlText sqlText = PARAM_PARSER.parseInlineParameterMap(client.getDelegate().getTypeHandlerFactory(), newSql,
304 statement.getParameterClass());
305 newSql = sqlText.getText();
306 List mappingList = Arrays.asList(sqlText.getParameterMappings());
307 map.setParameterMappingList(mappingList);
308 }
309 Sql sql;
310 if (SimpleDynamicSql.isSimpleDynamicSql(newSql)) {
311 sql = new SimpleDynamicSql(client.getDelegate(), newSql);
312 } else {
313 sql = new StaticSql(newSql);
314 }
315 statement.setSql(sql);
316
317 }
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333 private ResultMap buildAutoResultMap(boolean allowRemapping, MappedStatement statement, Class firstResultClass,
334 String xmlResultName) {
335 ResultMap resultMap = new AutoResultMap(client.getDelegate(), allowRemapping);
336 resultMap.setId(statement.getId() + "-AutoResultMap");
337 resultMap.setResultClass(firstResultClass);
338 resultMap.setXmlName(xmlResultName);
339 resultMap.setResource(statement.getResource());
340 return resultMap;
341 }
342
343
344
345
346
347
348 public MappedStatement getMappedStatement() {
349 return mappedStatement;
350 }
351 }