1
2
3
4
5 package net.sf.diaz;
6
7 import java.sql.*;
8 import java.math.BigDecimal;
9 import java.util.*;
10
11 /**
12 *
13 * @author Sean C. Sullivan
14 *
15 */
16 public abstract class AbstractJdbcDao
17 {
18 private int fetchSize = 500;
19 private int maxRows = 2000;
20 private int queryTimeout = 180;
21 private boolean closeQuietly = false;
22 private int resultSetType = ResultSet.TYPE_FORWARD_ONLY;
23 private int resultSetConcurrency = ResultSet.CONCUR_READ_ONLY;
24 private int transactionIsolation = Connection.TRANSACTION_READ_COMMITTED;
25
26 protected int getTransactionIsolation()
27 {
28 return transactionIsolation;
29 }
30
31 protected void setTransactionIsolation(int transactionIsolation)
32 {
33 this.transactionIsolation = transactionIsolation;
34 }
35
36 /**
37 *
38 */
39 protected GeneratedKeys executeInsert(CharSequence sql, Object... queryParameters)
40 {
41 GeneratedKeys keys = (GeneratedKeys) executeUpdate(sql, Statement.RETURN_GENERATED_KEYS, queryParameters);
42 return keys;
43 }
44
45
46 protected Object executeUpdate(CharSequence sql)
47 {
48 return executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
49 }
50
51 /**
52 *
53 * @param sql
54 * @param queryParameters
55 *
56 */
57 protected Object executeUpdate(CharSequence sql, int autoGeneratedKeys, Object... queryParameters)
58 {
59 Connection conn = null;
60
61 Object result = null;
62
63 try
64 {
65 conn = getConnection();
66 result = executeUpdate(conn, sql, autoGeneratedKeys, queryParameters);
67 return result;
68 }
69 catch (SQLException ex)
70 {
71 throw new DataAccessException(
72 buildMessage(sql, queryParameters),
73 ex);
74 }
75 finally
76 {
77 close(conn, null, null);
78 }
79 }
80
81 /**
82 *
83 * @param conn
84 * @param sql
85 * @param queryParameters
86 *
87 */
88 protected Object executeUpdate(Connection conn, CharSequence sql, int autoGeneratedKeys, Object... queryParameters)
89 {
90 PreparedStatement ps = null;
91
92 Object result = null;
93
94 String strSQL = sql.toString();
95
96 try
97 {
98 conn = getConnection();
99 ps = conn.prepareStatement(strSQL, autoGeneratedKeys);
100 setPreparedStatementParameters(ps, queryParameters);
101 int rowCount = ps.executeUpdate();
102 if (autoGeneratedKeys == Statement.RETURN_GENERATED_KEYS)
103 {
104 result = new GeneratedKeys(ps.getGeneratedKeys());
105 }
106 else
107 {
108 result = new Integer(rowCount);
109 }
110 return result;
111 }
112 catch (SQLException ex)
113 {
114 throw new DataAccessException(
115 buildMessage(strSQL, queryParameters),
116 ex);
117 }
118 finally
119 {
120 close(null, null, ps);
121 }
122 }
123
124 /**
125 *
126 * @param sql
127 * @param queryParameters
128 * @return a List containing zero or more {@link Row} objects
129 *
130 */
131 protected List<Row> executeQuery(CharSequence sql, Object... queryParameters)
132 {
133 ResultSet rs = null;
134 PreparedStatement ps = null;
135 Connection conn = null;
136 List<Row> rows = null;
137
138 String strSQL = sql.toString();
139
140 try
141 {
142 conn = getConnection();
143 conn.setTransactionIsolation(this.getTransactionIsolation());
144 ps = conn.prepareStatement(strSQL,
145 this.getResultSetType(),
146 this.getResultSetConcurrency());
147 setPreparedStatementParameters(ps, queryParameters);
148 ps.setFetchDirection(ResultSet.FETCH_FORWARD);
149 ps.setFetchSize(this.getFetchSize());
150 ps.setQueryTimeout(this.getQueryTimeout());
151 ps.setMaxRows(this.getMaxRows());
152 rs = ps.executeQuery();
153 rows = buildRows(rs);
154 return rows;
155 }
156 catch (SQLException ex)
157 {
158 throw new DataAccessException(
159 buildMessage(strSQL, queryParameters),
160 ex);
161 }
162 finally
163 {
164 close(conn, rs, ps);
165 }
166
167 }
168
169 protected int getFetchSize()
170 {
171 return fetchSize;
172 }
173
174 protected void setFetchSize(int size)
175 {
176 this.fetchSize = size;
177 }
178
179 protected List<Row> buildRows(ResultSet rs) throws SQLException
180 {
181 List<Row> rows = new LinkedList<Row>();
182
183 while (rs.next())
184 {
185 Row r = buildSingleRow(rs);
186 rows.add(r);
187 }
188
189 return rows;
190 }
191
192 protected Row buildSingleRow(ResultSet rs) throws SQLException
193 {
194
195
196
197 ResultSetMetaData metaData = rs.getMetaData();
198
199 int colCount = metaData.getColumnCount();
200 IndexedMap<String, Object> map = new IndexedMapImpl<String, Object>(colCount);
201 for (int colIndex = 1; colIndex < colCount; colIndex++)
202 {
203 String colName = metaData.getColumnName(colIndex).toUpperCase();
204 Object colValue = rs.getObject(colIndex);
205 map.put(colName, colValue);
206 }
207 return new Row(map);
208 }
209
210 protected boolean getCloseQuietly()
211 {
212 return closeQuietly;
213 }
214
215 protected void setCloseQuietly(boolean b)
216 {
217 closeQuietly = b;
218 }
219
220 protected void close(Connection c, ResultSet rs, Statement st)
221 {
222 Exception caught = null;
223
224 try
225 {
226 if (rs != null)
227 {
228 rs.close();
229 }
230 }
231 catch (Exception ex)
232 {
233 caught = ex;
234 }
235 try
236 {
237 if (st != null)
238 {
239 st.close();
240 }
241 }
242 catch (Exception ex)
243 {
244 caught = ex;
245 }
246 try
247 {
248 if (c != null)
249 {
250 c.close();
251 }
252 }
253 catch (Exception ex)
254 {
255 caught = ex;
256 }
257
258 if ( ( ! getCloseQuietly()) && (caught != null) )
259 {
260 throw new DataAccessException(caught);
261 }
262 }
263
264
265 abstract protected Connection getConnection() throws SQLException;
266
267 protected void setPreparedStatementParameters(PreparedStatement ps, Object[] parameters)
268 throws SQLException
269 {
270 for (int i = 0; i < parameters.length; i++)
271 {
272 int parameterIndex = i + 1;
273 Object param = parameters[i];
274 if (param == null)
275 {
276 ps.setObject(parameterIndex, param);
277 }
278 else if (param instanceof java.sql.Time)
279 {
280 ps.setTime(parameterIndex, (java.sql.Time) param);
281 }
282 else if (param instanceof java.sql.Timestamp)
283 {
284 ps.setTimestamp(parameterIndex, (java.sql.Timestamp) param);
285 }
286 else if (param instanceof java.sql.Date)
287 {
288 java.sql.Date value = (java.sql.Date) param;
289 ps.setDate(parameterIndex, value);
290 }
291 else if (param instanceof java.util.Date)
292 {
293 long time = ((java.util.Date) param).getTime();
294 java.sql.Date value = new java.sql.Date(time);
295 ps.setDate(parameterIndex, value);
296 }
297 else if (param instanceof java.util.Calendar)
298 {
299 Calendar c = (Calendar) param;
300 java.sql.Date d = new java.sql.Date(c.getTime().getTime());
301 ps.setDate(parameterIndex, d, c);
302 }
303 else if (param instanceof String)
304 {
305 ps.setString(parameterIndex, (String) param);
306 }
307 else if (param instanceof CharSequence)
308 {
309 String value = param.toString();
310 ps.setString(parameterIndex, value);
311 }
312 else if (param instanceof char[])
313 {
314 String value = new String( (char[]) param );
315 ps.setString(parameterIndex, value);
316 }
317 else if (param instanceof Character)
318 {
319 ps.setString(parameterIndex, String.valueOf(param));
320 }
321 else if (param instanceof Enum)
322 {
323 Enum e = (Enum) param;
324 int value = e.ordinal();
325 ps.setInt(parameterIndex, value);
326 }
327 else if (param instanceof Integer)
328 {
329 int value = ((Integer) param).intValue();
330 ps.setInt(parameterIndex, value);
331 }
332 else if (param instanceof Short)
333 {
334 short value = ((Short) param).shortValue();
335 ps.setShort(parameterIndex, value);
336 }
337 else if (param instanceof Long)
338 {
339 long value = ((Long) param).longValue();
340 ps.setLong(parameterIndex, value);
341 }
342 else if (param instanceof BigDecimal)
343 {
344 BigDecimal value = (BigDecimal) param;
345 ps.setBigDecimal(parameterIndex, value);
346 }
347 else if (param instanceof java.sql.Ref)
348 {
349 Ref value = (Ref) param;
350 ps.setRef(i, value);
351 }
352 else if (param instanceof Double)
353 {
354 double value = ((Double) param).doubleValue();
355 ps.setDouble(parameterIndex, value);
356 }
357 else if (param instanceof Float)
358 {
359 float value = ((Float) param).floatValue();
360 ps.setFloat(parameterIndex, value);
361 }
362 else if (param instanceof Boolean)
363 {
364 boolean value = ((Boolean) param).booleanValue();
365 ps.setBoolean(parameterIndex, value);
366 }
367 else if (param instanceof java.sql.Array)
368 {
369 ps.setArray(parameterIndex, (java.sql.Array) param);
370 }
371 else if (param instanceof java.net.URL)
372 {
373 ps.setURL(parameterIndex, (java.net.URL) param);
374 }
375 else if (param instanceof byte[])
376 {
377 ps.setBytes(parameterIndex, (byte[]) param);
378 }
379 else if (param instanceof Clob)
380 {
381 ps.setClob(parameterIndex, (Clob) param);
382 }
383 else if (param instanceof Blob)
384 {
385 ps.setBlob(parameterIndex, (Blob) param);
386 }
387 else if (param instanceof Byte)
388 {
389 byte value = ((Byte) param).byteValue();
390 ps.setByte(parameterIndex, value);
391 }
392 else
393 {
394 throw new IllegalArgumentException("unexpected parameter type: "
395 + param.getClass());
396 }
397 }
398 }
399
400 protected String buildMessage(CharSequence sql, Object[] queryParameters)
401 {
402 StringBuffer sb = new StringBuffer();
403 sb.append(sql);
404 if (queryParameters.length > 0)
405 {
406 sb.append(",");
407 for (Object o : queryParameters)
408 {
409 sb.append(" [");
410 sb.append(o);
411 sb.append("] ");
412 }
413 }
414 return sb.toString();
415 }
416
417 protected int getQueryTimeout()
418 {
419 return queryTimeout;
420 }
421
422 protected void setQueryTimeout(int value)
423 {
424 queryTimeout = value;
425 }
426
427 protected int getMaxRows()
428 {
429 return maxRows;
430 }
431
432
433 protected void setMaxRows(int value)
434 {
435 this.maxRows = value;
436 }
437
438 public String toString()
439 {
440 return "QueryTimeout="
441 + getQueryTimeout()
442 + ",FetchSize="
443 + getFetchSize()
444 + ",MaxRows="
445 + getMaxRows();
446 }
447
448 protected int getResultSetType()
449 {
450 return this.resultSetType;
451 }
452
453 protected void setResultSetType(int value)
454 {
455 this.resultSetType = value;
456 }
457
458 protected int getResultSetConcurrency()
459 {
460 return resultSetConcurrency;
461 }
462
463 protected void setResultSetConcurrency(int resultSetConcurrency)
464 {
465 this.resultSetConcurrency = resultSetConcurrency;
466 }
467
468 }