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 (int i = 0; i < additionalResultMapNames.length; i++) {
125 statement.addResultMap(client.getDelegate().getResultMap(additionalResultMapNames[i]));
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 if ("FORWARD_ONLY".equals(resultSetType)) {
137 statement.setResultSetType(Integer.valueOf(ResultSet.TYPE_FORWARD_ONLY));
138 } else if ("SCROLL_INSENSITIVE".equals(resultSetType)) {
139 statement.setResultSetType(Integer.valueOf(ResultSet.TYPE_SCROLL_INSENSITIVE));
140 } else if ("SCROLL_SENSITIVE".equals(resultSetType)) {
141 statement.setResultSetType(Integer.valueOf(ResultSet.TYPE_SCROLL_SENSITIVE));
142 }
143 }
144 if (fetchSize != null) {
145 statement.setFetchSize(fetchSize);
146 }
147
148
149 ParameterMap parameterMap = statement.getParameterMap();
150 if (parameterMap == null) {
151 statement.setParameterClass(parameterClass);
152 } else {
153 statement.setParameterClass(parameterMap.getParameterClass());
154 }
155
156
157 errorContext.setMoreInfo("Check the SQL statement.");
158 Sql sql = processor.getSql();
159 setSqlForStatement(statement, sql);
160
161
162 ResultMap resultMap = (ResultMap) statement.getResultMap();
163 if (resultMap == null && resultClass == null) {
164 statement.setResultMap(null);
165 } else if (resultMap == null) {
166 resultMap = buildAutoResultMap(allowRemapping, statement, resultClass, xmlResultName);
167 statement.setResultMap(resultMap);
168 if (additionalResultClasses != null) {
169 for (int i = 0; i < additionalResultClasses.length; i++) {
170 statement
171 .addResultMap(buildAutoResultMap(allowRemapping, statement, additionalResultClasses[i], xmlResultName));
172 }
173 }
174
175 }
176 statement.setTimeout(defaultStatementTimeout);
177 if (timeout != null) {
178 try {
179 statement.setTimeout(timeout);
180 } catch (NumberFormatException e) {
181 throw new SqlMapException(
182 "Specified timeout value for statement " + statement.getId() + " is not a valid integer");
183 }
184 }
185 errorContext.setMoreInfo(null);
186 errorContext.setObjectId(null);
187 statement.setSqlMapClient(client);
188 if (cacheModelName != null && cacheModelName.length() > 0 && client.getDelegate().isCacheModelsEnabled()) {
189 CacheModel cacheModel = client.getDelegate().getCacheModel(cacheModelName);
190 mappedStatement = new CachingStatement(statement, cacheModel);
191 } else {
192 mappedStatement = statement;
193 }
194 rootStatement = statement;
195 delegate.addMappedStatement(mappedStatement);
196 }
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212 public void setSelectKeyStatement(SqlSource processor, String resultClassName, String keyPropName,
213 boolean runAfterSQL, String type) {
214 if (rootStatement instanceof InsertStatement) {
215 InsertStatement insertStatement = ((InsertStatement) rootStatement);
216 Class parameterClass = insertStatement.getParameterClass();
217 errorContext.setActivity("parsing a select key");
218 SelectKeyStatement selectKeyStatement = new SelectKeyStatement();
219 resultClassName = typeHandlerFactory.resolveAlias(resultClassName);
220 Class resultClass = null;
221
222
223 selectKeyStatement.setSqlMapClient(client);
224 selectKeyStatement.setId(insertStatement.getId() + "-SelectKey");
225 selectKeyStatement.setResource(errorContext.getResource());
226 selectKeyStatement.setKeyProperty(keyPropName);
227 selectKeyStatement.setRunAfterSQL(runAfterSQL);
228
229 if (type != null) {
230 selectKeyStatement.setRunAfterSQL("post".equals(type));
231 }
232 try {
233 if (resultClassName != null) {
234 errorContext.setMoreInfo("Check the select key result class.");
235 resultClass = Resources.classForName(resultClassName);
236 } else {
237 if (keyPropName != null && parameterClass != null) {
238 resultClass = PROBE.getPropertyTypeForSetter(parameterClass, selectKeyStatement.getKeyProperty());
239 }
240 }
241 } catch (ClassNotFoundException e) {
242 throw new SqlMapException("Error. Could not set result class. Cause: " + e, e);
243 }
244 if (resultClass == null) {
245 resultClass = Object.class;
246 }
247
248
249 errorContext.setMoreInfo("Check the select key SQL statement.");
250 Sql sql = processor.getSql();
251 setSqlForStatement(selectKeyStatement, sql);
252 ResultMap resultMap;
253 resultMap = new AutoResultMap(client.getDelegate(), false);
254 resultMap.setId(selectKeyStatement.getId() + "-AutoResultMap");
255 resultMap.setResultClass(resultClass);
256 resultMap.setResource(selectKeyStatement.getResource());
257 selectKeyStatement.setResultMap(resultMap);
258 errorContext.setMoreInfo(null);
259 insertStatement.setSelectKeyStatement(selectKeyStatement);
260 } else {
261 throw new SqlMapException("You cant set a select key statement on statement named " + rootStatement.getId()
262 + " because it is not an InsertStatement.");
263 }
264 }
265
266
267
268
269
270
271
272
273
274 private void setSqlForStatement(MappedStatement statement, Sql sql) {
275 if (sql instanceof DynamicSql) {
276 statement.setSql(sql);
277 } else {
278 applyInlineParameterMap(statement, sql.getSql(null, null));
279 }
280 }
281
282
283
284
285
286
287
288
289
290 private void applyInlineParameterMap(MappedStatement statement, String sqlStatement) {
291 String newSql = sqlStatement;
292 errorContext.setActivity("building an inline parameter map");
293 ParameterMap parameterMap = statement.getParameterMap();
294 errorContext.setMoreInfo("Check the inline parameters.");
295 if (parameterMap == null) {
296 ParameterMap map;
297 map = new ParameterMap(client.getDelegate());
298 map.setId(statement.getId() + "-InlineParameterMap");
299 map.setParameterClass(statement.getParameterClass());
300 map.setResource(statement.getResource());
301 statement.setParameterMap(map);
302 SqlText sqlText = PARAM_PARSER.parseInlineParameterMap(client.getDelegate().getTypeHandlerFactory(), newSql,
303 statement.getParameterClass());
304 newSql = sqlText.getText();
305 List mappingList = Arrays.asList(sqlText.getParameterMappings());
306 map.setParameterMappingList(mappingList);
307 }
308 Sql sql;
309 if (SimpleDynamicSql.isSimpleDynamicSql(newSql)) {
310 sql = new SimpleDynamicSql(client.getDelegate(), newSql);
311 } else {
312 sql = new StaticSql(newSql);
313 }
314 statement.setSql(sql);
315
316 }
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332 private ResultMap buildAutoResultMap(boolean allowRemapping, MappedStatement statement, Class firstResultClass,
333 String xmlResultName) {
334 ResultMap resultMap;
335 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 }