KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ojb > broker > accesslayer > JdbcAccessImpl


1 package org.apache.ojb.broker.accesslayer;
2
3 /* Copyright 2003-2005 The Apache Software Foundation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 import java.sql.CallableStatement JavaDoc;
19 import java.sql.PreparedStatement JavaDoc;
20 import java.sql.ResultSet JavaDoc;
21 import java.sql.SQLException JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.Map JavaDoc;
25
26 import org.apache.ojb.broker.Identity;
27 import org.apache.ojb.broker.OptimisticLockException;
28 import org.apache.ojb.broker.PersistenceBroker;
29 import org.apache.ojb.broker.PersistenceBrokerException;
30 import org.apache.ojb.broker.PersistenceBrokerSQLException;
31 import org.apache.ojb.broker.accesslayer.sql.SelectStatement;
32 import org.apache.ojb.broker.core.ValueContainer;
33 import org.apache.ojb.broker.metadata.ArgumentDescriptor;
34 import org.apache.ojb.broker.metadata.ClassDescriptor;
35 import org.apache.ojb.broker.metadata.FieldDescriptor;
36 import org.apache.ojb.broker.metadata.JdbcType;
37 import org.apache.ojb.broker.metadata.ProcedureDescriptor;
38 import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
39 import org.apache.ojb.broker.platforms.Platform;
40 import org.apache.ojb.broker.query.Query;
41 import org.apache.ojb.broker.util.ExceptionHelper;
42 import org.apache.ojb.broker.util.logging.Logger;
43 import org.apache.ojb.broker.util.logging.LoggerFactory;
44 import org.apache.ojb.broker.util.sequence.SequenceManagerException;
45
46 /**
47  * JdbcAccess is responsible for establishing performing
48  * SQL Queries against remote Databases.
49  * It hides all knowledge about JDBC from the BrokerImpl
50  *
51  * @author <a HREF="mailto:thma@apache.org">Thomas Mahler</a>
52  * @version $Id: JdbcAccessImpl.java,v 1.22.2.11 2005/12/13 18:21:23 arminw Exp $
53  */

54 public class JdbcAccessImpl implements JdbcAccess
55 {
56     /**
57      * The logger used.
58      */

59     protected Logger logger;
60
61     /**
62      * The broker in use.
63      */

64     protected PersistenceBroker broker;
65
66     /**
67      * constructor is private, use getInstance to get
68      * the singleton instance of this class
69      */

70     public JdbcAccessImpl(PersistenceBroker broker)
71     {
72         this.broker = broker;
73         logger = LoggerFactory.getLogger(this.getClass());
74     }
75
76     /**
77      * Helper Platform accessor method
78      *
79      * @return Platform for the current broker connection manager.
80      */

81     private Platform getPlatform()
82     {
83         return this.broker.serviceConnectionManager().getSupportedPlatform();
84     }
85
86     /**
87      * performs a DELETE operation against RDBMS.
88      * @param cld ClassDescriptor providing mapping information.
89      * @param obj The object to be deleted.
90      */

91     public void executeDelete(ClassDescriptor cld, Object JavaDoc obj) throws PersistenceBrokerException
92     {
93         if (logger.isDebugEnabled())
94         {
95             logger.debug("executeDelete: " + obj);
96         }
97
98         final StatementManagerIF sm = broker.serviceStatementManager();
99         PreparedStatement JavaDoc stmt = null;
100         try
101         {
102             stmt = sm.getDeleteStatement(cld);
103             if (stmt == null)
104             {
105                 logger.error("getDeleteStatement returned a null statement");
106                 throw new PersistenceBrokerException("JdbcAccessImpl: getDeleteStatement returned a null statement");
107             }
108
109             sm.bindDelete(stmt, cld, obj);
110             if (logger.isDebugEnabled())
111                 logger.debug("executeDelete: " + stmt);
112
113             // @todo: clearify semantics
114
// thma: the following check is not secure. The object could be deleted *or* changed.
115
// if it was deleted it makes no sense to throw an OL exception.
116
// does is make sense to throw an OL exception if the object was changed?
117
if (stmt.executeUpdate() == 0 && cld.isLocking()) //BRJ
118
{
119                 throw new OptimisticLockException("Object has been modified or deleted by someone else", obj);
120             }
121
122             // Harvest any return values.
123
harvestReturnValues(cld.getDeleteProcedure(), obj, stmt);
124         }
125         catch (OptimisticLockException e)
126         {
127             // Don't log as error
128
if (logger.isDebugEnabled())
129                 logger.debug("OptimisticLockException during the execution of delete: "
130                         + e.getMessage(), e);
131             throw e;
132         }
133         catch (PersistenceBrokerException e)
134         {
135             logger.error("PersistenceBrokerException during the execution of delete: "
136                     + e.getMessage(), e);
137             throw e;
138         }
139         catch (SQLException JavaDoc e)
140         {
141             final String JavaDoc sql = broker.serviceSqlGenerator().getPreparedDeleteStatement(cld).getStatement();
142             throw ExceptionHelper.generateException(e, sql, cld, logger, obj);
143         }
144         finally
145         {
146             sm.closeResources(stmt, null);
147         }
148     }
149
150     /**
151      * Performs a DELETE operation based on the given {@link Query} against RDBMS.
152      * @param query the query string.
153      * @param cld ClassDescriptor providing JDBC information.
154      */

155     public void executeDelete(Query query, ClassDescriptor cld) throws PersistenceBrokerException
156     {
157         if (logger.isDebugEnabled())
158         {
159             logger.debug("executeDelete (by Query): " + query);
160         }
161         final StatementManagerIF sm = broker.serviceStatementManager();
162         PreparedStatement JavaDoc stmt = null;
163         final String JavaDoc sql = this.broker.serviceSqlGenerator().getPreparedDeleteStatement(query, cld).getStatement();
164         try
165         {
166             stmt = sm.getPreparedStatement(cld, sql,
167                     false, StatementManagerIF.FETCH_SIZE_NOT_APPLICABLE, cld.getDeleteProcedure()!=null);
168
169             sm.bindStatement(stmt, query, cld, 1);
170             if (logger.isDebugEnabled())
171                 logger.debug("executeDelete (by Query): " + stmt);
172
173             stmt.executeUpdate();
174         }
175         catch (SQLException JavaDoc e)
176         {
177             throw ExceptionHelper.generateException(e, sql, cld, null, logger);
178         }
179         finally
180         {
181             sm.closeResources(stmt, null);
182         }
183     }
184
185     /**
186      * performs an INSERT operation against RDBMS.
187      * @param obj The Object to be inserted as a row of the underlying table.
188      * @param cld ClassDescriptor providing mapping information.
189      */

190     public void executeInsert(ClassDescriptor cld, Object JavaDoc obj) throws PersistenceBrokerException
191     {
192         if (logger.isDebugEnabled())
193         {
194             logger.debug("executeInsert: " + obj);
195         }
196         final StatementManagerIF sm = broker.serviceStatementManager();
197         PreparedStatement JavaDoc stmt = null;
198         try
199         {
200             stmt = sm.getInsertStatement(cld);
201             if (stmt == null)
202             {
203                 logger.error("getInsertStatement returned a null statement");
204                 throw new PersistenceBrokerException("getInsertStatement returned a null statement");
205             }
206             // before bind values perform autoincrement sequence columns
207
assignAutoincrementSequences(cld, obj);
208             sm.bindInsert(stmt, cld, obj);
209             if (logger.isDebugEnabled())
210                 logger.debug("executeInsert: " + stmt);
211             stmt.executeUpdate();
212             // after insert read and assign identity columns
213
assignAutoincrementIdentityColumns(cld, obj);
214
215             // Harvest any return values.
216
harvestReturnValues(cld.getInsertProcedure(), obj, stmt);
217         }
218         catch (PersistenceBrokerException e)
219         {
220             logger.error("PersistenceBrokerException during the execution of the insert: " + e.getMessage(), e);
221             throw e;
222         }
223         catch(SequenceManagerException e)
224         {
225             throw new PersistenceBrokerException("Error while try to assign identity value", e);
226         }
227         catch (SQLException JavaDoc e)
228         {
229             final String JavaDoc sql = broker.serviceSqlGenerator().getPreparedInsertStatement(cld).getStatement();
230             throw ExceptionHelper.generateException(e, sql, cld, logger, obj);
231         }
232         finally
233         {
234             sm.closeResources(stmt, null);
235         }
236     }
237
238     /**
239      * performs a SELECT operation against RDBMS.
240      * @param query the query string.
241      * @param cld ClassDescriptor providing JDBC information.
242      */

243     public ResultSetAndStatement executeQuery(Query query, ClassDescriptor cld) throws PersistenceBrokerException
244     {
245         if (logger.isDebugEnabled())
246         {
247             logger.debug("executeQuery: " + query);
248         }
249         /*
250          * MBAIRD: we should create a scrollable resultset if the start at
251          * index or end at index is set
252          */

253         boolean scrollable = ((query.getStartAtIndex() > Query.NO_START_AT_INDEX) || (query.getEndAtIndex() > Query.NO_END_AT_INDEX));
254         /*
255          * OR if the prefetching of relationships is being used.
256          */

257         if (query != null && query.getPrefetchedRelationships() != null && !query.getPrefetchedRelationships().isEmpty())
258         {
259             scrollable = true;
260         }
261         final StatementManagerIF sm = broker.serviceStatementManager();
262         final SelectStatement sql = broker.serviceSqlGenerator().getPreparedSelectStatement(query, cld);
263         PreparedStatement JavaDoc stmt = null;
264         ResultSet JavaDoc rs = null;
265         try
266         {
267             final int queryFetchSize = query.getFetchSize();
268             final boolean isStoredProcedure = isStoredProcedure(sql.getStatement());
269             stmt = sm.getPreparedStatement(cld, sql.getStatement() ,
270                     scrollable, queryFetchSize, isStoredProcedure);
271             if (isStoredProcedure)
272             {
273                 // Query implemented as a stored procedure, which must return a result set.
274
// Query sytax is: { ?= call PROCEDURE_NAME(?,...,?)}
275
getPlatform().registerOutResultSet((CallableStatement JavaDoc) stmt, 1);
276                 sm.bindStatement(stmt, query, cld, 2);
277
278                 if (logger.isDebugEnabled())
279                     logger.debug("executeQuery: " + stmt);
280
281                 stmt.execute();
282                 rs = (ResultSet JavaDoc) ((CallableStatement JavaDoc) stmt).getObject(1);
283             }
284             else
285             {
286                 sm.bindStatement(stmt, query, cld, 1);
287
288                 if (logger.isDebugEnabled())
289                     logger.debug("executeQuery: " + stmt);
290
291                 rs = stmt.executeQuery();
292             }
293
294             return new ResultSetAndStatement(sm, stmt, rs, sql);
295         }
296         catch (PersistenceBrokerException e)
297         {
298             // release resources on exception
299
sm.closeResources(stmt, rs);
300             logger.error("PersistenceBrokerException during the execution of the query: " + e.getMessage(), e);
301             throw e;
302         }
303         catch (SQLException JavaDoc e)
304         {
305             // release resources on exception
306
sm.closeResources(stmt, rs);
307             throw ExceptionHelper.generateException(e, sql.getStatement(), null, logger, null);
308         }
309     }
310
311     public ResultSetAndStatement executeSQL(
312         String JavaDoc sqlStatement,
313         ClassDescriptor cld,
314         boolean scrollable)
315         throws PersistenceBrokerException
316     {
317         return executeSQL(sqlStatement, cld, null, scrollable);
318     }
319
320     /**
321      * performs a SQL SELECT statement against RDBMS.
322      * @param sql the query string.
323      * @param cld ClassDescriptor providing meta-information.
324      */

325     public ResultSetAndStatement executeSQL(
326         final String JavaDoc sql,
327         ClassDescriptor cld,
328         ValueContainer[] values,
329         boolean scrollable)
330         throws PersistenceBrokerException
331     {
332         if (logger.isDebugEnabled()) logger.debug("executeSQL: " + sql);
333         final boolean isStoredprocedure = isStoredProcedure(sql);
334         final StatementManagerIF sm = broker.serviceStatementManager();
335         PreparedStatement JavaDoc stmt = null;
336         ResultSet JavaDoc rs = null;
337         try
338         {
339             stmt = sm.getPreparedStatement(cld, sql,
340                     scrollable, StatementManagerIF.FETCH_SIZE_NOT_EXPLICITLY_SET, isStoredprocedure);
341             if (isStoredprocedure)
342             {
343                 // Query implemented as a stored procedure, which must return a result set.
344
// Query sytax is: { ?= call PROCEDURE_NAME(?,...,?)}
345
getPlatform().registerOutResultSet((CallableStatement JavaDoc) stmt, 1);
346                 sm.bindValues(stmt, values, 2);
347                 stmt.execute();
348                 rs = (ResultSet JavaDoc) ((CallableStatement JavaDoc) stmt).getObject(1);
349             }
350             else
351             {
352                 sm.bindValues(stmt, values, 1);
353                 rs = stmt.executeQuery();
354             }
355
356             // as we return the resultset for further operations, we cannot release the statement yet.
357
// that has to be done by the JdbcAccess-clients (i.e. RsIterator, ProxyRsIterator and PkEnumeration.)
358
return new ResultSetAndStatement(sm, stmt, rs, new SelectStatement()
359             {
360                 public Query getQueryInstance()
361                 {
362                     return null;
363                 }
364
365                 public int getColumnIndex(FieldDescriptor fld)
366                 {
367                     return JdbcType.MIN_INT;
368                 }
369
370                 public String JavaDoc getStatement()
371                 {
372                     return sql;
373                 }
374             });
375         }
376         catch (PersistenceBrokerException e)
377         {
378             // release resources on exception
379
sm.closeResources(stmt, rs);
380             logger.error("PersistenceBrokerException during the execution of the SQL query: " + e.getMessage(), e);
381             throw e;
382         }
383         catch (SQLException JavaDoc e)
384         {
385             // release resources on exception
386
sm.closeResources(stmt, rs);
387             throw ExceptionHelper.generateException(e, sql, cld, values, logger, null);
388         }
389     }
390
391     public int executeUpdateSQL(String JavaDoc sqlStatement, ClassDescriptor cld)
392         throws PersistenceBrokerException
393     {
394         return executeUpdateSQL(sqlStatement, cld, null, null);
395     }
396
397     /**
398      * performs a SQL UPDTE, INSERT or DELETE statement against RDBMS.
399      * @param sqlStatement the query string.
400      * @param cld ClassDescriptor providing meta-information.
401      * @return int returncode
402      */

403     public int executeUpdateSQL(
404         String JavaDoc sqlStatement,
405         ClassDescriptor cld,
406         ValueContainer[] values1,
407         ValueContainer[] values2)
408         throws PersistenceBrokerException
409     {
410         if (logger.isDebugEnabled())
411             logger.debug("executeUpdateSQL: " + sqlStatement);
412
413         int result;
414         int index;
415         PreparedStatement JavaDoc stmt = null;
416         final StatementManagerIF sm = broker.serviceStatementManager();
417         try
418         {
419             stmt = sm.getPreparedStatement(cld, sqlStatement,
420                     Query.NOT_SCROLLABLE, StatementManagerIF.FETCH_SIZE_NOT_APPLICABLE, isStoredProcedure(sqlStatement));
421             index = sm.bindValues(stmt, values1, 1);
422             sm.bindValues(stmt, values2, index);
423             result = stmt.executeUpdate();
424         }
425         catch (PersistenceBrokerException e)
426         {
427             logger.error("PersistenceBrokerException during the execution of the Update SQL query: " + e.getMessage(), e);
428             throw e;
429         }
430         catch (SQLException JavaDoc e)
431         {
432             ValueContainer[] tmp = addValues(values1, values2);
433             throw ExceptionHelper.generateException(e, sqlStatement, cld, tmp, logger, null);
434         }
435         finally
436         {
437             sm.closeResources(stmt, null);
438         }
439         return result;
440     }
441
442     /** Helper method, returns the addition of both arrays (add source to target array) */
443     private ValueContainer[] addValues(ValueContainer[] target, ValueContainer[] source)
444     {
445         ValueContainer[] newArray;
446         if(source != null && source.length > 0)
447         {
448             if(target != null)
449             {
450                 newArray = new ValueContainer[target.length + source.length];
451                 System.arraycopy(target, 0, newArray, 0, target.length);
452                 System.arraycopy(source, 0, newArray, target.length, source.length);
453             }
454             else
455             {
456                 newArray = source;
457             }
458         }
459         else
460         {
461             newArray = target;
462         }
463         return newArray;
464     }
465
466     /**
467      * performs an UPDATE operation against RDBMS.
468      * @param obj The Object to be updated in the underlying table.
469      * @param cld ClassDescriptor providing mapping information.
470      */

471     public void executeUpdate(ClassDescriptor cld, Object JavaDoc obj) throws PersistenceBrokerException
472     {
473         if (logger.isDebugEnabled())
474         {
475             logger.debug("executeUpdate: " + obj);
476         }
477
478         // obj with nothing but key fields is not updated
479
if (cld.getNonPkRwFields().length == 0)
480         {
481             return;
482         }
483
484         final StatementManagerIF sm = broker.serviceStatementManager();
485         PreparedStatement JavaDoc stmt = null;
486         // BRJ: preserve current locking values
487
// locking values will be restored in case of exception
488
ValueContainer[] oldLockingValues;
489         oldLockingValues = cld.getCurrentLockingValues(obj);
490         try
491         {
492             stmt = sm.getUpdateStatement(cld);
493             if (stmt == null)
494             {
495                 logger.error("getUpdateStatement returned a null statement");
496                 throw new PersistenceBrokerException("getUpdateStatement returned a null statement");
497             }
498
499             sm.bindUpdate(stmt, cld, obj);
500             if (logger.isDebugEnabled())
501                 logger.debug("executeUpdate: " + stmt);
502
503             if ((stmt.executeUpdate() == 0) && cld.isLocking()) //BRJ
504
{
505                 throw new OptimisticLockException("Object has been modified by someone else", obj);
506             }
507
508             // Harvest any return values.
509
harvestReturnValues(cld.getUpdateProcedure(), obj, stmt);
510         }
511         catch (OptimisticLockException e)
512         {
513             // Don't log as error
514
if (logger.isDebugEnabled())
515                 logger.debug(
516                     "OptimisticLockException during the execution of update: " + e.getMessage(),
517                     e);
518             throw e;
519         }
520         catch (PersistenceBrokerException e)
521         {
522             // BRJ: restore old locking values
523
setLockingValues(cld, obj, oldLockingValues);
524
525             logger.error(
526                 "PersistenceBrokerException during the execution of the update: " + e.getMessage(),
527                 e);
528             throw e;
529         }
530         catch (SQLException JavaDoc e)
531         {
532             final String JavaDoc sql = broker.serviceSqlGenerator().getPreparedUpdateStatement(cld).getStatement();
533             throw ExceptionHelper.generateException(e, sql, cld, logger, obj);
534         }
535         finally
536         {
537             sm.closeResources(stmt, null);
538         }
539     }
540
541     /**
542      * performs a primary key lookup operation against RDBMS and materializes
543      * an object from the resulting row. Only skalar attributes are filled from
544      * the row, references are not resolved.
545      * @param oid contains the primary key info.
546      * @param cld ClassDescriptor providing mapping information.
547      * @return the materialized object, null if no matching row was found or if
548      * any error occured.
549      */

550     public Object JavaDoc materializeObject(ClassDescriptor cld, Identity oid)
551         throws PersistenceBrokerException
552     {
553         final StatementManagerIF sm = broker.serviceStatementManager();
554         final SelectStatement sql = broker.serviceSqlGenerator().getPreparedSelectByPkStatement(cld);
555         Object JavaDoc result = null;
556         PreparedStatement JavaDoc stmt = null;
557         ResultSet JavaDoc rs = null;
558         try
559         {
560             stmt = sm.getSelectByPKStatement(cld);
561             if (stmt == null)
562             {
563                 logger.error("getSelectByPKStatement returned a null statement");
564                 throw new PersistenceBrokerException("getSelectByPKStatement returned a null statement");
565             }
566             /*
567             arminw: currently a select by PK could never be a stored procedure,
568             thus we can always set 'false'. Is this correct??
569             */

570             sm.bindSelect(stmt, oid, cld, false);
571             rs = stmt.executeQuery();
572             // data available read object, else return null
573
ResultSetAndStatement rs_stmt = new ResultSetAndStatement(broker.serviceStatementManager(), stmt, rs, sql);
574             if (rs.next())
575             {
576                 Map JavaDoc row = new HashMap JavaDoc();
577                 cld.getRowReader().readObjectArrayFrom(rs_stmt, row);
578                 result = cld.getRowReader().readObjectFrom(row);
579             }
580             // close resources
581
rs_stmt.close();
582         }
583         catch (PersistenceBrokerException e)
584         {
585             // release resources on exception
586
sm.closeResources(stmt, rs);
587             logger.error("PersistenceBrokerException during the execution of materializeObject: " + e.getMessage(), e);
588             throw e;
589         }
590         catch (SQLException JavaDoc e)
591         {
592             // release resources on exception
593
sm.closeResources(stmt, rs);
594             throw ExceptionHelper.generateException(e, sql.getStatement(), cld, logger, null);
595         }
596         return result;
597     }
598
599     /**
600      * Set the locking values
601      * @param cld
602      * @param obj
603      * @param oldLockingValues
604      */

605     private void setLockingValues(ClassDescriptor cld, Object JavaDoc obj, ValueContainer[] oldLockingValues)
606     {
607         FieldDescriptor fields[] = cld.getLockingFields();
608
609         for (int i=0; i<fields.length; i++)
610         {
611             PersistentField field = fields[i].getPersistentField();
612             Object JavaDoc lockVal = oldLockingValues[i].getValue();
613
614             field.set(obj, lockVal);
615         }
616     }
617
618     /**
619      * Harvest any values that may have been returned during the execution
620      * of a procedure.
621      *
622      * @param proc the procedure descriptor that provides info about the procedure
623      * that was invoked.
624      * @param obj the object that was persisted
625      * @param stmt the statement that was used to persist the object.
626      *
627      * @throws PersistenceBrokerSQLException if a problem occurs.
628      */

629     private void harvestReturnValues(
630         ProcedureDescriptor proc,
631         Object JavaDoc obj,
632         PreparedStatement JavaDoc stmt)
633         throws PersistenceBrokerSQLException
634     {
635         // If the procedure descriptor is null or has no return values or
636
// if the statement is not a callable statment, then we're done.
637
if ((proc == null) || (!proc.hasReturnValues()))
638         {
639             return;
640         }
641
642         // Set up the callable statement
643
CallableStatement JavaDoc callable = (CallableStatement JavaDoc) stmt;
644
645         // This is the index that we'll use to harvest the return value(s).
646
int index = 0;
647
648         // If the proc has a return value, then try to harvest it.
649
if (proc.hasReturnValue())
650         {
651
652             // Increment the index
653
index++;
654
655             // Harvest the value.
656
this.harvestReturnValue(obj, callable, proc.getReturnValueFieldRef(), index);
657         }
658
659         // Check each argument. If it's returned by the procedure,
660
// then harvest the value.
661
Iterator JavaDoc iter = proc.getArguments().iterator();
662         while (iter.hasNext())
663         {
664             index++;
665             ArgumentDescriptor arg = (ArgumentDescriptor) iter.next();
666             if (arg.getIsReturnedByProcedure())
667             {
668                 this.harvestReturnValue(obj, callable, arg.getFieldRef(), index);
669             }
670         }
671     }
672
673     /**
674      * Harvest a single value that was returned by a callable statement.
675      *
676      * @param obj the object that will receive the value that is harvested.
677      * @param callable the CallableStatement that contains the value to harvest
678      * @param fmd the FieldDescriptor that identifies the field where the
679      * harvested value will be stord.
680      * @param index the parameter index.
681      *
682      * @throws PersistenceBrokerSQLException if a problem occurs.
683      */

684     private void harvestReturnValue(
685         Object JavaDoc obj,
686         CallableStatement JavaDoc callable,
687         FieldDescriptor fmd,
688         int index)
689         throws PersistenceBrokerSQLException
690     {
691
692         try
693         {
694             // If we have a field descriptor, then we can harvest
695
// the return value.
696
if ((callable != null) && (fmd != null) && (obj != null))
697             {
698                 // Get the value and convert it to it's appropriate
699
// java type.
700
Object JavaDoc value = fmd.getJdbcType().getObjectFromColumn(callable, index);
701
702                 // Set the value of the persistent field.
703
fmd.getPersistentField().set(obj, fmd.getFieldConversion().sqlToJava(value));
704
705             }
706         }
707         catch (SQLException JavaDoc e)
708         {
709             String JavaDoc msg = "SQLException during the execution of harvestReturnValue"
710                 + " class="
711                 + obj.getClass().getName()
712                 + ","
713                 + " field="
714                 + fmd.getAttributeName()
715                 + " : "
716                 + e.getMessage();
717             logger.error(msg,e);
718             throw new PersistenceBrokerSQLException(msg, e);
719         }
720     }
721
722     /**
723      * Check if the specified sql-string is a stored procedure
724      * or not.
725      * @param sql The sql query to check
726      * @return <em>True</em> if the query is a stored procedure, else <em>false</em> is returned.
727      */

728     protected boolean isStoredProcedure(String JavaDoc sql)
729     {
730         /*
731         Stored procedures start with
732         {?= call <procedure-name>[<arg1>,<arg2>, ...]}
733         or
734         {call <procedure-name>[<arg1>,<arg2>, ...]}
735         but also statements with white space like
736         { ?= call <procedure-name>[<arg1>,<arg2>, ...]}
737         are possible.
738         */

739         int k = 0, i = 0;
740         char c;
741         while(k < 3 && i < sql.length())
742         {
743             c = sql.charAt(i);
744             if(c != ' ')
745             {
746                 switch (k)
747                 {
748                     case 0:
749                         if(c != '{') return false;
750                         break;
751                     case 1:
752                         if(c != '?' && c != 'c') return false;
753                         break;
754                     case 2:
755                         if(c != '=' && c != 'a') return false;
756                         break;
757                 }
758                 k++;
759             }
760             i++;
761         }
762         return true;
763     }
764
765     protected void assignAutoincrementSequences(ClassDescriptor cld, Object JavaDoc target) throws SequenceManagerException
766     {
767         // TODO: refactor auto-increment handling, auto-increment should only be supported by PK fields?
768
// FieldDescriptor[] fields = cld.getPkFields();
769
FieldDescriptor[] fields = cld.getFieldDescriptor(false);
770         FieldDescriptor field;
771         for(int i = 0; i < fields.length; i++)
772         {
773             field = fields[i];
774             if(field.isAutoIncrement() && !field.isAccessReadOnly())
775             {
776                 Object JavaDoc value = field.getPersistentField().get(target);
777                 if(broker.serviceBrokerHelper().representsNull(field, value))
778                 {
779                     Object JavaDoc id = broker.serviceSequenceManager().getUniqueValue(field);
780                     field.getPersistentField().set(target, id);
781                 }
782             }
783         }
784     }
785
786     protected void assignAutoincrementIdentityColumns(ClassDescriptor cld, Object JavaDoc target) throws SequenceManagerException
787     {
788         // if database Identity Columns are used, query the id from database
789
// other SequenceManager implementations will ignore this call
790
if(cld.useIdentityColumnField()) broker.serviceSequenceManager().afterStore(this, cld, target);
791     }
792 }
793
Popular Tags