001: package org.apache.ojb.broker.accesslayer;
002:
003: /* Copyright 2002-2005 The Apache Software Foundation
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: import java.sql.CallableStatement;
019: import java.sql.PreparedStatement;
020: import java.sql.ResultSet;
021: import java.sql.SQLException;
022: import java.sql.Statement;
023: import java.sql.Types;
024: import java.util.Collection;
025: import java.util.Enumeration;
026: import java.util.Iterator;
027:
028: import org.apache.ojb.broker.Identity;
029: import org.apache.ojb.broker.PersistenceBroker;
030: import org.apache.ojb.broker.PersistenceBrokerException;
031: import org.apache.ojb.broker.PersistenceBrokerSQLException;
032: import org.apache.ojb.broker.core.ValueContainer;
033: import org.apache.ojb.broker.metadata.ArgumentDescriptor;
034: import org.apache.ojb.broker.metadata.ClassDescriptor;
035: import org.apache.ojb.broker.metadata.FieldDescriptor;
036: import org.apache.ojb.broker.metadata.ProcedureDescriptor;
037: import org.apache.ojb.broker.platforms.Platform;
038: import org.apache.ojb.broker.platforms.PlatformException;
039: import org.apache.ojb.broker.platforms.PlatformFactory;
040: import org.apache.ojb.broker.query.BetweenCriteria;
041: import org.apache.ojb.broker.query.Criteria;
042: import org.apache.ojb.broker.query.ExistsCriteria;
043: import org.apache.ojb.broker.query.FieldCriteria;
044: import org.apache.ojb.broker.query.InCriteria;
045: import org.apache.ojb.broker.query.NullCriteria;
046: import org.apache.ojb.broker.query.Query;
047: import org.apache.ojb.broker.query.SelectionCriteria;
048: import org.apache.ojb.broker.query.SqlCriteria;
049: import org.apache.ojb.broker.util.logging.Logger;
050: import org.apache.ojb.broker.util.logging.LoggerFactory;
051:
052: /**
053: * manages JDBC Connection and Statement resources.
054: *
055: * @author Thomas Mahler
056: * @author <a href="mailto:rburt3@mchsi.com">Randall Burt</a>
057: * @version $Id: StatementManager.java,v 1.47.2.5 2005/06/04 14:13:43 arminw Exp $
058: */
059: public class StatementManager implements StatementManagerIF {
060: private Logger m_log = LoggerFactory
061: .getLogger(StatementManager.class);
062:
063: /** the associated broker */
064: private final PersistenceBroker m_broker;
065: private Platform m_platform;
066: /**
067: * Used when OJB run in JBoss
068: * TODO: Find a better solution to handle OJB within JBoss
069: * --> the JCA implementation should solve this problem
070: *
071: * arminw:
072: * Seems with JBoss 3.2.2 or higher the problem is gone, so we
073: * can deprecate this attribute sooner or later
074: */
075: private boolean m_eagerRelease;
076: private ConnectionManagerIF m_conMan;
077:
078: public StatementManager(final PersistenceBroker pBroker) {
079: this .m_broker = pBroker;
080: this .m_conMan = m_broker.serviceConnectionManager();
081: m_eagerRelease = m_conMan.getConnectionDescriptor()
082: .getEagerRelease();
083: m_platform = PlatformFactory.getPlatformFor(m_conMan
084: .getConnectionDescriptor());
085: }
086:
087: public void closeResources(Statement stmt, ResultSet rs) {
088: if (m_log.isDebugEnabled())
089: m_log.debug("closeResources was called");
090: try {
091: m_platform.beforeStatementClose(stmt, rs);
092: //close statement on wrapped statement class, or real statement
093: if (stmt != null) {
094: //log.info("## close: "+stmt);
095: stmt.close();
096:
097: /*
098: *********************************************
099: special stuff for OJB within JBoss
100: ********************************************
101: */
102: if (m_eagerRelease) {
103: m_conMan.releaseConnection();
104: }
105:
106: }
107: m_platform.afterStatementClose(stmt, rs);
108: } catch (PlatformException e) {
109: m_log.error("Platform dependent operation failed", e);
110: } catch (SQLException ignored) {
111: if (m_log.isDebugEnabled())
112: m_log.debug("Statement closing failed", ignored);
113: }
114: }
115:
116: /**
117: * binds the Identities Primary key values to the statement
118: */
119: public void bindDelete(PreparedStatement stmt, Identity oid,
120: ClassDescriptor cld) throws SQLException {
121: Object[] pkValues = oid.getPrimaryKeyValues();
122: FieldDescriptor[] pkFields = cld.getPkFields();
123: int i = 0;
124: try {
125: for (; i < pkValues.length; i++) {
126: setObjectForStatement(stmt, i + 1, pkValues[i],
127: pkFields[i].getJdbcType().getType());
128: }
129: } catch (SQLException e) {
130: m_log.error("bindDelete failed for: " + oid.toString()
131: + ", while set value '" + pkValues[i]
132: + "' for column " + pkFields[i].getColumnName());
133: throw e;
134: }
135: }
136:
137: /**
138: * binds the objects primary key and locking values to the statement, BRJ
139: */
140: public void bindDelete(PreparedStatement stmt, ClassDescriptor cld,
141: Object obj) throws SQLException {
142: if (cld.getDeleteProcedure() != null) {
143: this
144: .bindProcedure(stmt, cld, obj, cld
145: .getDeleteProcedure());
146: } else {
147: int index = 1;
148: ValueContainer[] values, currentLockingValues;
149:
150: currentLockingValues = cld.getCurrentLockingValues(obj);
151: // parameters for WHERE-clause pk
152: values = getKeyValues(m_broker, cld, obj);
153: for (int i = 0; i < values.length; i++) {
154: setObjectForStatement(stmt, index,
155: values[i].getValue(), values[i].getJdbcType()
156: .getType());
157: index++;
158: }
159:
160: // parameters for WHERE-clause locking
161: values = currentLockingValues;
162: for (int i = 0; i < values.length; i++) {
163: setObjectForStatement(stmt, index,
164: values[i].getValue(), values[i].getJdbcType()
165: .getType());
166: index++;
167: }
168: }
169: }
170:
171: /**
172: * bind attribute and value
173: * @param stmt
174: * @param index
175: * @param attributeOrQuery
176: * @param value
177: * @param cld
178: * @return
179: * @throws SQLException
180: */
181: private int bindStatementValue(PreparedStatement stmt, int index,
182: Object attributeOrQuery, Object value, ClassDescriptor cld)
183: throws SQLException {
184: FieldDescriptor fld = null;
185: // if value is a subQuery bind it
186: if (value instanceof Query) {
187: Query subQuery = (Query) value;
188: return bindStatement(stmt, subQuery, cld.getRepository()
189: .getDescriptorFor(subQuery.getSearchClass()), index);
190: }
191:
192: // if attribute is a subQuery bind it
193: if (attributeOrQuery instanceof Query) {
194: Query subQuery = (Query) attributeOrQuery;
195: bindStatement(stmt, subQuery, cld.getRepository()
196: .getDescriptorFor(subQuery.getSearchClass()), index);
197: } else {
198: fld = cld
199: .getFieldDescriptorForPath((String) attributeOrQuery);
200: }
201:
202: if (fld != null) {
203: // BRJ: use field conversions and platform
204: if (value != null) {
205: m_platform.setObjectForStatement(stmt, index, fld
206: .getFieldConversion().javaToSql(value), fld
207: .getJdbcType().getType());
208: } else {
209: m_platform.setNullForStatement(stmt, index, fld
210: .getJdbcType().getType());
211: }
212: } else {
213: if (value != null) {
214: stmt.setObject(index, value);
215: } else {
216: stmt.setNull(index, Types.NULL);
217: }
218: }
219:
220: return ++index; // increment before return
221: }
222:
223: /**
224: * bind SelectionCriteria
225: * @param stmt the PreparedStatement
226: * @param index the position of the parameter to bind
227: * @param crit the Criteria containing the parameter
228: * @param cld the ClassDescriptor
229: * @return next index for PreparedStatement
230: */
231: private int bindStatement(PreparedStatement stmt, int index,
232: SelectionCriteria crit, ClassDescriptor cld)
233: throws SQLException {
234: return bindStatementValue(stmt, index, crit.getAttribute(),
235: crit.getValue(), cld);
236: }
237:
238: /**
239: * bind NullCriteria
240: * @param stmt the PreparedStatement
241: * @param index the position of the parameter to bind
242: * @param crit the Criteria containing the parameter
243: * @return next index for PreparedStatement
244: */
245: private int bindStatement(PreparedStatement stmt, int index,
246: NullCriteria crit) {
247: return index;
248: }
249:
250: /**
251: * bind FieldCriteria
252: * @param stmt , the PreparedStatement
253: * @param index , the position of the parameter to bind
254: * @param crit , the Criteria containing the parameter
255: * @return next index for PreparedStatement
256: */
257: private int bindStatement(PreparedStatement stmt, int index,
258: FieldCriteria crit) {
259: return index;
260: }
261:
262: /**
263: * bind SqlCriteria
264: * @param stmt the PreparedStatement
265: * @param index the position of the parameter to bind
266: * @param crit the Criteria containing the parameter
267: * @return next index for PreparedStatement
268: */
269: private int bindStatement(PreparedStatement stmt, int index,
270: SqlCriteria crit) {
271: return index;
272: }
273:
274: /**
275: * bind BetweenCriteria
276: * @param stmt the PreparedStatement
277: * @param index the position of the parameter to bind
278: * @param crit the Criteria containing the parameter
279: * @param cld the ClassDescriptor
280: * @return next index for PreparedStatement
281: */
282: private int bindStatement(PreparedStatement stmt, int index,
283: BetweenCriteria crit, ClassDescriptor cld)
284: throws SQLException {
285: index = bindStatementValue(stmt, index, crit.getAttribute(),
286: crit.getValue(), cld);
287:
288: return bindStatementValue(stmt, index, crit.getAttribute(),
289: crit.getValue2(), cld);
290: }
291:
292: /**
293: * bind InCriteria
294: * @param stmt the PreparedStatement
295: * @param index the position of the parameter to bind
296: * @param crit the Criteria containing the parameter
297: * @param cld the ClassDescriptor
298: * @return next index for PreparedStatement
299: */
300: private int bindStatement(PreparedStatement stmt, int index,
301: InCriteria crit, ClassDescriptor cld) throws SQLException {
302: if (crit.getValue() instanceof Collection) {
303: Collection values = (Collection) crit.getValue();
304: Iterator iter = values.iterator();
305:
306: while (iter.hasNext()) {
307: index = bindStatementValue(stmt, index, crit
308: .getAttribute(), iter.next(), cld);
309: }
310: } else {
311: index = bindStatementValue(stmt, index,
312: crit.getAttribute(), crit.getValue(), cld);
313: }
314: return index;
315: }
316:
317: /**
318: * bind ExistsCriteria
319: * @param stmt the PreparedStatement
320: * @param index the position of the parameter to bind
321: * @param crit the Criteria containing the parameter
322: * @param cld the ClassDescriptor
323: * @return next index for PreparedStatement
324: */
325: private int bindStatement(PreparedStatement stmt, int index,
326: ExistsCriteria crit, ClassDescriptor cld)
327: throws SQLException {
328: Query subQuery = (Query) crit.getValue();
329:
330: // if query has criteria, bind them
331: if (subQuery.getCriteria() != null
332: && !subQuery.getCriteria().isEmpty()) {
333: return bindStatement(stmt, subQuery.getCriteria(), cld
334: .getRepository().getDescriptorFor(
335: subQuery.getSearchClass()), index);
336:
337: // otherwise, just ignore it
338: } else {
339: return index;
340: }
341: }
342:
343: /**
344: * bind a Query based Select Statement
345: */
346: public int bindStatement(PreparedStatement stmt, Query query,
347: ClassDescriptor cld, int param) throws SQLException {
348: int result;
349:
350: result = bindStatement(stmt, query.getCriteria(), cld, param);
351: result = bindStatement(stmt, query.getHavingCriteria(), cld,
352: result);
353:
354: return result;
355: }
356:
357: /**
358: * bind a Query based Select Statement
359: */
360: protected int bindStatement(PreparedStatement stmt, Criteria crit,
361: ClassDescriptor cld, int param) throws SQLException {
362: if (crit != null) {
363: Enumeration e = crit.getElements();
364:
365: while (e.hasMoreElements()) {
366: Object o = e.nextElement();
367: if (o instanceof Criteria) {
368: Criteria pc = (Criteria) o;
369: param = bindStatement(stmt, pc, cld, param);
370: } else {
371: SelectionCriteria c = (SelectionCriteria) o;
372: // BRJ : bind once for the criterion's main class
373: param = bindSelectionCriteria(stmt, param, c, cld);
374:
375: // BRJ : and once for each extent
376: for (int i = 0; i < c.getNumberOfExtentsToBind(); i++) {
377: param = bindSelectionCriteria(stmt, param, c,
378: cld);
379: }
380: }
381: }
382: }
383: return param;
384: }
385:
386: /**
387: * bind SelectionCriteria
388: * @param stmt the PreparedStatement
389: * @param index the position of the parameter to bind
390: * @param crit the Criteria containing the parameter
391: * @param cld the ClassDescriptor
392: * @return next index for PreparedStatement
393: */
394: private int bindSelectionCriteria(PreparedStatement stmt,
395: int index, SelectionCriteria crit, ClassDescriptor cld)
396: throws SQLException {
397: if (crit instanceof NullCriteria)
398: index = bindStatement(stmt, index, (NullCriteria) crit);
399: else if (crit instanceof BetweenCriteria)
400: index = bindStatement(stmt, index, (BetweenCriteria) crit,
401: cld);
402: else if (crit instanceof InCriteria)
403: index = bindStatement(stmt, index, (InCriteria) crit, cld);
404: else if (crit instanceof SqlCriteria)
405: index = bindStatement(stmt, index, (SqlCriteria) crit);
406: else if (crit instanceof FieldCriteria)
407: index = bindStatement(stmt, index, (FieldCriteria) crit);
408: else if (crit instanceof ExistsCriteria)
409: index = bindStatement(stmt, index, (ExistsCriteria) crit,
410: cld);
411: else
412: index = bindStatement(stmt, index, crit, cld);
413:
414: return index;
415: }
416:
417: /**
418: * binds the values of the object obj to the statements parameters
419: */
420: public void bindInsert(PreparedStatement stmt, ClassDescriptor cld,
421: Object obj) throws java.sql.SQLException {
422: ValueContainer[] values;
423: cld.updateLockingValues(obj); // BRJ : provide useful defaults for locking fields
424:
425: if (cld.getInsertProcedure() != null) {
426: this
427: .bindProcedure(stmt, cld, obj, cld
428: .getInsertProcedure());
429: } else {
430: values = getAllValues(cld, obj);
431: for (int i = 0; i < values.length; i++) {
432: setObjectForStatement(stmt, i + 1,
433: values[i].getValue(), values[i].getJdbcType()
434: .getType());
435: }
436: }
437: }
438:
439: /**
440: * Binds the Identities Primary key values to the statement.
441: */
442: public void bindSelect(PreparedStatement stmt, Identity oid,
443: ClassDescriptor cld, boolean callableStmt)
444: throws SQLException {
445: ValueContainer[] values = null;
446: int i = 0;
447: int j = 0;
448:
449: if (cld == null) {
450: cld = m_broker
451: .getClassDescriptor(oid.getObjectsRealClass());
452: }
453: try {
454: if (callableStmt) {
455: // First argument is the result set
456: m_platform.registerOutResultSet(
457: (CallableStatement) stmt, 1);
458: j++;
459: }
460:
461: values = getKeyValues(m_broker, cld, oid);
462: for (/*void*/; i < values.length; i++, j++) {
463: setObjectForStatement(stmt, j + 1,
464: values[i].getValue(), values[i].getJdbcType()
465: .getType());
466: }
467: } catch (SQLException e) {
468: m_log.error("bindSelect failed for: " + oid.toString()
469: + ", PK: " + i + ", value: " + values[i]);
470: throw e;
471: }
472: }
473:
474: /**
475: * binds the values of the object obj to the statements parameters
476: */
477: public void bindUpdate(PreparedStatement stmt, ClassDescriptor cld,
478: Object obj) throws java.sql.SQLException {
479: if (cld.getUpdateProcedure() != null) {
480: this
481: .bindProcedure(stmt, cld, obj, cld
482: .getUpdateProcedure());
483: } else {
484: int index = 1;
485: ValueContainer[] values, valuesSnapshot;
486: // first take a snapshot of current locking values
487: valuesSnapshot = cld.getCurrentLockingValues(obj);
488: cld.updateLockingValues(obj); // BRJ
489: values = getNonKeyValues(m_broker, cld, obj);
490:
491: // parameters for SET-clause
492: for (int i = 0; i < values.length; i++) {
493: setObjectForStatement(stmt, index,
494: values[i].getValue(), values[i].getJdbcType()
495: .getType());
496: index++;
497: }
498: // parameters for WHERE-clause pk
499: values = getKeyValues(m_broker, cld, obj);
500: for (int i = 0; i < values.length; i++) {
501: setObjectForStatement(stmt, index,
502: values[i].getValue(), values[i].getJdbcType()
503: .getType());
504: index++;
505: }
506: // parameters for WHERE-clause locking
507: // take old locking values
508: values = valuesSnapshot;
509: for (int i = 0; i < values.length; i++) {
510: setObjectForStatement(stmt, index,
511: values[i].getValue(), values[i].getJdbcType()
512: .getType());
513: index++;
514: }
515: }
516: }
517:
518: /**
519: * binds the given array of values (if not null) starting from the given
520: * parameter index
521: * @return the next parameter index
522: */
523: public int bindValues(PreparedStatement stmt,
524: ValueContainer[] values, int index) throws SQLException {
525: if (values != null) {
526: for (int i = 0; i < values.length; i++) {
527: setObjectForStatement(stmt, index,
528: values[i].getValue(), values[i].getJdbcType()
529: .getType());
530: index++;
531: }
532: }
533: return index;
534: }
535:
536: /**
537: * return a prepared DELETE Statement fitting for the given ClassDescriptor
538: */
539: public PreparedStatement getDeleteStatement(ClassDescriptor cld)
540: throws PersistenceBrokerSQLException,
541: PersistenceBrokerException {
542: try {
543: return cld.getStatementsForClass(m_conMan).getDeleteStmt(
544: m_conMan.getConnection());
545: } catch (SQLException e) {
546: throw new PersistenceBrokerSQLException(
547: "Could not build statement ask for", e);
548: } catch (LookupException e) {
549: throw new PersistenceBrokerException(
550: "Used ConnectionManager instance could not obtain a connection",
551: e);
552: }
553: }
554:
555: /**
556: * return a generic Statement for the given ClassDescriptor.
557: * Never use this method for UPDATE/INSERT/DELETE if you want to use the batch mode.
558: */
559: public Statement getGenericStatement(ClassDescriptor cds,
560: boolean scrollable) throws PersistenceBrokerException {
561: try {
562: return cds.getStatementsForClass(m_conMan).getGenericStmt(
563: m_conMan.getConnection(), scrollable);
564: } catch (LookupException e) {
565: throw new PersistenceBrokerException(
566: "Used ConnectionManager instance could not obtain a connection",
567: e);
568: }
569: }
570:
571: /**
572: * return a prepared Insert Statement fitting for the given ClassDescriptor
573: */
574: public PreparedStatement getInsertStatement(ClassDescriptor cds)
575: throws PersistenceBrokerSQLException,
576: PersistenceBrokerException {
577: try {
578: return cds.getStatementsForClass(m_conMan).getInsertStmt(
579: m_conMan.getConnection());
580: } catch (SQLException e) {
581: throw new PersistenceBrokerSQLException(
582: "Could not build statement ask for", e);
583: } catch (LookupException e) {
584: throw new PersistenceBrokerException(
585: "Used ConnectionManager instance could not obtain a connection",
586: e);
587: }
588: }
589:
590: /**
591: * return a generic Statement for the given ClassDescriptor
592: */
593: public PreparedStatement getPreparedStatement(ClassDescriptor cds,
594: String sql, boolean scrollable, int explicitFetchSizeHint,
595: boolean callableStmt) throws PersistenceBrokerException {
596: try {
597: return cds.getStatementsForClass(m_conMan).getPreparedStmt(
598: m_conMan.getConnection(), sql, scrollable,
599: explicitFetchSizeHint, callableStmt);
600: } catch (LookupException e) {
601: throw new PersistenceBrokerException(
602: "Used ConnectionManager instance could not obtain a connection",
603: e);
604: }
605: }
606:
607: /**
608: * return a prepared Select Statement for the given ClassDescriptor
609: */
610: public PreparedStatement getSelectByPKStatement(ClassDescriptor cds)
611: throws PersistenceBrokerSQLException,
612: PersistenceBrokerException {
613: try {
614: return cds.getStatementsForClass(m_conMan)
615: .getSelectByPKStmt(m_conMan.getConnection());
616: } catch (SQLException e) {
617: throw new PersistenceBrokerSQLException(
618: "Could not build statement ask for", e);
619: } catch (LookupException e) {
620: throw new PersistenceBrokerException(
621: "Used ConnectionManager instance could not obtain a connection",
622: e);
623: }
624: }
625:
626: /**
627: * return a prepared Update Statement fitting to the given ClassDescriptor
628: */
629: public PreparedStatement getUpdateStatement(ClassDescriptor cds)
630: throws PersistenceBrokerSQLException,
631: PersistenceBrokerException {
632: try {
633: return cds.getStatementsForClass(m_conMan).getUpdateStmt(
634: m_conMan.getConnection());
635: } catch (SQLException e) {
636: throw new PersistenceBrokerSQLException(
637: "Could not build statement ask for", e);
638: } catch (LookupException e) {
639: throw new PersistenceBrokerException(
640: "Used ConnectionManager instance could not obtain a connection",
641: e);
642: }
643: }
644:
645: /**
646: * returns an array containing values for all the Objects attribute
647: * @throws PersistenceBrokerException if there is an erros accessing obj field values
648: */
649: protected ValueContainer[] getAllValues(ClassDescriptor cld,
650: Object obj) throws PersistenceBrokerException {
651: return m_broker.serviceBrokerHelper().getAllRwValues(cld, obj);
652: }
653:
654: /**
655: * returns an Array with an Objects PK VALUES
656: * @throws PersistenceBrokerException if there is an erros accessing o field values
657: */
658: protected ValueContainer[] getKeyValues(PersistenceBroker broker,
659: ClassDescriptor cld, Object obj)
660: throws PersistenceBrokerException {
661: return broker.serviceBrokerHelper().getKeyValues(cld, obj);
662: }
663:
664: /**
665: * returns an Array with an Identities PK VALUES
666: * @throws PersistenceBrokerException if there is an erros accessing o field values
667: */
668: protected ValueContainer[] getKeyValues(PersistenceBroker broker,
669: ClassDescriptor cld, Identity oid)
670: throws PersistenceBrokerException {
671: return broker.serviceBrokerHelper().getKeyValues(cld, oid);
672: }
673:
674: /**
675: * returns an Array with an Objects NON-PK VALUES
676: * @throws PersistenceBrokerException if there is an erros accessing o field values
677: */
678: protected ValueContainer[] getNonKeyValues(
679: PersistenceBroker broker, ClassDescriptor cld, Object obj)
680: throws PersistenceBrokerException {
681: return broker.serviceBrokerHelper().getNonKeyRwValues(cld, obj);
682: }
683:
684: /**
685: * Bind a prepared statment that represents a call to a procedure or
686: * user-defined function.
687: *
688: * @param stmt the statement to bind.
689: * @param cld the class descriptor of the object that triggered the
690: * invocation of the procedure or user-defined function.
691: * @param obj the object that triggered the invocation of the procedure
692: * or user-defined function.
693: * @param proc the procedure descriptor that provides information about
694: * the arguments that shoudl be passed to the procedure or
695: * user-defined function
696: */
697: private void bindProcedure(PreparedStatement stmt,
698: ClassDescriptor cld, Object obj, ProcedureDescriptor proc)
699: throws SQLException {
700: int valueSub = 0;
701:
702: // Figure out if we are using a callable statement. If we are, then we
703: // will need to register one or more output parameters.
704: CallableStatement callable = null;
705: try {
706: callable = (CallableStatement) stmt;
707: } catch (Exception e) {
708: m_log.error("Error while bind values for class '"
709: + (cld != null ? cld.getClassNameOfObject() : null)
710: + "', using stored procedure: " + proc, e);
711: if (e instanceof SQLException) {
712: throw (SQLException) e;
713: } else {
714: throw new PersistenceBrokerException(
715: "Unexpected error while bind values for class '"
716: + (cld != null ? cld
717: .getClassNameOfObject() : null)
718: + "', using stored procedure: " + proc);
719: }
720: }
721:
722: // If we have a return value, then register it.
723: if ((proc.hasReturnValue()) && (callable != null)) {
724: int jdbcType = proc.getReturnValueFieldRef().getJdbcType()
725: .getType();
726: m_platform
727: .setNullForStatement(stmt, valueSub + 1, jdbcType);
728: callable.registerOutParameter(valueSub + 1, jdbcType);
729: valueSub++;
730: }
731:
732: // Process all of the arguments.
733: Iterator iterator = proc.getArguments().iterator();
734: while (iterator.hasNext()) {
735: ArgumentDescriptor arg = (ArgumentDescriptor) iterator
736: .next();
737: Object val = arg.getValue(obj);
738: int jdbcType = arg.getJdbcType();
739: setObjectForStatement(stmt, valueSub + 1, val, jdbcType);
740: if ((arg.getIsReturnedByProcedure()) && (callable != null)) {
741: callable.registerOutParameter(valueSub + 1, jdbcType);
742: }
743: valueSub++;
744: }
745: }
746:
747: /**
748: * Sets object for statement at specific index, adhering to platform- and null-rules.
749: * @param stmt the statement
750: * @param index the current parameter index
751: * @param value the value to set
752: * @param sqlType the JDBC SQL-type of the value
753: * @throws SQLException on platform error
754: */
755: private void setObjectForStatement(PreparedStatement stmt,
756: int index, Object value, int sqlType) throws SQLException {
757: if (value == null) {
758: m_platform.setNullForStatement(stmt, index, sqlType);
759: } else {
760: m_platform.setObjectForStatement(stmt, index, value,
761: sqlType);
762: }
763: }
764:
765: }
|