1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.ibatis.sqlmap.engine.mapping.parameter;
17
18 import com.ibatis.common.logging.Log;
19 import com.ibatis.common.logging.LogFactory;
20 import com.ibatis.sqlmap.engine.cache.CacheKey;
21 import com.ibatis.sqlmap.engine.exchange.DataExchange;
22 import com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate;
23 import com.ibatis.sqlmap.engine.scope.ErrorContext;
24 import com.ibatis.sqlmap.engine.scope.StatementScope;
25 import com.ibatis.sqlmap.engine.type.CustomTypeHandler;
26 import com.ibatis.sqlmap.engine.type.JdbcTypeRegistry;
27 import com.ibatis.sqlmap.engine.type.TypeHandler;
28
29 import java.sql.DatabaseMetaData;
30 import java.sql.PreparedStatement;
31 import java.sql.SQLException;
32 import java.sql.Types;
33 import java.util.HashMap;
34 import java.util.List;
35 import java.util.Map;
36
37
38
39
40 public class ParameterMap {
41
42
43 private static final Log log = LogFactory.getLog(ParameterMap.class);
44
45
46 private String id;
47
48
49 private Class parameterClass;
50
51
52 private ParameterMapping[] parameterMappings;
53
54
55 private Boolean useSetObjectForNullValue;
56
57
58 private int sqlTypeToUseForNullValue;
59
60
61 private DataExchange dataExchange;
62
63
64 private String resource;
65
66
67 private Map parameterMappingIndex = new HashMap<>();
68
69
70 private SqlMapExecutorDelegate delegate;
71
72
73
74
75
76
77
78 public ParameterMap(SqlMapExecutorDelegate delegate) {
79 this.delegate = delegate;
80 }
81
82
83
84
85
86
87 public SqlMapExecutorDelegate getDelegate() {
88 return delegate;
89 }
90
91
92
93
94
95
96 public String getId() {
97 return id;
98 }
99
100
101
102
103
104
105
106 public void setId(String id) {
107 this.id = id;
108 }
109
110
111
112
113
114
115 public Class getParameterClass() {
116 return parameterClass;
117 }
118
119
120
121
122
123
124
125 public void setParameterClass(Class parameterClass) {
126 this.parameterClass = parameterClass;
127 }
128
129
130
131
132
133
134 public DataExchange getDataExchange() {
135 return dataExchange;
136 }
137
138
139
140
141
142
143
144 public void setDataExchange(DataExchange dataExchange) {
145 this.dataExchange = dataExchange;
146 }
147
148
149
150
151
152
153 public ParameterMapping[] getParameterMappings() {
154 return parameterMappings;
155 }
156
157
158
159
160
161
162
163 public void setParameterMappingList(List parameterMappingList) {
164 this.parameterMappings = (ParameterMapping[]) parameterMappingList
165 .toArray(new ParameterMapping[parameterMappingList.size()]);
166 parameterMappingIndex.clear();
167 for (int i = 0; i < parameterMappings.length; i++) {
168 parameterMappingIndex.put(parameterMappings[i].getPropertyName(), Integer.valueOf(i));
169 }
170 Map props = new HashMap<>();
171 props.put("map", this);
172
173 dataExchange = delegate.getDataExchangeFactory().getDataExchangeForClass(parameterClass);
174 dataExchange.initialize(props);
175 }
176
177
178
179
180
181
182
183
184
185 public int getParameterIndex(String propertyName) {
186 Integer idx = (Integer) parameterMappingIndex.get(propertyName);
187 return idx == null ? -1 : idx.intValue();
188 }
189
190
191
192
193
194
195 public int getParameterCount() {
196 return this.parameterMappings.length;
197 }
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212 public void setParameters(StatementScope statementScope, PreparedStatement ps, Object[] parameters)
213 throws SQLException {
214
215 ErrorContext errorContext = statementScope.getErrorContext();
216 errorContext.setActivity("applying a parameter map");
217 errorContext.setObjectId(this.getId());
218 errorContext.setResource(this.getResource());
219 errorContext.setMoreInfo("Check the parameter map.");
220
221 if (parameterMappings != null) {
222 for (int i = 0; i < parameterMappings.length; i++) {
223 ParameterMapping mapping = parameterMappings[i];
224 errorContext.setMoreInfo(mapping.getErrorString());
225 if (mapping.isInputAllowed()) {
226 setParameter(ps, mapping, parameters, i);
227 }
228 }
229 }
230 }
231
232
233
234
235
236
237
238
239
240
241
242 public Object[] getParameterObjectValues(StatementScope statementScope, Object parameterObject) {
243 return dataExchange.getData(statementScope, this, parameterObject);
244 }
245
246
247
248
249
250
251
252
253
254
255
256 public CacheKey getCacheKey(StatementScope statementScope, Object parameterObject) {
257 return dataExchange.getCacheKey(statementScope, this, parameterObject);
258 }
259
260
261
262
263
264
265
266
267
268
269
270 public void refreshParameterObjectValues(StatementScope statementScope, Object parameterObject, Object[] values) {
271 dataExchange.setData(statementScope, this, parameterObject, values);
272 }
273
274
275
276
277
278
279 public String getResource() {
280 return resource;
281 }
282
283
284
285
286
287
288
289 public void setResource(String resource) {
290 this.resource = resource;
291 }
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308 protected void setParameter(PreparedStatement ps, ParameterMapping mapping, Object[] parameters, int i)
309 throws SQLException {
310 Object value = parameters[i];
311
312 String nullValueString = mapping.getNullValue();
313 if (nullValueString != null) {
314 TypeHandler handler = mapping.getTypeHandler();
315 if (handler.equals(value, nullValueString)) {
316 value = null;
317 }
318 }
319
320
321 TypeHandler typeHandler = mapping.getTypeHandler();
322 if (value != null || typeHandler instanceof CustomTypeHandler) {
323 typeHandler.setParameter(ps, i + 1, value, mapping.getJdbcTypeName());
324 } else {
325 int jdbcType = mapping.getJdbcType();
326 if (jdbcType != JdbcTypeRegistry.UNKNOWN_TYPE) {
327 ps.setNull(i + 1, jdbcType);
328 } else {
329
330 if (useSetObjectForNullValue == null) {
331
332 useSetObjectForNullValue = Boolean.FALSE;
333 sqlTypeToUseForNullValue = Types.NULL;
334 try {
335 DatabaseMetaData dbmd = ps.getConnection().getMetaData();
336 String databaseProductName = dbmd.getDatabaseProductName();
337 String jdbcDriverName = dbmd.getDriverName();
338 if (databaseProductName.startsWith("Informix") || databaseProductName.startsWith("Microsoft SQL Server")) {
339 useSetObjectForNullValue = Boolean.TRUE;
340 } else if (databaseProductName.startsWith("DB2") || jdbcDriverName.startsWith("jConnect")
341 || jdbcDriverName.startsWith("SQLServer") || jdbcDriverName.startsWith("Apache Derby Embedded")) {
342 sqlTypeToUseForNullValue = Types.VARCHAR;
343 }
344 } catch (Throwable ex) {
345 log.debug("Could not check database or driver name: " + ex.getMessage());
346 }
347 }
348 if (useSetObjectForNullValue.booleanValue()) {
349 ps.setObject(i + 1, null);
350 } else {
351 ps.setNull(i + 1, sqlTypeToUseForNullValue);
352 }
353 }
354 }
355 }
356
357 }