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 = null;
187 idx = (Integer) parameterMappingIndex.get(propertyName);
188 return idx == null ? -1 : idx.intValue();
189 }
190
191
192
193
194
195
196 public int getParameterCount() {
197 return this.parameterMappings.length;
198 }
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213 public void setParameters(StatementScope statementScope, PreparedStatement ps, Object[] parameters)
214 throws SQLException {
215
216 ErrorContext errorContext = statementScope.getErrorContext();
217 errorContext.setActivity("applying a parameter map");
218 errorContext.setObjectId(this.getId());
219 errorContext.setResource(this.getResource());
220 errorContext.setMoreInfo("Check the parameter map.");
221
222 if (parameterMappings != null) {
223 for (int i = 0; i < parameterMappings.length; i++) {
224 ParameterMapping mapping = parameterMappings[i];
225 errorContext.setMoreInfo(mapping.getErrorString());
226 if (mapping.isInputAllowed()) {
227 setParameter(ps, mapping, parameters, i);
228 }
229 }
230 }
231 }
232
233
234
235
236
237
238
239
240
241
242
243 public Object[] getParameterObjectValues(StatementScope statementScope, Object parameterObject) {
244 return dataExchange.getData(statementScope, this, parameterObject);
245 }
246
247
248
249
250
251
252
253
254
255
256
257 public CacheKey getCacheKey(StatementScope statementScope, Object parameterObject) {
258 return dataExchange.getCacheKey(statementScope, this, parameterObject);
259 }
260
261
262
263
264
265
266
267
268
269
270
271 public void refreshParameterObjectValues(StatementScope statementScope, Object parameterObject, Object[] values) {
272 dataExchange.setData(statementScope, this, parameterObject, values);
273 }
274
275
276
277
278
279
280 public String getResource() {
281 return resource;
282 }
283
284
285
286
287
288
289
290 public void setResource(String resource) {
291 this.resource = resource;
292 }
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309 protected void setParameter(PreparedStatement ps, ParameterMapping mapping, Object[] parameters, int i)
310 throws SQLException {
311 Object value = parameters[i];
312
313 String nullValueString = mapping.getNullValue();
314 if (nullValueString != null) {
315 TypeHandler handler = mapping.getTypeHandler();
316 if (handler.equals(value, nullValueString)) {
317 value = null;
318 }
319 }
320
321
322 TypeHandler typeHandler = mapping.getTypeHandler();
323 if (value != null) {
324 typeHandler.setParameter(ps, i + 1, value, mapping.getJdbcTypeName());
325 } else if (typeHandler instanceof CustomTypeHandler) {
326 typeHandler.setParameter(ps, i + 1, value, mapping.getJdbcTypeName());
327 } else {
328 int jdbcType = mapping.getJdbcType();
329 if (jdbcType != JdbcTypeRegistry.UNKNOWN_TYPE) {
330 ps.setNull(i + 1, jdbcType);
331 } else {
332
333 if (useSetObjectForNullValue == null) {
334
335 useSetObjectForNullValue = Boolean.FALSE;
336 sqlTypeToUseForNullValue = Types.NULL;
337 try {
338 DatabaseMetaData dbmd = ps.getConnection().getMetaData();
339 String databaseProductName = dbmd.getDatabaseProductName();
340 String jdbcDriverName = dbmd.getDriverName();
341 if (databaseProductName.startsWith("Informix") || databaseProductName.startsWith("Microsoft SQL Server")) {
342 useSetObjectForNullValue = Boolean.TRUE;
343 } else if (databaseProductName.startsWith("DB2") || jdbcDriverName.startsWith("jConnect")
344 || jdbcDriverName.startsWith("SQLServer") || jdbcDriverName.startsWith("Apache Derby Embedded")) {
345 sqlTypeToUseForNullValue = Types.VARCHAR;
346 }
347 } catch (Throwable ex) {
348 log.debug("Could not check database or driver name: " + ex.getMessage());
349 }
350 }
351 if (useSetObjectForNullValue.booleanValue()) {
352 ps.setObject(i + 1, null);
353 } else {
354 ps.setNull(i + 1, sqlTypeToUseForNullValue);
355 }
356 }
357 }
358 }
359
360 }