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