001: /*
002: * $Id: SQLProcessor.java,v 1.8 2004/02/16 19:07:58 jonesde Exp $
003: *
004: * Copyright (c) 2001, 2002 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: */
024: package org.ofbiz.entity.jdbc;
025:
026: import java.io.ByteArrayInputStream;
027: import java.io.ByteArrayOutputStream;
028: import java.io.IOException;
029: import java.io.ObjectOutputStream;
030: import java.sql.*;
031: import java.util.ArrayList;
032: import java.util.List;
033: import java.util.Map;
034:
035: import org.ofbiz.base.util.Debug;
036: import org.ofbiz.entity.GenericDataSourceException;
037: import org.ofbiz.entity.GenericEntityException;
038: import org.ofbiz.entity.transaction.GenericTransactionException;
039: import org.ofbiz.entity.transaction.TransactionUtil;
040:
041: /**
042: * SQLProcessor - provides utitlity functions to ease database access
043: *
044: * @author <a href="mailto:jonesde@ofbiz.org">David E. Jones</a>
045: * @version $Revision: 1.8 $
046: * @since 2.0
047: */
048: public class SQLProcessor {
049:
050: /** Module Name Used for debugging */
051: public static final String module = SQLProcessor.class.getName();
052:
053: /** Used for testing connections when test is enabled */
054: public static List CONNECTION_TEST_LIST = new ArrayList();
055: public static int MAX_CONNECTIONS = 1000;
056: public static boolean ENABLE_TEST = false;
057:
058: /** The datasource helper (see entityengine.xml <datasource name="..">) */
059: private String helperName;
060:
061: // / The database resources to be used
062: private Connection _connection = null;
063:
064: // / The database resources to be used
065: private PreparedStatement _ps = null;
066:
067: // / The database resources to be used
068: private Statement _stmt = null;
069:
070: // / The database resources to be used
071: private ResultSet _rs = null;
072:
073: private ResultSetMetaData _rsmd = null;
074:
075: // / The SQL String used. Use for debugging only
076: private String _sql;
077:
078: // / Index to be used with preparedStatement.setValue(_ind, ...)
079: private int _ind;
080:
081: // / true in case of manual transactions
082: private boolean _manualTX;
083:
084: // / true in case the connection shall be closed.
085: private boolean _bDeleteConnection = false;
086:
087: private Map _needClobWorkAroundWrite = null;
088: private Map _needBlobWorkAroundWrite = null;
089:
090: /**
091: * Construct an object based on the helper/datasource
092: *
093: * @param helperName The datasource helper (see entityengine.xml <datasource name="..">)
094: */
095: public SQLProcessor(String helperName) {
096: this .helperName = helperName;
097: this ._manualTX = true;
098: }
099:
100: /**
101: * Construct an object with an connection given. The connection will not
102: * be closed by this SQLProcessor, but may be by some other.
103: *
104: * @param helperName The datasource helper (see entityengine.xml <datasource name="..">)
105: * @param connection The connection to be used
106: */
107: public SQLProcessor(String helperName, Connection connection) {
108: this .helperName = helperName;
109: this ._connection = connection;
110:
111: // Do not commit while closing
112: if (_connection != null) {
113: _manualTX = false;
114: }
115: }
116:
117: ResultSetMetaData getResultSetMetaData() {
118: if (_rsmd == null) {
119: // try the ResultSet, if not null, or try the PreparedStatement, also if not null
120: try {
121: if (_rs != null) {
122: _rsmd = _rs.getMetaData();
123: } else if (_ps != null) {
124: _rsmd = _ps.getMetaData();
125: }
126: } catch (SQLException sqle2) {
127: Debug.logWarning(
128: "[SQLProcessor.rollback]: SQL Exception while rolling back insert. Error was:"
129: + sqle2, module);
130: Debug.logWarning(sqle2, module);
131: }
132: }
133: return _rsmd;
134: }
135:
136: /**
137: * Commit all modifications
138: *
139: * @throws GenericDataSourceException
140: */
141: public void commit() throws GenericDataSourceException {
142: if (_connection == null) {
143: return;
144: }
145:
146: if (Debug.verboseOn())
147: Debug.logVerbose("SQLProcessor:commit() _manualTX="
148: + _manualTX, module);
149:
150: if (_manualTX) {
151: try {
152: _connection.commit();
153: if (Debug.verboseOn())
154: Debug
155: .logVerbose(
156: "SQLProcessor:commit() : called commit on connection",
157: module);
158: } catch (SQLException sqle) {
159: rollback();
160: throw new GenericDataSourceException(
161: "SQL Exception occurred on commit", sqle);
162: }
163: }
164: }
165:
166: /**
167: * Rollback all modifications
168: */
169: public void rollback() throws GenericDataSourceException {
170: if (_connection == null) {
171: return;
172: }
173:
174: if (Debug.verboseOn())
175: Debug.logVerbose("SQLProcessor:rollback() _manualTX="
176: + _manualTX, module);
177:
178: try {
179: if (_manualTX) {
180: _connection.rollback();
181: if (Debug.verboseOn())
182: Debug.logVerbose(
183: "SQLProcessor:rollback() : _manualTX="
184: + _manualTX, module);
185: } else {
186: try {
187: TransactionUtil.setRollbackOnly();
188: if (Debug.verboseOn())
189: Debug.logVerbose(
190: "SQLProcessor:rollback() : _manualTX="
191: + _manualTX, module);
192: } catch (GenericTransactionException e) {
193: Debug.logError(e, "Error setting rollback only",
194: module);
195: throw new GenericDataSourceException(
196: "Error setting rollback only", e);
197: }
198: }
199: } catch (SQLException sqle2) {
200: Debug.logWarning(
201: "[SQLProcessor.rollback]: SQL Exception while rolling back insert. Error was:"
202: + sqle2, module);
203: Debug.logWarning(sqle2, module);
204: }
205: }
206:
207: /**
208: * Commit if required and remove all allocated resources
209: *
210: * @throws GenericDataSourceException
211: */
212: public void close() throws GenericDataSourceException {
213: if (_manualTX) {
214: if (Debug.verboseOn())
215: Debug.logVerbose(
216: "SQLProcessor:close() calling commit : _manualTX="
217: + _manualTX, module);
218: commit();
219: }
220:
221: _sql = null;
222:
223: if (_rs != null) {
224: try {
225: _rs.close();
226: if (Debug.verboseOn())
227: Debug.logVerbose(
228: "SQLProcessor:close() result close : _manualTX="
229: + _manualTX, module);
230: } catch (SQLException sqle) {
231: Debug.logWarning(sqle.getMessage(), module);
232: }
233:
234: _rs = null;
235: }
236:
237: if (_ps != null) {
238: try {
239: _ps.close();
240: if (Debug.verboseOn())
241: Debug.logVerbose(
242: "SQLProcessor:close() preparedStatement close : _manualTX="
243: + _manualTX, module);
244: } catch (SQLException sqle) {
245: Debug.logWarning(sqle.getMessage(), module);
246: }
247:
248: _ps = null;
249: }
250:
251: if (_stmt != null) {
252: try {
253: _stmt.close();
254: if (Debug.verboseOn())
255: Debug.logVerbose(
256: "SQLProcessor:close() statement close : _manualTX="
257: + _manualTX, module);
258: } catch (SQLException sqle) {
259: Debug.logWarning(sqle.getMessage(), module);
260: }
261:
262: _stmt = null;
263: }
264:
265: if ((_connection != null) && _bDeleteConnection) {
266: try {
267: _connection.close();
268: if (Debug.verboseOn())
269: Debug.logVerbose(
270: "SQLProcessor:close() connection close : _manualTX="
271: + _manualTX, module);
272: } catch (SQLException sqle) {
273: Debug.logWarning(sqle.getMessage(), module);
274: }
275:
276: _connection = null;
277: }
278: }
279:
280: /**
281: * Get a connection from the ConnectionFactory
282: *
283: * @return The connection created
284: *
285: * @throws GenericDataSourceException
286: * @throws GenericEntityException
287: */
288: public Connection getConnection()
289: throws GenericDataSourceException, GenericEntityException {
290: if (_connection != null)
291: return _connection;
292:
293: _manualTX = true;
294:
295: try {
296: _connection = ConnectionFactory.getConnection(helperName);
297: if (Debug.verboseOn())
298: Debug.logVerbose(
299: "SQLProcessor:connection() : manualTx="
300: + _manualTX, module);
301: } catch (SQLException sqle) {
302: throw new GenericDataSourceException(
303: "Unable to esablish a connection with the database.",
304: sqle);
305: }
306:
307: testConnection(_connection);
308:
309: /* causes problems w/ postgres ??
310: if (Debug.verboseOn()) {
311: int isoLevel = -999;
312: try {
313: isoLevel = _connection.getTransactionIsolation();
314: } catch (SQLException e) {
315: Debug.logError(e, "Problems getting the connection's isolation level", module);
316: }
317: if (isoLevel == Connection.TRANSACTION_NONE) {
318: Debug.logVerbose("Transaction isolation level set to 'None'.", module);
319: } else if (isoLevel == Connection.TRANSACTION_READ_COMMITTED) {
320: Debug.logVerbose("Transaction isolation level set to 'ReadCommited'.", module);
321: } else if (isoLevel == Connection.TRANSACTION_READ_UNCOMMITTED) {
322: Debug.logVerbose("Transaction isolation level set to 'ReadUncommitted'.", module);
323: } else if (isoLevel == Connection.TRANSACTION_REPEATABLE_READ) {
324: Debug.logVerbose("Transaction isolation level set to 'RepeatableRead'.", module);
325: } else if (isoLevel == Connection.TRANSACTION_SERIALIZABLE) {
326: Debug.logVerbose("Transaction isolation level set to 'Serializable'.", module);
327: }
328: }
329: */
330:
331: // always try to set auto commit to false, but if we can't then later on we won't commit
332: try {
333: if (_connection.getAutoCommit()) {
334: try {
335: _connection.setAutoCommit(false);
336: if (Debug.verboseOn())
337: Debug.logVerbose(
338: "SQLProcessor:setAutoCommit(false) : manualTx="
339: + _manualTX, module);
340: } catch (SQLException sqle) {
341: _manualTX = false;
342: }
343: }
344: } catch (SQLException e) {
345: throw new GenericDataSourceException(
346: "Cannot get autoCommit status from connection", e);
347: }
348:
349: try {
350: if (TransactionUtil.getStatus() == TransactionUtil.STATUS_ACTIVE) {
351: if (Debug.verboseOn())
352: Debug
353: .logVerbose(
354: "[SQLProcessor.getConnection] : active transaction",
355: module);
356: _manualTX = false;
357: }
358: } catch (GenericTransactionException e) {
359: // nevermind, don't worry about it, but print the exc anyway
360: Debug.logWarning(
361: "[SQLProcessor.getConnection]: Exception was thrown trying to check "
362: + "transaction status: " + e.toString(),
363: module);
364: }
365:
366: if (Debug.verboseOn())
367: Debug.logVerbose("[SQLProcessor.getConnection] : con="
368: + _connection, module);
369:
370: _bDeleteConnection = true;
371: return _connection;
372: }
373:
374: /**
375: * Prepare a statement. In case no connection has been given, allocate a
376: * new one.
377: *
378: * @param sql The SQL statement to be executed
379: *
380: * @throws GenericDataSourceException
381: * @throws GenericEntityException
382: */
383: public void prepareStatement(String sql)
384: throws GenericDataSourceException, GenericEntityException {
385: this .prepareStatement(sql, false, 0, 0);
386: }
387:
388: /**
389: * Prepare a statement. In case no connection has been given, allocate a
390: * new one.
391: *
392: * @param sql The SQL statement to be executed
393: *
394: * @throws GenericDataSourceException
395: * @throws GenericEntityException
396: */
397: public void prepareStatement(String sql,
398: boolean specifyTypeAndConcur, int resultSetType,
399: int resultSetConcurrency)
400: throws GenericDataSourceException, GenericEntityException {
401: if (Debug.verboseOn())
402: Debug.logVerbose("[SQLProcessor.prepareStatement] sql="
403: + sql, module);
404:
405: if (_connection == null) {
406: getConnection();
407: }
408:
409: try {
410: _sql = sql;
411: _ind = 1;
412: if (specifyTypeAndConcur) {
413: _ps = _connection.prepareStatement(sql, resultSetType,
414: resultSetConcurrency);
415: if (Debug.verboseOn())
416: Debug.logVerbose(
417: "[SQLProcessor.prepareStatement] _ps="
418: + _ps, module);
419: } else {
420: _ps = _connection.prepareStatement(sql);
421: if (Debug.verboseOn())
422: Debug.logVerbose(
423: "[SQLProcessor.prepareStatement] (def) _ps="
424: + _ps, module);
425: }
426: } catch (SQLException sqle) {
427: throw new GenericDataSourceException(
428: "SQL Exception while executing the following:"
429: + sql, sqle);
430: }
431: }
432:
433: /**
434: * Execute a query based on the prepared statement
435: *
436: * @return The result set of the query
437: * @throws GenericDataSourceException
438: */
439: public ResultSet executeQuery() throws GenericDataSourceException {
440: try {
441: // if (Debug.verboseOn()) Debug.logVerbose("[SQLProcessor.executeQuery] ps=" + _ps.toString(), module);
442: _rs = _ps.executeQuery();
443: } catch (SQLException sqle) {
444: throw new GenericDataSourceException(
445: "SQL Exception while executing the following:"
446: + _sql, sqle);
447: }
448:
449: return _rs;
450: }
451:
452: /**
453: * Execute a query baed ont SQL string given
454: *
455: * @param sql The SQL string to be executed
456: * @return The result set of the query
457: * @throws GenericEntityException
458: * @throws GenericDataSourceException
459: */
460: public ResultSet executeQuery(String sql)
461: throws GenericDataSourceException, GenericEntityException {
462: prepareStatement(sql);
463: return executeQuery();
464: }
465:
466: /**
467: * Execute updates
468: *
469: * @return The number of rows updated
470: * @throws GenericDataSourceException
471: */
472: public int executeUpdate() throws GenericDataSourceException {
473: try {
474: // if (Debug.verboseOn()) Debug.logVerbose("[SQLProcessor.executeUpdate] ps=" + _ps.toString(), module);
475: return _ps.executeUpdate();
476: } catch (SQLException sqle) {
477: // don't display this here, may not be critical, allow handling further up... Debug.logError(sqle, "SQLProcessor.executeUpdate() : ERROR : ", module);
478: throw new GenericDataSourceException(
479: "SQL Exception while executing the following:"
480: + _sql, sqle);
481: }
482: }
483:
484: /**
485: * Execute update based on the SQL statement given
486: *
487: * @param sql SQL statement to be executed
488: * @throws GenericDataSourceException
489: */
490: public int executeUpdate(String sql)
491: throws GenericDataSourceException {
492: Statement stmt = null;
493:
494: try {
495: stmt = _connection.createStatement();
496: return stmt.executeUpdate(sql);
497: } catch (SQLException sqle) {
498: Debug.logError(sqle,
499: "SQLProcessor.executeUpdate(sql) : ERROR : ",
500: module);
501: throw new GenericDataSourceException(
502: "SQL Exception while executing the following:"
503: + _sql, sqle);
504: } finally {
505: if (stmt != null) {
506: try {
507: stmt.close();
508: } catch (SQLException sqle) {
509: Debug.logWarning("Unable to close 'statement': "
510: + sqle.getMessage(), module);
511: }
512: }
513: }
514: }
515:
516: /**
517: * Test if there more records available
518: *
519: * @return true, if there more records available
520: *
521: * @throws GenericDataSourceException
522: */
523: public boolean next() throws GenericDataSourceException {
524: try {
525: return _rs.next();
526: } catch (SQLException sqle) {
527: throw new GenericDataSourceException(
528: "SQL Exception while executing the following:"
529: + _sql, sqle);
530: }
531: }
532:
533: /**
534: * Getter: get the currently activ ResultSet
535: *
536: * @return ResultSet
537: */
538: public ResultSet getResultSet() {
539: return _rs;
540: }
541:
542: /**
543: * Getter: get the prepared statement
544: *
545: * @return PreparedStatement
546: */
547: public PreparedStatement getPreparedStatement() {
548: return _ps;
549: }
550:
551: /**
552: * Execute a query based on the SQL string given. For each record
553: * of the ResultSet return, execute a callback function
554: *
555: * @param sql The SQL string to be executed
556: * @param aListener The callback function object
557: *
558: * @throws GenericEntityException
559: */
560: public void execQuery(String sql,
561: ExecQueryCallbackFunctionIF aListener)
562: throws GenericEntityException {
563: if (_connection == null) {
564: getConnection();
565: }
566:
567: try {
568: if (Debug.verboseOn())
569: Debug.logVerbose("[SQLProcessor.execQuery]: " + sql,
570: module);
571: executeQuery(sql);
572:
573: // process the results by calling the listener for
574: // each row...
575: boolean keepGoing = true;
576:
577: while (keepGoing && _rs.next()) {
578: keepGoing = aListener.processNextRow(_rs);
579: }
580:
581: if (_manualTX) {
582: _connection.commit();
583: }
584:
585: } catch (SQLException sqle) {
586: Debug.logWarning(
587: "[SQLProcessor.execQuery]: SQL Exception while executing the following:\n"
588: + sql + "\nError was:", module);
589: Debug.logWarning(sqle.getMessage(), module);
590: throw new GenericEntityException(
591: "SQL Exception while executing the following:"
592: + _sql, sqle);
593: } finally {
594: close();
595: }
596: }
597:
598: /**
599: * Set the next binding variable of the currently active prepared statement.
600: *
601: * @param field
602: *
603: * @throws SQLException
604: */
605: public void setValue(String field) throws SQLException {
606: //ResultSetMetaData rsmd = this.getResultSetMetaData();
607: //this doesn't seem to work, query not yet parsed: int colType = rsmd.getColumnType(_ind);
608: if (field != null) {
609: //if (field.length() > 4000) {
610: //Clob clb = new Cl
611: // doesn't work with Oracle drivers, need the funky work-around: _ps.setCharacterStream(_ind, new StringReader(field), field.length());
612: //_needClobWorkAroundWrite.put(new Integer(_ind), field);
613: //_ps.setString(_ind, " ");
614: //} else {
615: _ps.setString(_ind, field);
616: //}
617: } else {
618: _ps.setNull(_ind, Types.VARCHAR);
619: }
620: _ind++;
621: }
622:
623: /**
624: * Set the next binding variable of the currently active prepared statement.
625: *
626: * @param field
627: *
628: * @throws SQLException
629: */
630: public void setValue(java.sql.Timestamp field) throws SQLException {
631: if (field != null) {
632: _ps.setTimestamp(_ind, field);
633: } else {
634: _ps.setNull(_ind, Types.TIMESTAMP);
635: }
636: _ind++;
637: }
638:
639: /**
640: * Set the next binding variable of the currently active prepared statement.
641: *
642: * @param field
643: *
644: * @throws SQLException
645: */
646: public void setValue(java.sql.Time field) throws SQLException {
647: if (field != null) {
648: _ps.setTime(_ind, field);
649: } else {
650: _ps.setNull(_ind, Types.TIME);
651: }
652: _ind++;
653: }
654:
655: /**
656: * Set the next binding variable of the currently active prepared statement.
657: *
658: * @param field
659: *
660: * @throws SQLException
661: */
662: public void setValue(java.sql.Date field) throws SQLException {
663: if (field != null) {
664: _ps.setDate(_ind, field);
665: } else {
666: _ps.setNull(_ind, Types.DATE);
667: }
668: _ind++;
669: }
670:
671: /**
672: * Set the next binding variable of the currently active prepared statement.
673: *
674: * @param field
675: *
676: * @throws SQLException
677: */
678: public void setValue(Integer field) throws SQLException {
679: if (field != null) {
680: _ps.setInt(_ind, field.intValue());
681: } else {
682: _ps.setNull(_ind, Types.NUMERIC);
683: }
684: _ind++;
685: }
686:
687: /**
688: * Set the next binding variable of the currently active prepared statement.
689: *
690: * @param field
691: *
692: * @throws SQLException
693: */
694: public void setValue(Long field) throws SQLException {
695: if (field != null) {
696: _ps.setLong(_ind, field.longValue());
697: } else {
698: _ps.setNull(_ind, Types.NUMERIC);
699: }
700: _ind++;
701: }
702:
703: /**
704: * Set the next binding variable of the currently active prepared statement.
705: *
706: * @param field
707: *
708: * @throws SQLException
709: */
710: public void setValue(Float field) throws SQLException {
711: if (field != null) {
712: _ps.setFloat(_ind, field.floatValue());
713: } else {
714: _ps.setNull(_ind, Types.NUMERIC);
715: }
716: _ind++;
717: }
718:
719: /**
720: * Set the next binding variable of the currently active prepared statement.
721: *
722: * @param field
723: *
724: * @throws SQLException
725: */
726: public void setValue(Double field) throws SQLException {
727: if (field != null) {
728: _ps.setDouble(_ind, field.doubleValue());
729: } else {
730: _ps.setNull(_ind, Types.NUMERIC);
731: }
732: _ind++;
733: }
734:
735: /**
736: * Set the next binding variable of the currently active prepared statement.
737: *
738: * @param field
739: *
740: * @throws SQLException
741: */
742: public void setValue(Boolean field) throws SQLException {
743: if (field != null) {
744: _ps.setBoolean(_ind, field.booleanValue());
745: } else {
746: _ps.setNull(_ind, Types.NULL); // TODO: really should be Types.BOOLEAN, but that wasn't introduced until Java 1.4... hmmm what to do?
747: }
748: _ind++;
749: }
750:
751: /**
752: * Set the next binding variable of the currently active prepared statement.
753: *
754: * @param field
755: *
756: * @throws SQLException
757: */
758: public void setValue(Object field) throws SQLException {
759: if (field != null) {
760: _ps.setObject(_ind, field, Types.JAVA_OBJECT);
761: } else {
762: _ps.setNull(_ind, Types.JAVA_OBJECT);
763: }
764: _ind++;
765: }
766:
767: /**
768: * Set the next binding variable of the currently active prepared statement
769: *
770: * @param field
771: *
772: * @throws SQLException
773: */
774: public void setValue(Blob field) throws SQLException {
775: if (field != null) {
776: _ps.setBlob(_ind, field);
777: } else {
778: _ps.setNull(_ind, Types.BLOB);
779: }
780: _ind++;
781: }
782:
783: /**
784: * Set the next binding variable of the currently active prepared statement
785: *
786: * @param field
787: *
788: * @throws SQLException
789: */
790: public void setValue(Clob field) throws SQLException {
791: if (field != null) {
792: _ps.setClob(_ind, field);
793: } else {
794: _ps.setNull(_ind, Types.CLOB);
795: }
796: _ind++;
797: }
798:
799: /**
800: * Set the next binding variable of the currently active prepared statement
801: * to write the serialized data of 'field' to a BLOB.
802: *
803: * @param field
804: *
805: * @throws SQLException
806: */
807: public void setBinaryStream(Object field) throws SQLException {
808: if (field != null) {
809: try {
810: ByteArrayOutputStream os = new ByteArrayOutputStream();
811: ObjectOutputStream oos = new ObjectOutputStream(os);
812: oos.writeObject(field);
813: oos.close();
814:
815: byte[] buf = os.toByteArray();
816: os.close();
817: ByteArrayInputStream is = new ByteArrayInputStream(buf);
818: _ps.setBinaryStream(_ind, is, buf.length);
819: is.close();
820: } catch (IOException ex) {
821: throw new SQLException(ex.getMessage());
822: }
823: } else {
824: _ps.setNull(_ind, Types.BLOB);
825: }
826:
827: _ind++;
828: }
829:
830: protected void finalize() throws Throwable {
831: try {
832: this .close();
833: } catch (Exception e) {
834: Debug
835: .logError(
836: e,
837: "Error closing the result, connection, etc in finalize SQLProcessor",
838: module);
839: }
840: super .finalize();
841: }
842:
843: protected void testConnection(Connection con)
844: throws GenericEntityException {
845: if (SQLProcessor.ENABLE_TEST) {
846: if (SQLProcessor.CONNECTION_TEST_LIST.contains(con
847: .toString())) {
848: throw new GenericEntityException(
849: "Connection the exact same as index "
850: + SQLProcessor.CONNECTION_TEST_LIST
851: .indexOf(con.toString()));
852: }
853: SQLProcessor.CONNECTION_TEST_LIST.add(con.toString());
854: if (SQLProcessor.CONNECTION_TEST_LIST.size() > SQLProcessor.MAX_CONNECTIONS) {
855: SQLProcessor.CONNECTION_TEST_LIST.remove(0);
856: }
857: }
858: }
859: }
|