Source Code Cross Referenced for RsIterator.java in  » Database-ORM » db-ojb » org » apache » ojb » broker » accesslayer » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database ORM » db ojb » org.apache.ojb.broker.accesslayer 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package org.apache.ojb.broker.accesslayer;
0002:
0003:        /* Copyright 2002-2005 The Apache Software Foundation
0004:         *
0005:         * Licensed under the Apache License, Version 2.0 (the "License");
0006:         * you may not use this file except in compliance with the License.
0007:         * You may obtain a copy of the License at
0008:         *
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:
0018:        import java.lang.ref.WeakReference;
0019:        import java.sql.ResultSet;
0020:        import java.sql.SQLException;
0021:        import java.util.Collection;
0022:        import java.util.HashMap;
0023:        import java.util.List;
0024:        import java.util.Map;
0025:        import java.util.NoSuchElementException;
0026:        import java.util.Vector;
0027:
0028:        import org.apache.ojb.broker.Identity;
0029:        import org.apache.ojb.broker.OJBRuntimeException;
0030:        import org.apache.ojb.broker.PBLifeCycleEvent;
0031:        import org.apache.ojb.broker.PBStateEvent;
0032:        import org.apache.ojb.broker.PBStateListener;
0033:        import org.apache.ojb.broker.PersistenceBrokerException;
0034:        import org.apache.ojb.broker.PersistenceBrokerInternal;
0035:        import org.apache.ojb.broker.PersistenceBrokerSQLException;
0036:        import org.apache.ojb.broker.cache.MaterializationCache;
0037:        import org.apache.ojb.broker.cache.ObjectCacheInternal;
0038:        import org.apache.ojb.broker.core.PersistenceBrokerImpl;
0039:        import org.apache.ojb.broker.metadata.ClassDescriptor;
0040:        import org.apache.ojb.broker.metadata.DescriptorRepository;
0041:        import org.apache.ojb.broker.metadata.FieldDescriptor;
0042:        import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
0043:        import org.apache.ojb.broker.query.Query;
0044:        import org.apache.ojb.broker.query.QueryBySQL;
0045:        import org.apache.ojb.broker.util.logging.Logger;
0046:        import org.apache.ojb.broker.util.logging.LoggerFactory;
0047:
0048:        /**
0049:         * RsIterator can be used to iterate over a jdbc ResultSet to retrieve
0050:         * persistent objects step-by-step and not all at once. In fact the
0051:         * PersistenceBroker::getCollectionByQuery(...) method uses a RsIterator
0052:         * internally to build up a Collection of objects
0053:         *
0054:         * <p>
0055:         * NOTE: OJB is very strict in handling <tt>RsIterator</tt> instances. <tt>RsIterator</tt> is
0056:         * bound very closely to the used {@link org.apache.ojb.broker.PersistenceBroker} instance.
0057:         * Thus if you do a
0058:         * <br/> - {@link org.apache.ojb.broker.PersistenceBroker#close}
0059:         * <br/> - {@link org.apache.ojb.broker.PersistenceBroker#commitTransaction}
0060:         * <br/> - {@link org.apache.ojb.broker.PersistenceBroker#abortTransaction}
0061:         * <br/>
0062:         * call, the current <tt>RsIterator</tt> instance resources will be cleaned up automatic
0063:         * and invalidate current instance.
0064:         * </p>
0065:         *
0066:         * <p>
0067:         * NOTE: this code uses features that only JDBC 2.0 compliant Drivers support.
0068:         * It will NOT work with JDBC 1.0 Drivers (e.g. SUN's JdbcOdbcDriver) If you
0069:         * are forced to use such a driver, you can use code from the 0.1.30 release.
0070:         * </p>
0071:         * @author <a href="mailto:thma@apache.org">Thomas Mahler <a>
0072:         * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird <a>- added the
0073:         *         support for extents mapped to single table - added the .size
0074:         *         functionality - added cursor control
0075:         *
0076:         * @version $Id: RsIterator.java,v 1.63.2.19 2005/12/21 22:22:58 tomdz Exp $
0077:         */
0078:        public class RsIterator implements  OJBIterator {
0079:            protected Logger logger = LoggerFactory.getLogger(this .getClass());
0080:            private static final String INFO_MSG = "Resources already cleaned up, recommend to set"
0081:                    + " this flag before first use of the iterator";
0082:            /*
0083:             * arminw: to improve performance we only use this instance to fire events
0084:             * and set the target object on every use TODO: Find a better solution
0085:             */
0086:            private PBLifeCycleEvent afterLookupEvent;
0087:            private MaterializationCache m_cache;
0088:
0089:            /**
0090:             * reference to the PersistenceBroker
0091:             */
0092:            private PersistenceBrokerImpl m_broker;
0093:
0094:            /**
0095:             * the underlying resultset
0096:             */
0097:            private ResultSetAndStatement m_rsAndStmt;
0098:
0099:            /**
0100:             * the underlying query object
0101:             */
0102:            private RsQueryObject m_queryObject;
0103:
0104:            /**
0105:             * the proxy class to be used or null
0106:             */
0107:            private Class m_itemProxyClass;
0108:
0109:            /**
0110:             * the top-level class of the item objects
0111:             */
0112:            private Class m_itemTopLevelClass = null;
0113:
0114:            /**
0115:             * this container holds the values of the current ro during materialisation
0116:             */
0117:            private Map m_row = null;
0118:
0119:            /**
0120:             * flag that indicates wether hasNext on m_rs has allready been called
0121:             */
0122:            private boolean m_hasCalledCheck = false;
0123:
0124:            /**
0125:             * prefetch relationship: inBatchedMode true prevents releasing of
0126:             * DbResources IN_LIMIT defines the max number of values of sql (IN) , -1
0127:             * for no limits
0128:             */
0129:            private boolean m_inBatchedMode = false;
0130:
0131:            /**
0132:             * return value of the previously called hasNext from m_rs
0133:             */
0134:            private boolean hasNext = false;
0135:
0136:            private boolean advancedJDBCSupport = false;
0137:            private boolean JDBCSupportAssessed = false;
0138:            private int m_current_row = 0;
0139:            /**
0140:             * Tracks whether or not the resources that are used by this class have been released.
0141:             */
0142:            private boolean resourcesAreReleased = false;
0143:
0144:            /**
0145:             * Flag that indicates if the automatic resource cleanup should be
0146:             * done or not. Default is <tt>true</tt>.
0147:             */
0148:            private boolean autoRelease = true;
0149:            private ResourceWrapper resourceListener;
0150:
0151:            /** if true do not fire PBLifeCycleEvent. */
0152:            private boolean disableLifeCycleEvents = false;
0153:
0154:            /**
0155:             * RsIterator constructor.
0156:             *
0157:             * @param queryObject query object
0158:             * @param broker the broker we should use.
0159:             */
0160:            public RsIterator(RsQueryObject queryObject,
0161:                    final PersistenceBrokerImpl broker) {
0162:                setCache(broker.getInternalCache());
0163:                setRow(new HashMap());
0164:                setBroker(broker);
0165:                setQueryObject(queryObject);
0166:
0167:                Class classToPrefetch = broker.getReferenceBroker()
0168:                        .getClassToPrefetch();
0169:                if ((classToPrefetch != null)
0170:                        && classToPrefetch.isAssignableFrom(queryObject
0171:                                .getClassDescriptor().getClassOfObject())) {
0172:                    setItemProxyClass(null);
0173:                } else {
0174:                    setItemProxyClass(queryObject.getClassDescriptor()
0175:                            .getProxyClass());
0176:                }
0177:
0178:                /*
0179:                 * arminw: to improve performance we only use this instance to fire
0180:                 * events and set the target object on every use TODO: Find a better
0181:                 * solution
0182:                 */
0183:                setAfterLookupEvent(new PBLifeCycleEvent(getBroker(),
0184:                        PBLifeCycleEvent.Type.AFTER_LOOKUP));
0185:
0186:                try {
0187:                    setRsAndStmt(queryObject.performQuery(broker
0188:                            .serviceJdbcAccess()));
0189:                    /*
0190:                     * TODO: how does prefetchRelationships handle QueryBySQL instances? Is
0191:                     * it ok to pass query object?
0192:                     */
0193:                    prefetchRelationships(queryObject.getQuery());
0194:                    if (logger.isDebugEnabled()) {
0195:                        logger.debug("RsIterator[" + queryObject
0196:                                + "] initialized");
0197:                    }
0198:                } catch (RuntimeException e) {
0199:                    autoReleaseDbResources();
0200:                    throw e;
0201:                }
0202:
0203:                /*
0204:                now RsIterator instance is created, we wrap this instance with a
0205:                PBStateListener to make sure that resources of this instance will be
0206:                released. Add this as temporary PBStateListener.
0207:                 */
0208:                resourceListener = new ResourceWrapper(this );
0209:                m_broker.addListener(resourceListener);
0210:            }
0211:
0212:            protected Class getTopLevelClass() {
0213:                if (m_itemTopLevelClass == null) {
0214:                    m_itemTopLevelClass = getBroker().getTopLevelClass(
0215:                            getQueryObject().getClassDescriptor()
0216:                                    .getClassOfObject());
0217:                }
0218:                return m_itemTopLevelClass;
0219:            }
0220:
0221:            /**
0222:             * returns true if there are still more rows in the underlying ResultSet.
0223:             * Returns false if ResultSet is exhausted.
0224:             */
0225:            public synchronized boolean hasNext() {
0226:                try {
0227:                    if (!isHasCalledCheck()) {
0228:                        setHasCalledCheck(true);
0229:                        setHasNext(getRsAndStmt().m_rs.next());
0230:                        if (!getHasNext()) {
0231:                            autoReleaseDbResources();
0232:                        }
0233:                    }
0234:                } catch (Exception ex) {
0235:                    setHasNext(false);
0236:                    autoReleaseDbResources();
0237:                    if (ex instanceof  ResourceClosedException) {
0238:                        throw (ResourceClosedException) ex;
0239:                    }
0240:                    if (ex instanceof  SQLException) {
0241:                        throw new PersistenceBrokerSQLException(
0242:                                "Calling ResultSet.next() failed",
0243:                                (SQLException) ex);
0244:                    } else {
0245:                        throw new PersistenceBrokerException(
0246:                                "Can't get next row from ResultSet", ex);
0247:                    }
0248:                }
0249:                if (logger.isDebugEnabled())
0250:                    logger.debug("hasNext() -> " + getHasNext());
0251:
0252:                return getHasNext();
0253:            }
0254:
0255:            /**
0256:             * moves to the next row of the underlying ResultSet and returns the
0257:             * corresponding Object materialized from this row.
0258:             */
0259:            public synchronized Object next() throws NoSuchElementException {
0260:                try {
0261:                    if (!isHasCalledCheck()) {
0262:                        hasNext();
0263:                    }
0264:                    setHasCalledCheck(false);
0265:                    if (getHasNext()) {
0266:                        Object obj = getObjectFromResultSet();
0267:                        m_current_row++;
0268:
0269:                        // Invoke events on PersistenceBrokerAware instances and listeners
0270:                        // set target object
0271:                        if (!disableLifeCycleEvents) {
0272:                            getAfterLookupEvent().setTarget(obj);
0273:                            getBroker().fireBrokerEvent(getAfterLookupEvent());
0274:                            getAfterLookupEvent().setTarget(null);
0275:                        }
0276:                        return obj;
0277:                    } else {
0278:                        throw new NoSuchElementException(
0279:                                "inner hasNext was false");
0280:                    }
0281:                } catch (ResourceClosedException ex) {
0282:                    autoReleaseDbResources();
0283:                    throw ex;
0284:                } catch (NoSuchElementException ex) {
0285:                    autoReleaseDbResources();
0286:                    logger.error("Error while iterate ResultSet for query "
0287:                            + m_queryObject, ex);
0288:                    throw new NoSuchElementException(
0289:                            "Could not obtain next object: " + ex.getMessage());
0290:                }
0291:            }
0292:
0293:            /**
0294:             * removing is not supported
0295:             */
0296:            public void remove() {
0297:                throw new UnsupportedOperationException(
0298:                        "removing not supported by RsIterator");
0299:            }
0300:
0301:            /**
0302:             * read all objects of this iterator. objects will be placed in cache
0303:             */
0304:            private Collection getOwnerObjects() {
0305:                Collection owners = new Vector();
0306:                while (hasNext()) {
0307:                    owners.add(next());
0308:                }
0309:                return owners;
0310:            }
0311:
0312:            /**
0313:             * prefetch defined relationships requires JDBC level 2.0, does not work
0314:             * with Arrays
0315:             */
0316:            private void prefetchRelationships(Query query) {
0317:                List prefetchedRel;
0318:                Collection owners;
0319:                String relName;
0320:                RelationshipPrefetcher[] prefetchers;
0321:
0322:                if (query == null || query.getPrefetchedRelationships() == null
0323:                        || query.getPrefetchedRelationships().isEmpty()) {
0324:                    return;
0325:                }
0326:
0327:                if (!supportsAdvancedJDBCCursorControl()) {
0328:                    logger
0329:                            .info("prefetching relationships requires JDBC level 2.0");
0330:                    return;
0331:                }
0332:
0333:                // prevent releasing of DBResources
0334:                setInBatchedMode(true);
0335:
0336:                prefetchedRel = query.getPrefetchedRelationships();
0337:                prefetchers = new RelationshipPrefetcher[prefetchedRel.size()];
0338:
0339:                // disable auto retrieve for all prefetched relationships
0340:                for (int i = 0; i < prefetchedRel.size(); i++) {
0341:                    relName = (String) prefetchedRel.get(i);
0342:                    prefetchers[i] = getBroker()
0343:                            .getRelationshipPrefetcherFactory()
0344:                            .createRelationshipPrefetcher(
0345:                                    getQueryObject().getClassDescriptor(),
0346:                                    relName);
0347:                    prefetchers[i].prepareRelationshipSettings();
0348:                }
0349:
0350:                // materialize ALL owners of this Iterator
0351:                owners = getOwnerObjects();
0352:
0353:                // prefetch relationships and associate with owners
0354:                for (int i = 0; i < prefetchedRel.size(); i++) {
0355:                    prefetchers[i].prefetchRelationship(owners);
0356:                }
0357:
0358:                // reset auto retrieve for all prefetched relationships
0359:                for (int i = 0; i < prefetchedRel.size(); i++) {
0360:                    prefetchers[i].restoreRelationshipSettings();
0361:                }
0362:
0363:                try {
0364:                    getRsAndStmt().m_rs.beforeFirst(); // reposition resultset jdbc 2.0
0365:                } catch (SQLException e) {
0366:                    logger.error("beforeFirst failed !", e);
0367:                }
0368:
0369:                setInBatchedMode(false);
0370:                setHasCalledCheck(false);
0371:            }
0372:
0373:            /**
0374:             * returns an Identity object representing the current resultset row
0375:             */
0376:            protected Identity getIdentityFromResultSet()
0377:                    throws PersistenceBrokerException {
0378:                // fill primary key values from Resultset
0379:                FieldDescriptor fld;
0380:                FieldDescriptor[] pkFields = getQueryObject()
0381:                        .getClassDescriptor().getPkFields();
0382:                Object[] pkValues = new Object[pkFields.length];
0383:
0384:                for (int i = 0; i < pkFields.length; i++) {
0385:                    fld = pkFields[i];
0386:                    pkValues[i] = getRow().get(fld.getColumnName());
0387:                }
0388:
0389:                // return identity object build up from primary keys
0390:                return getBroker().serviceIdentity().buildIdentity(
0391:                        getQueryObject().getClassDescriptor()
0392:                                .getClassOfObject(), getTopLevelClass(),
0393:                        pkValues);
0394:            }
0395:
0396:            /**
0397:             * returns a fully materialized Object from the current row of the
0398:             * underlying resultset. Works as follows: - read Identity from the primary
0399:             * key values of current row - check if Object is in cache - return cached
0400:             * object or read it from current row and put it in cache
0401:             */
0402:            protected Object getObjectFromResultSet()
0403:                    throws PersistenceBrokerException {
0404:                getRow().clear();
0405:                /**
0406:                 * MBAIRD if a proxy is to be used, return a proxy instance and dont
0407:                 * perfom a full materialization. NOTE: Potential problem here with
0408:                 * multi-mapped table. The itemProxyClass is for the m_cld
0409:                 * classdescriptor. The object you are materializing might not be of
0410:                 * that type, it could be a subclass. We should get the concrete class
0411:                 * type out of the resultset then check the proxy from that.
0412:                 * itemProxyClass should NOT be a member variable.
0413:                 */
0414:
0415:                RowReader rowReader = getQueryObject().getClassDescriptor()
0416:                        .getRowReader();
0417:                // in any case we need the PK values of result set row
0418:                // provide m_row with primary key data of current row
0419:                rowReader.readPkValuesFrom(getRsAndStmt(), getRow());
0420:
0421:                if (getItemProxyClass() != null) {
0422:                    // assert: m_row is filled with primary key values from db
0423:                    return getProxyFromResultSet();
0424:                } else {
0425:                    // 1.read Identity
0426:                    Identity oid = getIdentityFromResultSet();
0427:                    Object result;
0428:
0429:                    // 2. check if Object is in cache. if so return cached version.
0430:                    result = getCache().lookup(oid);
0431:                    if (result == null) {
0432:
0433:                        // map all field values from the current result set
0434:                        rowReader.readObjectArrayFrom(getRsAndStmt(), getRow());
0435:                        // 3. If Object is not in cache
0436:                        // materialize Object with primitive attributes filled from current row
0437:                        result = rowReader.readObjectFrom(getRow());
0438:                        // result may still be null!
0439:                        if (result != null) {
0440:                            /*
0441:                             * synchronize on result so the ODMG-layer can take a
0442:                             * snapshot only of fully cached (i.e. with all references +
0443:                             * collections) objects
0444:                             */
0445:                            synchronized (result) {
0446:                                getCache().enableMaterializationCache();
0447:                                try {
0448:                                    getCache()
0449:                                            .doInternalCache(
0450:                                                    oid,
0451:                                                    result,
0452:                                                    ObjectCacheInternal.TYPE_NEW_MATERIALIZED);
0453:                                    /**
0454:                                     * MBAIRD if you have multiple classes mapped to a
0455:                                     * table, and you query on the base class you could get
0456:                                     * back NON base class objects, so we shouldn't pass
0457:                                     * m_cld, but rather the class descriptor for the
0458:                                     * actual class.
0459:                                     */
0460:                                    // fill reference and collection attributes
0461:                                    ClassDescriptor cld = getBroker()
0462:                                            .getClassDescriptor(
0463:                                                    result.getClass());
0464:                                    // don't force loading of reference
0465:                                    final boolean unforced = false;
0466:                                    // Maps ReferenceDescriptors to HashSets of owners
0467:                                    getBroker().getReferenceBroker()
0468:                                            .retrieveReferences(result, cld,
0469:                                                    unforced);
0470:                                    getBroker().getReferenceBroker()
0471:                                            .retrieveCollections(result, cld,
0472:                                                    unforced);
0473:                                    getCache().disableMaterializationCache();
0474:                                } catch (RuntimeException e) {
0475:                                    // catch runtime exc. to guarantee clearing of internal buffer on failure
0476:                                    getCache().doLocalClear();
0477:                                    throw e;
0478:                                }
0479:                            }
0480:                        }
0481:                    } else // Object is in cache
0482:                    {
0483:                        ClassDescriptor cld = getBroker().getClassDescriptor(
0484:                                result.getClass());
0485:                        // if refresh is required, read all values from the result set and
0486:                        // update the cache instance from the db
0487:                        if (cld.isAlwaysRefresh()) {
0488:                            // map all field values from the current result set
0489:                            rowReader.readObjectArrayFrom(getRsAndStmt(),
0490:                                    getRow());
0491:                            rowReader.refreshObject(result, getRow());
0492:                        }
0493:                        getBroker().checkRefreshRelationships(result, oid, cld);
0494:                    }
0495:
0496:                    return result;
0497:                }
0498:            }
0499:
0500:            /**
0501:             * Reads primary key information from current RS row and generates a
0502:             *
0503:             * corresponding Identity, and returns a proxy from the Identity.
0504:             *
0505:             * @throws PersistenceBrokerException
0506:             *             if there was an error creating the proxy class
0507:             */
0508:            protected Object getProxyFromResultSet()
0509:                    throws PersistenceBrokerException {
0510:                // 1. get Identity of current row:
0511:                Identity oid = getIdentityFromResultSet();
0512:
0513:                // 2. return a Proxy instance:
0514:                return getBroker().createProxy(getItemProxyClass(), oid);
0515:            }
0516:
0517:            /**
0518:             * with a new batch of JDBC 3.0 drivers coming out we can't just check for
0519:             * begins with 2, we need to check the actual version and see if it's
0520:             * greater than or equal to 2.
0521:             */
0522:            private boolean supportsAdvancedJDBCCursorControl() {
0523:                if (!JDBCSupportAssessed) {
0524:                    if (getConnectionDescriptor().getJdbcLevel() >= 2.0)
0525:                        advancedJDBCSupport = true;
0526:                    JDBCSupportAssessed = true;
0527:                }
0528:                return advancedJDBCSupport;
0529:            }
0530:
0531:            /**
0532:             * Answer the counted size
0533:             *
0534:             * @return int
0535:             */
0536:            protected int countedSize() throws PersistenceBrokerException {
0537:                Query countQuery = getBroker().serviceBrokerHelper()
0538:                        .getCountQuery(getQueryObject().getQuery());
0539:                ResultSetAndStatement rsStmt;
0540:                ClassDescriptor cld = getQueryObject().getClassDescriptor();
0541:                int count = 0;
0542:
0543:                // BRJ: do not use broker.getCount() because it's extent-aware
0544:                // the count we need here must not include extents !
0545:                if (countQuery instanceof  QueryBySQL) {
0546:                    String countSql = ((QueryBySQL) countQuery).getSql();
0547:                    rsStmt = getBroker().serviceJdbcAccess().executeSQL(
0548:                            countSql, cld, Query.NOT_SCROLLABLE);
0549:                } else {
0550:                    rsStmt = getBroker().serviceJdbcAccess().executeQuery(
0551:                            countQuery, cld);
0552:                }
0553:
0554:                try {
0555:                    if (rsStmt.m_rs.next()) {
0556:                        count = rsStmt.m_rs.getInt(1);
0557:                    }
0558:                } catch (SQLException e) {
0559:                    throw new PersistenceBrokerException(e);
0560:                } finally {
0561:                    rsStmt.close();
0562:                }
0563:
0564:                return count;
0565:            }
0566:
0567:            /**
0568:             * @return the size of the iterator, aka the number of rows in this
0569:             *         iterator.
0570:             */
0571:            public int size() throws PersistenceBrokerException {
0572:                int retval = 0; // default size is 0;
0573:                boolean forwardOnly = true;
0574:                try {
0575:                    forwardOnly = getRsAndStmt().m_stmt.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY;
0576:                } catch (SQLException e) {
0577:                    //ignore it
0578:                }
0579:                if (!supportsAdvancedJDBCCursorControl()
0580:                        || getBroker().serviceConnectionManager()
0581:                                .getSupportedPlatform()
0582:                                .useCountForResultsetSize() || forwardOnly) {
0583:                    /**
0584:                     * MBAIRD: doesn't support the .last .getRow method, use the
0585:                     * .getCount on the persistenceBroker which executes a count(*)
0586:                     * query.
0587:                     */
0588:                    if (logger.isDebugEnabled())
0589:                        logger.debug("Executing count(*) to get size()");
0590:                    retval = countedSize();
0591:                } else {
0592:                    /**
0593:                     * Use the .last .getRow method of finding size. The reason for
0594:                     * supplying an alternative method is effeciency, some driver/db
0595:                     * combos are a lot more efficient at just moving the cursor and
0596:                     * returning the row in a real (not -1) number.
0597:                     */
0598:                    int whereIAm; // first
0599:                    try {
0600:                        if (getRsAndStmt().m_rs != null) {
0601:                            whereIAm = getRsAndStmt().m_rs.getRow();
0602:                            if (getRsAndStmt().m_rs.last()) {
0603:                                retval = getRsAndStmt().m_rs.getRow();
0604:                            } else {
0605:                                retval = 0;
0606:                            }
0607:                            // go back from whence I came.
0608:                            if (whereIAm > 0) {
0609:                                getRsAndStmt().m_rs.absolute(whereIAm);
0610:                            } else {
0611:                                getRsAndStmt().m_rs.beforeFirst();
0612:                            }
0613:                        }
0614:                    } catch (SQLException se) {
0615:                        advancedJDBCSupport = false;
0616:                    }
0617:                }
0618:                return retval;
0619:            }
0620:
0621:            /* (non-Javadoc)
0622:             * @see org.apache.ojb.broker.accesslayer.OJBIterator#fullSize()
0623:             */
0624:            public int fullSize() throws PersistenceBrokerException {
0625:                return size();
0626:            }
0627:
0628:            /**
0629:             * Moves the cursor to the given row number in the iterator. If the row
0630:             * number is positive, the cursor moves to the given row number with
0631:             * respect to the beginning of the iterator. The first row is row 1, the
0632:             * second is row 2, and so on.
0633:             *
0634:             * @param row  the row to move to in this iterator, by absolute number
0635:             */
0636:            public boolean absolute(int row) throws PersistenceBrokerException {
0637:                boolean retval;
0638:                if (supportsAdvancedJDBCCursorControl()) {
0639:                    retval = absoluteAdvanced(row);
0640:                } else {
0641:                    retval = absoluteBasic(row);
0642:                }
0643:                return retval;
0644:            }
0645:
0646:            /**
0647:             * absolute for basicJDBCSupport
0648:             * @param row
0649:             */
0650:            private boolean absoluteBasic(int row) {
0651:                boolean retval = false;
0652:
0653:                if (row > m_current_row) {
0654:                    try {
0655:                        while (m_current_row < row
0656:                                && getRsAndStmt().m_rs.next()) {
0657:                            m_current_row++;
0658:                        }
0659:                        if (m_current_row == row) {
0660:                            retval = true;
0661:                        } else {
0662:                            setHasCalledCheck(true);
0663:                            setHasNext(false);
0664:                            retval = false;
0665:                            autoReleaseDbResources();
0666:                        }
0667:                    } catch (Exception ex) {
0668:                        setHasCalledCheck(true);
0669:                        setHasNext(false);
0670:                        retval = false;
0671:                    }
0672:                } else {
0673:                    logger
0674:                            .info("Your driver does not support advanced JDBC Functionality, "
0675:                                    + "you cannot call absolute() with a position < current");
0676:                }
0677:                return retval;
0678:            }
0679:
0680:            /**
0681:             * absolute for advancedJDBCSupport
0682:             * @param row
0683:             */
0684:            private boolean absoluteAdvanced(int row) {
0685:                boolean retval = false;
0686:
0687:                try {
0688:                    if (getRsAndStmt().m_rs != null) {
0689:                        if (row == 0) {
0690:                            getRsAndStmt().m_rs.beforeFirst();
0691:                        } else {
0692:                            retval = getRsAndStmt().m_rs.absolute(row);
0693:                        }
0694:                        m_current_row = row;
0695:                        setHasCalledCheck(false);
0696:                    }
0697:                } catch (SQLException e) {
0698:                    advancedJDBCSupport = false;
0699:                }
0700:                return retval;
0701:            }
0702:
0703:            /**
0704:             * Moves the cursor a relative number of rows, either positive or negative.
0705:             * Attempting to move beyond the first/last row in the iterator positions
0706:             * the cursor before/after the the first/last row. Calling relative(0) is
0707:             * valid, but does not change the cursor position.
0708:             *
0709:             * @param row
0710:             *            the row to move to in this iterator, by relative number
0711:             */
0712:            public boolean relative(int row) throws PersistenceBrokerException {
0713:                boolean retval = false;
0714:                if (supportsAdvancedJDBCCursorControl()) {
0715:                    try {
0716:                        if (getRsAndStmt().m_rs != null) {
0717:                            retval = getRsAndStmt().m_rs.relative(row);
0718:                            m_current_row += row;
0719:                        }
0720:                    } catch (SQLException e) {
0721:                        advancedJDBCSupport = false;
0722:                    }
0723:                } else {
0724:                    if (row >= 0) {
0725:                        return absolute(m_current_row + row);
0726:                    } else {
0727:                        logger
0728:                                .info("Your driver does not support advanced JDBC Functionality, you cannot call relative() with a negative value");
0729:                    }
0730:                }
0731:                return retval;
0732:            }
0733:
0734:            /**
0735:             * Release all internally used Database resources of the iterator. Clients
0736:             * must call this methods explicitely if the iterator is not exhausted by
0737:             * the client application. If the Iterator is exhauseted this method will
0738:             * be called implicitely.
0739:             */
0740:            public void releaseDbResources() {
0741:                release(true);
0742:            }
0743:
0744:            void release(boolean removeResourceListener) {
0745:                if (!isInBatchedMode()) // resources are reused in batched mode
0746:                {
0747:                    // If we haven't released resources yet, then do so.
0748:                    if (!this .resourcesAreReleased) {
0749:                        // remove the resource listener
0750:                        if (removeResourceListener && resourceListener != null) {
0751:                            try {
0752:                                /*
0753:                                when RsIterator is closed, the resource listener
0754:                                was no longer needed to listen on PB events for clean up.
0755:                                 */
0756:                                m_broker.removeListener(resourceListener);
0757:                                this .resourceListener = null;
0758:                            } catch (Exception e) {
0759:                                logger
0760:                                        .error(
0761:                                                "Error when try to remove RsIterator resource listener",
0762:                                                e);
0763:                            }
0764:                        }
0765:                        this .resourcesAreReleased = true;
0766:                        if (m_rsAndStmt != null) {
0767:                            m_rsAndStmt.close();
0768:                            m_rsAndStmt = null;
0769:                        }
0770:                    }
0771:                }
0772:            }
0773:
0774:            /**
0775:             * Internally used by this class to close used resources
0776:             * as soon as possible.
0777:             */
0778:            protected void autoReleaseDbResources() {
0779:                if (autoRelease) {
0780:                    releaseDbResources();
0781:                }
0782:            }
0783:
0784:            /**
0785:             * Allows user to switch off/on automatic resource cleanup.
0786:             * Set <tt>false</tt> to take responsibility of resource cleanup
0787:             * for this class, means after use it's mandatory to call
0788:             * {@link #releaseDbResources}.
0789:             * <br/> By default it's <tt>true</tt> and resource cleanup is done
0790:             * automatic.
0791:             */
0792:            public void setAutoRelease(boolean autoRelease) {
0793:                /*
0794:                arminw:
0795:                this method should be declared in OJBIterator interface till
0796:                OJB 1.1 and PersistenceBroker interface should only return
0797:                OJBIterator instead of Iterator instances
0798:                 */
0799:                if (resourcesAreReleased && !autoRelease) {
0800:                    logger.info(INFO_MSG);
0801:                }
0802:                this .autoRelease = autoRelease;
0803:            }
0804:
0805:            /**
0806:             * Return the DescriptorRepository
0807:             */
0808:            protected DescriptorRepository getDescriptorRepository() {
0809:                return getBroker().getDescriptorRepository();
0810:            }
0811:
0812:            protected JdbcConnectionDescriptor getConnectionDescriptor() {
0813:                return getBroker().serviceConnectionManager()
0814:                        .getConnectionDescriptor();
0815:            }
0816:
0817:            /**
0818:             * safety just in case someone leaks.
0819:             */
0820:            protected void finalize() {
0821:                if (m_rsAndStmt != null) {
0822:                    logger
0823:                            .info("Found unclosed resources while finalize (causer class: "
0824:                                    + this .getClass().getName()
0825:                                    + ")"
0826:                                    + " Do automatic cleanup");
0827:                    releaseDbResources();
0828:                }
0829:                try {
0830:                    super .finalize();
0831:                } catch (Throwable throwable) {
0832:                    throwable.printStackTrace();
0833:                }
0834:            }
0835:
0836:            public String toString() {
0837:                return super .toString();
0838:            }
0839:
0840:            /**
0841:             * @return Returns the cld.
0842:             */
0843:            public ClassDescriptor getClassDescriptor() {
0844:                return getQueryObject().getClassDescriptor();
0845:            }
0846:
0847:            protected void setBroker(PersistenceBrokerImpl broker) {
0848:                m_broker = broker;
0849:            }
0850:
0851:            protected PersistenceBrokerInternal getBroker() {
0852:                return m_broker;
0853:            }
0854:
0855:            protected void setRsAndStmt(ResultSetAndStatement rsAndStmt) {
0856:                if (m_rsAndStmt != null) {
0857:                    throw new ResourceNotClosedException(
0858:                            "Unclosed resources found, please release resources"
0859:                                    + " before set new ones");
0860:                }
0861:                resourcesAreReleased = false;
0862:                m_rsAndStmt = rsAndStmt;
0863:            }
0864:
0865:            protected ResultSetAndStatement getRsAndStmt() {
0866:                if (resourcesAreReleased) {
0867:                    throw new ResourceClosedException(
0868:                            "Resources no longer reachable, RsIterator will be automatic"
0869:                                    + " cleaned up on PB.close/.commitTransaction/.abortTransaction");
0870:                }
0871:                return m_rsAndStmt;
0872:            }
0873:
0874:            protected void setQueryObject(RsQueryObject queryObject) {
0875:                this .m_queryObject = queryObject;
0876:            }
0877:
0878:            protected RsQueryObject getQueryObject() {
0879:                return m_queryObject;
0880:            }
0881:
0882:            protected void setItemProxyClass(Class itemProxyClass) {
0883:                this .m_itemProxyClass = itemProxyClass;
0884:            }
0885:
0886:            protected Class getItemProxyClass() {
0887:                return m_itemProxyClass;
0888:            }
0889:
0890:            protected void setRow(Map row) {
0891:                m_row = row;
0892:            }
0893:
0894:            protected Map getRow() {
0895:                return m_row;
0896:            }
0897:
0898:            protected void setCache(MaterializationCache cache) {
0899:                this .m_cache = cache;
0900:            }
0901:
0902:            protected MaterializationCache getCache() {
0903:                return m_cache;
0904:            }
0905:
0906:            protected void setAfterLookupEvent(PBLifeCycleEvent afterLookupEvent) {
0907:                this .afterLookupEvent = afterLookupEvent;
0908:            }
0909:
0910:            protected PBLifeCycleEvent getAfterLookupEvent() {
0911:                return afterLookupEvent;
0912:            }
0913:
0914:            protected void setHasCalledCheck(boolean hasCalledCheck) {
0915:                this .m_hasCalledCheck = hasCalledCheck;
0916:            }
0917:
0918:            protected boolean isHasCalledCheck() {
0919:                return m_hasCalledCheck;
0920:            }
0921:
0922:            protected void setHasNext(boolean hasNext) {
0923:                this .hasNext = hasNext;
0924:            }
0925:
0926:            protected boolean getHasNext() {
0927:                return hasNext;
0928:            }
0929:
0930:            protected void setInBatchedMode(boolean inBatchedMode) {
0931:                this .m_inBatchedMode = inBatchedMode;
0932:            }
0933:
0934:            protected boolean isInBatchedMode() {
0935:                return m_inBatchedMode;
0936:            }
0937:
0938:            //***********************************************************
0939:            // inner classes
0940:            //***********************************************************
0941:            /**
0942:             * Wraps a {@link RsIterator} instance as {@link WeakReference}.
0943:             */
0944:            public static class ResourceWrapper implements  PBStateListener {
0945:                /*
0946:                arminw:
0947:                we do register a PBStateListener to PB instance
0948:                to make sure that this instance will be cleaned up at PB.close() call.
0949:                If PB was in tx, we cleanup resources on PB.commit/abort, because
0950:                commit/abort close the current used connection and all Statement/ResultSet
0951:                instances will become invalid.
0952:                 */
0953:                WeakReference ref;
0954:
0955:                public ResourceWrapper(RsIterator rs) {
0956:                    ref = new WeakReference(rs);
0957:                }
0958:
0959:                public void beforeClose(PBStateEvent event) {
0960:                    if (ref != null) {
0961:                        RsIterator rs = (RsIterator) ref.get();
0962:                        if (rs != null)
0963:                            rs.release(false);
0964:                        ref = null;
0965:                    }
0966:                }
0967:
0968:                public void beforeRollback(PBStateEvent event) {
0969:                    if (ref != null) {
0970:                        RsIterator rs = (RsIterator) ref.get();
0971:                        if (rs != null)
0972:                            rs.release(false);
0973:                        ref = null;
0974:                    }
0975:                }
0976:
0977:                public void beforeCommit(PBStateEvent event) {
0978:                    if (ref != null) {
0979:                        RsIterator rs = (RsIterator) ref.get();
0980:                        if (rs != null)
0981:                            rs.release(false);
0982:                        ref = null;
0983:                    }
0984:                }
0985:
0986:                public void afterCommit(PBStateEvent event) {
0987:                    //do nothing
0988:                }
0989:
0990:                public void afterRollback(PBStateEvent event) {
0991:                    //do nothing
0992:                }
0993:
0994:                public void afterBegin(PBStateEvent event) {
0995:                    //do nothing
0996:                }
0997:
0998:                public void beforeBegin(PBStateEvent event) {
0999:                    //do nothing
1000:                }
1001:
1002:                public void afterOpen(PBStateEvent event) {
1003:                    //do nothing
1004:                }
1005:            }
1006:
1007:            public static class ResourceClosedException extends
1008:                    OJBRuntimeException {
1009:                public ResourceClosedException(String msg) {
1010:                    super (msg);
1011:                }
1012:
1013:                public ResourceClosedException(String msg, Throwable cause) {
1014:                    super (msg, cause);
1015:                }
1016:            }
1017:
1018:            public static class ResourceNotClosedException extends
1019:                    OJBRuntimeException {
1020:                public ResourceNotClosedException(String msg) {
1021:                    super (msg);
1022:                }
1023:
1024:                public ResourceNotClosedException(String msg, Throwable cause) {
1025:                    super (msg, cause);
1026:                }
1027:            }
1028:
1029:            /**
1030:             * @see org.apache.ojb.broker.accesslayer.OJBIterator#disableLifeCycleEvents()
1031:             */
1032:            public void disableLifeCycleEvents() {
1033:                disableLifeCycleEvents = true;
1034:            }
1035:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.