svn commit: r513577 [3/3] - in /db/ojb/trunk/src: java/org/apache/ojb/broker/ java/org/apache/ojb/broker/accesslayer/ java/org/apache/ojb/broker/accesslayer/sql/ java/org/apache/ojb/broker/core/ java/org/apache/ojb/broker/metadata/ java/org/apache/ojb/...
[email protected] Fri, 02 Mar 2007 01:33:47 -0000
| Newsgroups | gmane.comp.jakarta.ojb.devel |
|---|---|
| Message-ID | <[email protected]> |
Added: db/ojb/trunk/src/test/org/apache/ojb/broker/PaginationTest.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/test/org/apache/ojb/broker/PaginationTest.java?view=auto&rev=513577
==============================================================================
--- db/ojb/trunk/src/test/org/apache/ojb/broker/PaginationTest.java (added)
+++ db/ojb/trunk/src/test/org/apache/ojb/broker/PaginationTest.java Thu Mar 1 17:33:44 2007
@@ -0,0 +1,1351 @@
+package org.apache.ojb.broker;
+
+/* Copyright 2002-2007 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.Object;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.apache.ojb.junit.PBTestCase;
+import org.apache.ojb.broker.query.Query;
+import org.apache.ojb.broker.query.QueryFactory;
+import org.apache.ojb.broker.query.Criteria;
+import org.apache.ojb.broker.query.QueryByCriteria;
+import org.apache.ojb.broker.util.ObjectModification;
+import org.apache.ojb.broker.accesslayer.OJBIterator;
+import org.apache.ojb.broker.accesslayer.RsIterator;
+import org.apache.ojb.broker.accesslayer.ChainingIterator;
+import org.apache.ojb.broker.accesslayer.PagingIterator;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+import org.apache.commons.lang.ClassUtils;
+
+/**
+ * Test OJB's pagination and limit concepts.
+ */
+public class PaginationTest extends PBTestCase
+{
+ public static void main(String[] args)
+ {
+ String[] arr = {PaginationTest.class.getName()};
+ junit.textui.TestRunner.main(arr);
+ }
+
+ public PaginationTest(String name)
+ {
+ super(name);
+ }
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ }
+
+ public void tearDown() throws Exception
+ {
+ super.tearDown();
+ }
+
+ private void insertTestData(String appendix)
+ {
+ Book b1 = new Book("book_1" + appendix, new Date(1), null);
+ Author a1 = new Author("author_1" + appendix, null);
+ Author a2 = new Author("author_2" + appendix, null);
+ Author a3 = new Author("author_3" + appendix, null);
+ Author a4 = new Author("author_4" + appendix, null);
+ Review r = new Review("review" + appendix, new Integer(30));
+ Publisher p = new PublisherImpl("publisher" + appendix);
+
+ p.addAuthor(a1);
+ p.addAuthor(a2);
+ p.addAuthor(a3);
+ p.addAuthor(a4);
+ a1.setPublisher(p);
+ a2.setPublisher(p);
+ a3.setPublisher(p);
+ a4.setPublisher(p);
+
+ List reviews = new ArrayList();
+ for(int i=0; i<10; i++)
+ {
+ Review rev = new Review("review_" + i + appendix, new Integer(10 * i));
+ rev.setAuthor(new Author("review_author" + i + appendix, null));
+ rev.setBook(b1);
+ reviews.add(rev);
+ }
+ b1.setReviews(reviews);
+ a1.addBook(b1);
+ b1.addAuthor(a1);
+ b1.setPublisher(p);
+
+ broker.beginTransaction();
+ // it's a circular object graph, so insert the plain start object first
+ // and then update it with all references
+ broker.store(b1, ObjectModification.INSERT, true);
+ broker.serviceBatchManager().executeBatch();
+ broker.store(b1);
+ broker.commitTransaction();
+
+ }
+
+ private void deleteTestData(String appendix)
+ {
+ broker.serviceBatchManager().setBatchMode(false);
+ broker.beginTransaction();
+ Query q = QueryFactory.newQuery(Book.class, new Criteria().addLike("title", "%"+appendix));
+ List books = new ArrayList(broker.getCollectionByQuery(q));
+ for(int i = 0; i < books.size(); i++)
+ {
+ Object o = books.get(i);
+ broker.delete(o);
+ }
+ broker.commitTransaction();
+ }
+
+ public void testLimit_1()
+ {
+ String appendix = "_testLimit_1_" + System.currentTimeMillis();
+ performLimit(appendix, 1, 1, 10);
+ }
+
+ public void testLimit_3()
+ {
+ String appendix = "_testLimit_3_" + System.currentTimeMillis();
+ performLimit(appendix, 3, 3, 30);
+ }
+
+ public void testLimit_2()
+ {
+ String appendix = "_testLimit_2_" + System.currentTimeMillis();
+ performLimit(appendix, 9, 9, 90);
+ }
+
+ public void testLimit_4()
+ {
+ String appendix = "_testLimit_4_" + System.currentTimeMillis();
+ performLimit(appendix, 10, 9, 90);
+ }
+
+ public void performLimit(String appendix, int limit, int expectedSize, int voteLessOrEqual)
+ {
+ insertTestData(appendix);
+
+ // first check query without limit, this returns all Review objects with
+ // 'vote' >= 10 ===> expect 9 objects
+ Criteria crit = new Criteria()
+ .addGreaterOrEqualThan("vote", new Integer(10))
+ .addLike("book.title", "%"+appendix);
+ QueryByCriteria query = QueryFactory.newQuery(Review.class, crit);
+ // NOTE: If pagination/limit is used it's strongly recommended to order by
+ // a unique column to avoid problems with different result order
+ // ('vote' isn't unique, thus add PK field)
+ query.addOrderByAscending("vote");
+ query.addOrderByAscending("id");
+ // NOTE: if we use pagination it's mandatory not to query "extents" too,
+ // because else it will end in multiple limit queries (one for each extent)
+ // thus the result will be pagination_size * extents
+ query.setWithExtents(false);
+
+ // check result without limit
+ Collection result = broker.getCollectionByQuery(query);
+ assertEquals(9, result.size());
+ for(Iterator iterator = result.iterator(); iterator.hasNext();)
+ {
+ Review r = (Review) iterator.next();
+ assertTrue(r.getVote().intValue() >= 10);
+ assertNotNull(r.getBook());
+ assertTrue(r.getBook().getTitle().endsWith(appendix));
+ }
+
+ // now start the real work: perform LIMIT query
+ query = QueryFactory.newQuery(Review.class, crit);
+ // NOTE: If pagination/limit is used it's strongly recommended to order by
+ // a unique column to avoid problems with different result order
+ // ('vote' isn't unique, thus add PK field)
+ query.addOrderByAscending("vote");
+ query.addOrderByAscending("id");
+ // NOTE: if we use pagination it's mandatory not to query "extents" too,
+ // because else it will end in multiple limit queries (one for each extent)
+ // thus the result will be pagination_size * extents
+ query.setWithExtents(false);
+ // query with limit
+ query.setEndAtIndex(limit);
+ result = broker.getCollectionByQuery(query);
+
+ assertEquals(expectedSize, result.size());
+ for(Iterator iterator = result.iterator(); iterator.hasNext();)
+ {
+ Review r = (Review) iterator.next();
+ assertTrue(r.getVote().intValue() >= 10);
+ assertTrue(r.getVote().intValue() <= voteLessOrEqual);
+ assertNotNull(r.getBook());
+ assertTrue(r.getBook().getTitle().endsWith(appendix));
+ }
+
+ deleteTestData(appendix);
+ }
+
+ public void testLimitOffset_1()
+ {
+ String appendix = "_testLimitOffset_1_" + System.currentTimeMillis();
+ int start = 1;
+ int end = 1;
+ int expectedSize = 1;
+ int voteGreaterEquals = 10;
+ int voteLessEquals = 10;
+ performLimitOffest(appendix, start, end, expectedSize, voteGreaterEquals, voteLessEquals);
+ }
+
+ public void testLimitOffset_2()
+ {
+ String appendix = "_testLimitOffset_2_" + System.currentTimeMillis();
+ int start = 4;
+ int end = 4;
+ int expectedSize = 1;
+ int voteGreaterEquals = 40;
+ int voteLessEquals = 40;
+ performLimitOffest(appendix, start, end, expectedSize, voteGreaterEquals, voteLessEquals);
+ }
+
+ public void testLimitOffset_3()
+ {
+ String appendix = "_testLimitOffset_3_" + System.currentTimeMillis();
+ int start = 1;
+ int end = 8;
+ int expectedSize = 8;
+ int voteGreaterEquals = 10;
+ int voteLessEquals = 80;
+ performLimitOffest(appendix, start, end, expectedSize, voteGreaterEquals, voteLessEquals);
+ }
+
+ public void testLimitOffset_4()
+ {
+ String appendix = "_testLimitOffset_4_" + System.currentTimeMillis();
+ int start = 1;
+ int end = 9;
+ int expectedSize = 9;
+ int voteGreaterEquals = 10;
+ int voteLessEquals = 90;
+ performLimitOffest(appendix, start, end, expectedSize, voteGreaterEquals, voteLessEquals);
+ }
+
+ public void testLimitOffset_5()
+ {
+ String appendix = "_testLimitOffset_5_" + System.currentTimeMillis();
+ int start = 1;
+ int end = 12;
+ int expectedSize = 9;
+ int voteGreaterEquals = 10;
+ int voteLessEquals = 90;
+ performLimitOffest(appendix, start, end, expectedSize, voteGreaterEquals, voteLessEquals);
+ }
+
+ public void testLimitOffset_6()
+ {
+ String appendix = "_testLimitOffset_6_" + System.currentTimeMillis();
+ int start = 9;
+ int end = 9;
+ int expectedSize = 1;
+ int voteGreaterEquals = 90;
+ int voteLessEquals = 90;
+ performLimitOffest(appendix, start, end, expectedSize, voteGreaterEquals, voteLessEquals);
+ }
+
+ public void testLimitOffset_7()
+ {
+ String appendix = "_testLimitOffset_7_" + System.currentTimeMillis();
+ int start = 4;
+ int end = 7;
+ int expectedSize = 4;
+ int voteGreaterEquals = 40;
+ int voteLessEquals = 70;
+ performLimitOffest(appendix, start, end, expectedSize, voteGreaterEquals, voteLessEquals);
+ }
+
+ public void testLimitOffset_8()
+ {
+ String appendix = "_testLimitOffset_8_" + System.currentTimeMillis();
+ int start = 3;
+ // don't specify end
+ int end = Query.NO_END_AT_INDEX;
+ int expectedSize = 7;
+ int voteGreaterEquals = 30;
+ int voteLessEquals = 90;
+ performLimitOffest(appendix, start, end, expectedSize, voteGreaterEquals, voteLessEquals);
+ }
+
+ public void testLimitOffset_9()
+ {
+ String appendix = "_testLimitOffset_9_" + System.currentTimeMillis();
+ int start = 9;
+ // don't specify end
+ int end = Query.NO_END_AT_INDEX;
+ int expectedSize = 1;
+ int voteGreaterEquals = 90;
+ int voteLessEquals = 90;
+ performLimitOffest(appendix, start, end, expectedSize, voteGreaterEquals, voteLessEquals);
+ }
+
+ public void performLimitOffest(String appendix, int start, int end,
+ int expectedSize,
+ int voteGreaterEquals, int voteLessEquals)
+ {
+ insertTestData(appendix);
+
+ // first check query without limit/offset, this returns all Review objects with
+ // 'vote' >= 10 ===> expect 9 objects
+ Criteria crit = new Criteria()
+ .addGreaterOrEqualThan("vote", new Integer(10))
+ .addLike("book.title", "%"+appendix);
+ QueryByCriteria query = QueryFactory.newQuery(Review.class, crit);
+ // NOTE: If pagination/limit is used it's strongly recommended to order by
+ // a unique column to avoid problems with different result order
+ // ('vote' isn't unique, thus add PK field)
+ query.addOrderByAscending("vote");
+ query.addOrderByAscending("id");
+ // NOTE: if we use pagination it's mandatory not to query "extents" too,
+ // because else it will end in multiple limit queries (one for each extent)
+ // thus the result will be pagination_size * extents
+ query.setWithExtents(false);
+
+ // check result without limit
+ Collection result = broker.getCollectionByQuery(query);
+ assertEquals(9, result.size());
+ for(Iterator iterator = result.iterator(); iterator.hasNext();)
+ {
+ Review r = (Review) iterator.next();
+ assertTrue(r.getVote().intValue() >= 10);
+ assertNotNull(r.getBook());
+ assertTrue(r.getBook().getTitle().endsWith(appendix));
+ }
+
+ // now start the real work: perform LIMIT query
+ query = QueryFactory.newQuery(Review.class, crit);
+ // NOTE: If pagination/limit is used it's strongly recommended to order by
+ // a unique column to avoid problems with different result order
+ // ('vote' isn't unique, thus add PK field)
+ query.addOrderByAscending("vote");
+ query.addOrderByAscending("id");
+ // NOTE: if we use pagination it's mandatory not to query "extents" too,
+ // because else it will end in multiple limit queries (one for each extent)
+ // thus the result will be pagination_size * extents
+ query.setWithExtents(false);
+ query.setStartAtIndex(start);
+ query.setEndAtIndex(end);
+ result = broker.getCollectionByQuery(query);
+
+ assertEquals(expectedSize, result.size());
+ for(Iterator iterator = result.iterator(); iterator.hasNext();)
+ {
+ Review r = (Review) iterator.next();
+ // we skip the first one thus we expect 60
+ assertTrue("Expected Review.vote >=" + voteGreaterEquals + " but get: "
+ + r.getVote().intValue(), r.getVote().intValue() >= voteGreaterEquals);
+ assertTrue("Expected Review.vote <=" + voteLessEquals +" but get: "
+ + r.getVote().intValue(), r.getVote().intValue() <= voteLessEquals);
+ assertNotNull(r.getBook());
+ assertTrue(r.getBook().getTitle().endsWith(appendix));
+ //System.out.println("r: " + r);
+ }
+
+ deleteTestData(appendix);
+ }
+
+ /**
+ * Creates and store multiple Article objects with increasing
+ * Article.stock value (starting with 1).
+ */
+ private List createArticles(String name, int count)
+ {
+ List result = new ArrayList();
+ broker.beginTransaction();
+ for(int i=1; i<count + 1; i++)
+ {
+ Article a = createArticle(null, name);
+ a.setStock(i);
+ broker.store(a);
+ result.add(a);
+ }
+ broker.commitTransaction();
+ return result;
+ }
+
+ public void pagingPositionTest(String name, int articleCount, int startIndex, int endIndex,
+ int absoluteIndex, final int expectedStockValue, boolean allowRelativePlus1)
+ {
+// String name = "testPagingPosition_1_" + System.currentTimeMillis();
+// int articleCount = 20;
+// int startIndex = 10;
+// int endIndex = 14;
+// int absoluteIndex = 1;
+// int expectedStockValue = 10;
+
+ boolean supportsScrollableResultSet = broker.serviceConnectionManager().getConnectionDescriptor().getJdbcLevel() > 1.0;
+ boolean old = broker.serviceConnectionManager().getConnectionDescriptor().isNativeLimitOffset();
+
+ createArticles(name, articleCount);
+
+ Collection fullColl;
+ OJBIterator ojbIterator;
+ InterfaceArticle article;
+
+ // All Articles index in range
+ Criteria crit = new Criteria().addEqualTo("articleName", name);
+ QueryByCriteria query = QueryFactory.newQuery(Article.class, crit);
+ // primary order clause, not unique!!
+ query.addOrderByAscending("stock");
+ query.setWithExtents(false);
+ // get all created Article objects
+ fullColl = broker.getCollectionByQuery(query);
+ assertEquals(articleCount, fullColl.size());
+
+
+ try
+ {
+ // -------------------------------------------------------------
+ // expect RsIterator instance, without extents, nativeLimit=true
+ // -------------------------------------------------------------
+ query = QueryFactory.newQuery(Article.class, crit);
+ // NOTE: If pagination/limit is used it's strongly recommended to order by
+ // a unique column to avoid problems with different result order
+ query.addOrderByAscending("articleId");
+ // if we use pagination it's mandatory not to query "extents" too,
+ // because else it will end in multiple limit queries (one for each extent)
+ // thus the result will be pagination_size * extents
+ query.setWithExtents(false);
+ // limited query
+ query.setStartAtIndex(startIndex);
+ query.setEndAtIndex(endIndex);
+ // use native DB paging if supported
+ broker.serviceConnectionManager().getConnectionDescriptor().setNativeLimitOffset(true);
+
+ ojbIterator = broker.getIteratorByQuery(query);
+ // we expect the default iterator class
+ assertTrue(broker.serviceConnectionManager().getSupportedPlatform().supportsOffset() ?
+ ojbIterator instanceof RsIterator : ojbIterator instanceof PagingIterator);
+
+// System.out.println("#### result for (start=" + startIndex + ",end=" + endIndex
+// +"), absoluteIndex="+ absoluteIndex + ", expected="+expectedStockValue+": "
+// + new ArrayList(broker.getCollectionByQuery(query)));
+
+ // jump to index
+ ojbIterator.absolute(absoluteIndex);
+ article = (InterfaceArticle) ojbIterator.next();
+ assertEquals("Expected Article stock=" + expectedStockValue, expectedStockValue, article.getStock());
+ if(supportsScrollableResultSet)
+ {
+ // jump back
+ ojbIterator.relative(-1);
+ article = (InterfaceArticle)ojbIterator.next();
+ assertEquals("Expected Article stock=" + expectedStockValue, expectedStockValue, article.getStock());
+ // jump back
+ ojbIterator.relative(-1);
+ assertTrue(ojbIterator.hasNext());
+ article = (InterfaceArticle)ojbIterator.next();
+ assertEquals("Expected Article stock=" + expectedStockValue, expectedStockValue, article.getStock());
+ if(allowRelativePlus1)
+ {
+ // jump forward 1
+ ojbIterator.relative(1);
+ article = (InterfaceArticle)ojbIterator.next();
+ assertEquals("Expected Article stock=" + (expectedStockValue + 2), expectedStockValue + 2, article.getStock());
+
+ // jump back two
+ ojbIterator.relative(-3);
+ article = (InterfaceArticle)ojbIterator.next();
+ assertEquals("Expected Article stock=" + expectedStockValue, expectedStockValue, article.getStock());
+ }
+ }
+ // manually release used resources
+ ojbIterator.releaseDbResources();
+
+
+ // -------------------------------------------------------------
+ // expect PagingIterator instance, without extents, nativeLimit=false
+ // -------------------------------------------------------------
+ query = QueryFactory.newQuery(Article.class, crit);
+ query.setWithExtents(false);
+ query.setStartAtIndex(startIndex);
+ query.setEndAtIndex(endIndex);
+ broker.serviceConnectionManager().getConnectionDescriptor().setNativeLimitOffset(false);
+
+ ojbIterator = broker.getIteratorByQuery(query);
+ // we expect a paging iterator instance
+ assertTrue(ojbIterator instanceof PagingIterator);
+
+ // jump to index
+ ojbIterator.absolute(absoluteIndex);
+ article = (InterfaceArticle)ojbIterator.next();
+ assertEquals("Expected Article stock=" + expectedStockValue, expectedStockValue, article.getStock());
+ if(supportsScrollableResultSet)
+ {
+ // jump back
+ ojbIterator.relative(-1);
+ article = (InterfaceArticle)ojbIterator.next();
+ assertEquals("Expected Article stock=" + expectedStockValue, expectedStockValue, article.getStock());
+ // jump back
+ ojbIterator.relative(-1);
+ assertTrue(ojbIterator.hasNext());
+ article = (InterfaceArticle)ojbIterator.next();
+ assertEquals("Expected Article stock=" + expectedStockValue, expectedStockValue, article.getStock());
+ if(allowRelativePlus1)
+ {
+ // jump forward 1
+ ojbIterator.relative(1);
+ article = (InterfaceArticle)ojbIterator.next();
+ assertEquals("Expected Article stock=" + (expectedStockValue + 2), expectedStockValue + 2, article.getStock());
+
+ // jump back two
+ ojbIterator.relative(-3);
+ article = (InterfaceArticle)ojbIterator.next();
+ assertEquals("Expected Article stock=" + expectedStockValue, expectedStockValue, article.getStock());
+ }
+ }
+ // manually release used resources
+ ojbIterator.releaseDbResources();
+
+
+ // -------------------------------------------------------------
+ // expect ChainingIterator instance, with extents, nativeLimit=true
+ // -------------------------------------------------------------
+ query = QueryFactory.newQuery(Article.class, crit);
+ // now we want all results with extents, in this case OJB
+ // will use a chaining iterator
+ query.setWithExtents(true);
+ query.setStartAtIndex(startIndex);
+ query.setEndAtIndex(endIndex);
+ broker.serviceConnectionManager().getConnectionDescriptor().setNativeLimitOffset(true);
+ ojbIterator = broker.getIteratorByQuery(query);
+ assertTrue(ojbIterator instanceof ChainingIterator);
+ // jump to index
+ ojbIterator.absolute(absoluteIndex);
+ article = (InterfaceArticle)ojbIterator.next();
+ assertEquals("Expected Article stock=" + expectedStockValue, expectedStockValue, article.getStock());
+ if(supportsScrollableResultSet)
+ {
+ // jump back
+ ojbIterator.relative(-1);
+ article = (InterfaceArticle)ojbIterator.next();
+ assertEquals("Expected Article stock=" + expectedStockValue, expectedStockValue, article.getStock());
+ // jump back
+ ojbIterator.relative(-1);
+ assertTrue(ojbIterator.hasNext());
+ article = (InterfaceArticle)ojbIterator.next();
+ assertEquals("Expected Article stock=" + expectedStockValue, expectedStockValue, article.getStock());
+ if(allowRelativePlus1)
+ {
+ // jump forward 1
+ ojbIterator.relative(1);
+ article = (InterfaceArticle)ojbIterator.next();
+ assertEquals("Expected Article stock=" + (expectedStockValue + 2), expectedStockValue + 2, article.getStock());
+
+ // jump back two
+ ojbIterator.relative(-3);
+ article = (InterfaceArticle)ojbIterator.next();
+ assertEquals("Expected Article stock=" + expectedStockValue, expectedStockValue, article.getStock());
+ }
+ }
+ // manually release used resources
+ ojbIterator.releaseDbResources();
+
+
+ // -------------------------------------------------------------
+ // expect ChainingIterator instance, with extents, nativeLimit=false
+ // -------------------------------------------------------------
+ query = QueryFactory.newQuery(Article.class, crit);
+ // now we want all results with extents, in this case OJB
+ // will use a chaining iterator
+ query.setWithExtents(true);
+ query.setStartAtIndex(startIndex);
+ query.setEndAtIndex(endIndex);
+ broker.serviceConnectionManager().getConnectionDescriptor().setNativeLimitOffset(false);
+ ojbIterator = broker.getIteratorByQuery(query);
+ assertTrue("Expect instance of "+ClassUtils.getShortClassName(ChainingIterator.class)
+ + " but was " + ojbIterator, ojbIterator instanceof ChainingIterator);
+
+ // jump to index
+ ojbIterator.absolute(absoluteIndex);
+ article = (InterfaceArticle)ojbIterator.next();
+ assertEquals("Expected Article stock=" + expectedStockValue, expectedStockValue, article.getStock());
+ if(supportsScrollableResultSet)
+ {
+ // jump back
+ ojbIterator.relative(-1);
+ article = (InterfaceArticle)ojbIterator.next();
+ assertEquals("Expected Article stock=" + expectedStockValue, expectedStockValue, article.getStock());
+ // jump back
+ ojbIterator.relative(-1);
+ assertTrue(ojbIterator.hasNext());
+ article = (InterfaceArticle)ojbIterator.next();
+ assertEquals("Expected Article stock=" + expectedStockValue, expectedStockValue, article.getStock());
+ if(allowRelativePlus1)
+ {
+ // jump forward 1
+ ojbIterator.relative(1);
+ article = (InterfaceArticle)ojbIterator.next();
+ assertEquals("Expected Article stock=" + (expectedStockValue + 2), expectedStockValue + 2, article.getStock());
+
+ // jump back two
+ ojbIterator.relative(-3);
+ article = (InterfaceArticle)ojbIterator.next();
+ assertEquals("Expected Article stock=" + expectedStockValue, expectedStockValue, article.getStock());
+ }
+ }
+ // manually release used resources
+ ojbIterator.releaseDbResources();
+ }
+ finally
+ {
+ broker.serviceConnectionManager().getConnectionDescriptor().setNativeLimitOffset(old);
+ }
+ }
+
+ public void testPagingPosition_1()
+ {
+ String name = "testPagingPosition_1_" + System.currentTimeMillis();
+ int articleCount = 20;
+ int startIndex = 10;
+ int endIndex = 14;
+ // move to first position
+ int absoluteIndex = 1;
+ int expectedStockValue = 10;
+ boolean allowRelativePlusOneCall = true;
+
+ pagingPositionTest(name, articleCount, startIndex, endIndex, absoluteIndex, expectedStockValue, allowRelativePlusOneCall);
+ }
+
+ public void testPagingPosition_2()
+ {
+ String name = "testPagingPosition_2_" + System.currentTimeMillis();
+ int articleCount = 20;
+ int startIndex = 10;
+ int endIndex = 15;
+ // move to third position
+ int absoluteIndex = 3;
+ int expectedStockValue = 12;
+ boolean allowRelativePlusOneCall = true;
+
+ pagingPositionTest(name, articleCount, startIndex, endIndex, absoluteIndex, expectedStockValue, allowRelativePlusOneCall);
+ }
+
+ public void testPagingPosition_3()
+ {
+ String name = "testPagingPosition_3_" + System.currentTimeMillis();
+ int articleCount = 20;
+ int startIndex = 10;
+ int endIndex = 14;
+ // move to last position
+ int absoluteIndex = 5;
+ int expectedStockValue = 14;
+ boolean allowRelativePlusOneCall = false;
+
+ pagingPositionTest(name, articleCount, startIndex, endIndex, absoluteIndex, expectedStockValue, allowRelativePlusOneCall);
+ }
+
+ public void testPagingPosition_4()
+ {
+ String name = "testPagingPosition_4_" + System.currentTimeMillis();
+ int articleCount = 20;
+ int startIndex = 10;
+ int endIndex = 14;
+ // move to last position
+ int absoluteIndex = -1;
+ int expectedStockValue = 14;
+ boolean allowRelativePlusOneCall = false;
+
+ pagingPositionTest(name, articleCount, startIndex, endIndex, absoluteIndex, expectedStockValue, allowRelativePlusOneCall);
+ }
+
+ public void testPagingPosition_5()
+ {
+ String name = "testPagingPosition_5_" + System.currentTimeMillis();
+ int articleCount = 20;
+ int startIndex = 10;
+ int endIndex = 14;
+ // move to first position
+ int absoluteIndex = -5;
+ int expectedStockValue = 10;
+ boolean allowRelativePlusOneCall = true;
+
+ pagingPositionTest(name, articleCount, startIndex, endIndex, absoluteIndex, expectedStockValue, allowRelativePlusOneCall);
+ }
+
+
+
+ public void testChainingIteratorPaging()
+ {
+ String name = "testChainingIteratorPaging_" + System.currentTimeMillis();
+ int count = 27;
+
+ List result = new ArrayList();
+ broker.beginTransaction();
+ for(int i=0; i<count; i++)
+ {
+ InterfaceArticle a;
+ if((i/3) % 3 == 0) a = new Article();
+ else if((i/3) % 3 == 1) a = new CdArticle();
+ else a = new BookArticle();
+ a.setArticleName(name);
+ a.setStock(i);
+ //System.out.println("store " + i + ": " + ClassUtils.getShortClassName(a.getClass()) + "[stock="+a.getStock()+"]");
+ broker.store(a);
+ result.add(a);
+ }
+ broker.commitTransaction();
+
+ // All Articles index in range
+ Criteria crit = new Criteria().addEqualTo("articleName", name);
+ QueryByCriteria query = QueryFactory.newQuery(Article.class, crit);
+ query.addOrderByAscending("stock");
+ query.addOrderByAscending("articleId");
+ query.setWithExtents(true);
+
+ int fullSize = broker.getCollectionByQuery(query).size();
+ assertEquals(count, fullSize);
+
+ // limit query to main class Article objects
+ query = QueryFactory.newQuery(Article.class, crit);
+ query.addOrderByAscending("stock");
+ query.addOrderByAscending("articleId");
+ query.setWithExtents(true);
+ query.setStartAtIndex(1);
+ query.setEndAtIndex(1);
+ OJBIterator ojbIter = broker.getIteratorByQuery(query);
+ int counter = 0;
+ while(ojbIter.hasNext())
+ {
+ InterfaceArticle o = (InterfaceArticle) ojbIter.next();
+ //System.out.println("o: " + o);
+ assertEquals(0, o.getStock() % 3);
+ ++counter;
+ }
+ assertEquals(3, counter);
+
+
+ query = QueryFactory.newQuery(Article.class, crit);
+ query.addOrderByAscending("stock");
+ query.addOrderByAscending("articleId");
+ query.setWithExtents(true);
+ query.setStartAtIndex(7);
+ query.setEndAtIndex(7);
+ ojbIter = broker.getIteratorByQuery(query);
+ counter = 0;
+ while(ojbIter.hasNext())
+ {
+ ++counter;
+ InterfaceArticle o = (InterfaceArticle) ojbIter.next();
+ //System.out.println("o: " + o);
+ assertEquals(0, o.getStock()%3);
+ }
+ assertEquals(3, counter);
+
+
+ query = QueryFactory.newQuery(Article.class, crit);
+ query.addOrderByAscending("stock");
+ query.addOrderByAscending("articleId");
+ query.setWithExtents(true);
+ query.setStartAtIndex(3);
+ query.setEndAtIndex(4);
+ ojbIter = broker.getIteratorByQuery(query);
+ counter = 0;
+ while(ojbIter.hasNext())
+ {
+ ++counter;
+ InterfaceArticle o = (InterfaceArticle) ojbIter.next();
+ //System.out.println("o: " + o);
+ int modValue = o.getStock() % 3;
+ assertTrue(modValue == 0 || modValue == 2);
+ }
+ assertEquals(6, counter);
+
+ query = QueryFactory.newQuery(Article.class, crit);
+ query.addOrderByAscending("stock");
+ query.addOrderByAscending("articleId");
+ query.setWithExtents(true);
+ query.setStartAtIndex(7);
+ query.setEndAtIndex(7);
+ ojbIter = broker.getIteratorByQuery(query);
+ counter = 0;
+ while(ojbIter.hasNext())
+ {
+ ++counter;
+ InterfaceArticle o = (InterfaceArticle) ojbIter.next();
+ //System.out.println("o: " + o);
+ assertEquals(0, o.getStock()%3);
+ }
+ assertEquals(3, counter);
+ }
+
+ public void testPagingIndicesOutOfRange()
+ {
+ OJBIterator ojbIter;
+ QueryByCriteria query;
+ int fullSize;
+
+ // All Articles index out of range
+ query = QueryFactory.newQuery(Article.class, new Criteria());
+ fullSize = broker.getCollectionByQuery(query).size();
+
+ // NOTE: If pagination/limit is used it's strongly recommended to order by
+ // a unique column to avoid problems with different result order
+ query.addOrderByAscending("articleId");
+ // if we use pagination it's mandatory not to query "extents" too,
+ // because else it will end in multiple limit queries (one for each extent)
+ // thus the result will be pagination_size * extents
+ query.setWithExtents(false);
+ query.setStartAtIndex(fullSize + 5);
+ query.setEndAtIndex(fullSize + 14);
+ ojbIter = broker.getIteratorByQuery(query);
+ assertEquals("indices out of range expecting 0 rows", 0,ojbIter.size());
+ ojbIter.releaseDbResources();
+ }
+
+ public void testPagingEndIndexOutOfRange()
+ {
+ OJBIterator ojbIter;
+ Criteria crit;
+ QueryByCriteria query;
+ int fullSize;
+
+ // All Articles index out of range
+ crit = new Criteria();
+ query = QueryFactory.newQuery(Article.class, crit);
+ // NOTE: If pagination/limit is used it's strongly recommended to order by
+ // a unique column to avoid problems with different result order
+ query.addOrderByAscending("articleId");
+ // if we use pagination it's mandatory not to query "extents" too,
+ // because else it will end in multiple limit queries (one for each extent)
+ // thus the result will be pagination_size * extents
+ query.setWithExtents(false);
+ fullSize = broker.getCollectionByQuery(query).size();
+
+ query.setStartAtIndex(fullSize - 9);
+ query.setEndAtIndex(fullSize + 9);
+ ojbIter = broker.getIteratorByQuery(query);
+ assertEquals("end index out of range expecting 0 rows", 10,ojbIter.size());
+ ojbIter.releaseDbResources();
+ }
+
+ public void testPagingEmptyIterator()
+ {
+ OJBIterator ojbIter;
+ Criteria crit;
+ QueryByCriteria query;
+
+ // looking for inexistent Article
+ crit = new Criteria();
+ crit.addEqualTo("articleId",new Integer(-777));
+ query = QueryFactory.newQuery(Article.class, crit);
+ int fullSize = broker.getCollectionByQuery(query).size();
+
+ // NOTE: If pagination/limit is used it's strongly recommended to order by
+ // a unique column to avoid problems with different result order
+ query.addOrderByAscending("articleId");
+ // if we use pagination it's mandatory not to query "extents" too,
+ // because else it will end in multiple limit queries (one for each extent)
+ // thus the result will be pagination_size * extents
+ query.setWithExtents(false);
+ query.setStartAtIndex(10);
+ query.setEndAtIndex(14);
+ ojbIter = broker.getIteratorByQuery(query);
+ assertEquals("index 10 - 14 expecting 0 rows for empty iterator", 0,ojbIter.size());
+ ojbIter.releaseDbResources();
+ }
+
+ private Article createArticle(ProductGroup group, String name)
+ {
+ Article a = new Article();
+ a.setArticleName(name);
+ a.setIsSelloutArticle(true);
+ a.setMinimumStock(100);
+ a.setOrderedUnits(17);
+ a.setPrice(0.45);
+ if(group != null)
+ {
+ a.setProductGroup(group);
+ group.add(a);
+ }
+ a.setStock(234);
+ a.setSupplierId(4);
+ a.setUnit("bottle");
+ return a;
+ }
+
+
+
+
+ //=======================================================
+ // inner test classes
+ //=======================================================
+ /*
+ NOTE: Take care of endless loops when change override toString method!!!!
+ */
+ public static class Book implements Serializable
+ {
+ private Integer id;
+ private String title;
+ private Date publicationDate;
+ private byte[] cover;
+ private Integer version;
+ private Integer fkPublisher;
+
+ private List authors;
+ private List reviews;
+ private Publisher publisher;
+
+ public Book()
+ {
+ }
+
+ public Book(String title, Date publicationDate, byte[] cover)
+ {
+ this.title = title;
+ this.publicationDate = publicationDate;
+ this.cover = cover;
+ }
+
+ public String toString()
+ {
+ return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+ .append("id", id)
+ .append("title", title)
+ .append("publicationDate", publicationDate)
+ .append("version", version)
+ .append("fkPublisher", fkPublisher)
+ .append("cover", cover)
+ .append("authors.size", authors != null ? authors.size() : 0)
+ .append("reviews.size", reviews != null ? reviews.size() : 0)
+ .append("publisher", publisher)
+ .toString();
+ }
+
+ public void addAuthor(Author author)
+ {
+ if(authors == null)
+ {
+ authors = new ArrayList();
+ }
+ authors.add(author);
+ }
+
+ public void addReview(Review review)
+ {
+ if(reviews == null)
+ {
+ reviews = new ArrayList();
+ }
+ reviews.add(review);
+ }
+
+ public boolean removeReview(Review review)
+ {
+ if(reviews != null) return reviews.remove(review);
+ else return false;
+ }
+
+ public Integer getId()
+ {
+ return id;
+ }
+
+ public void setId(Integer id)
+ {
+ this.id = id;
+ }
+
+ public String getTitle()
+ {
+ return title;
+ }
+
+ public void setTitle(String title)
+ {
+ this.title = title;
+ }
+
+ public Date getPublicationDate()
+ {
+ return publicationDate;
+ }
+
+ public void setPublicationDate(Date publicationDate)
+ {
+ this.publicationDate = publicationDate;
+ }
+
+ public byte[] getCover()
+ {
+ return cover;
+ }
+
+ public void setCover(byte[] cover)
+ {
+ this.cover = cover;
+ }
+
+ public Integer getVersion()
+ {
+ return version;
+ }
+
+ public void setVersion(Integer version)
+ {
+ this.version = version;
+ }
+
+ public List getAuthors()
+ {
+ return authors;
+ }
+
+ public void setAuthors(List authors)
+ {
+ this.authors = authors;
+ }
+
+ public List getReviews()
+ {
+ return reviews;
+ }
+
+ public void setReviews(List reviews)
+ {
+ this.reviews = reviews;
+ }
+
+ public Publisher getPublisher()
+ {
+ return publisher;
+ }
+
+ public void setPublisher(Publisher publisher)
+ {
+ this.publisher = publisher;
+ }
+ }
+
+ public static class Author implements Serializable
+ {
+ private Integer id;
+ private String name;
+ private List books;
+ private Integer version;
+ private Publisher publisher;
+ private Integer fkPublisher;
+
+ public Author()
+ {
+ }
+
+ public Author(String name, List books)
+ {
+ this.name = name;
+ this.books = books;
+ }
+
+ public void addBook(Book book)
+ {
+ if(books == null)
+ {
+ books = new ArrayList();
+ }
+ books.add(book);
+ }
+
+ public Integer getId()
+ {
+ return id;
+ }
+
+ public void setId(Integer id)
+ {
+ this.id = id;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public Integer getVersion()
+ {
+ return version;
+ }
+
+ public void setVersion(Integer version)
+ {
+ this.version = version;
+ }
+
+ public List getBooks()
+ {
+ return books;
+ }
+
+ public void setBooks(List books)
+ {
+ this.books = books;
+ }
+
+ public Publisher getPublisher()
+ {
+ return publisher;
+ }
+
+ public void setPublisher(Publisher publisher)
+ {
+ this.publisher = publisher;
+ }
+ }
+
+ public static interface Publisher extends Serializable
+ {
+ public Integer getId();
+ public void setId(Integer id);
+ public String getName();
+ public void setName(String name);
+ public Integer getVersion();
+ public void setVersion(Integer version);
+ public List getAuthors();
+ public void setAuthors(List authors);
+ public void addAuthor(Author author);
+ public List getBooks();
+ public void setBooks(List books);
+ public void addBook(Book book);
+ }
+
+ public static class PublisherImpl implements Publisher
+ {
+ private Integer id;
+ private String name;
+ private Integer version;
+ private List authors;
+ private List books;
+
+ public PublisherImpl()
+ {
+ }
+
+ public PublisherImpl(String name)
+ {
+ this.name = name;
+ }
+
+ public Integer getId()
+ {
+ return id;
+ }
+
+ public void setId(Integer id)
+ {
+ this.id = id;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public Integer getVersion()
+ {
+ return version;
+ }
+
+ public void setVersion(Integer version)
+ {
+ this.version = version;
+ }
+
+ public List getAuthors()
+ {
+ return authors;
+ }
+
+ public void setAuthors(List authors)
+ {
+ this.authors = authors;
+ }
+
+ public void addAuthor(Author author)
+ {
+ if(authors == null)
+ {
+ authors = new ArrayList();
+ }
+ if(! authors.contains(author)) authors.add(author);
+ }
+
+ public List getBooks()
+ {
+ return books;
+ }
+
+ public void setBooks(List books)
+ {
+ this.books = books;
+ }
+
+ public void addBook(Book book)
+ {
+ if(books == null)
+ {
+ books = new ArrayList();
+ }
+ if(! books.contains(book)) books.add(book);
+ }
+ }
+
+ public static class Review implements Serializable
+ {
+ private Integer id;
+ private Integer vote;
+ private String summary;
+ private Integer fkBook;
+ private Integer version;
+ private Author author;
+ private Book book;
+
+ public Review()
+ {
+ }
+
+ public Review(String summary, Integer vote, Book book)
+ {
+ this.summary = summary;
+ this.vote = vote;
+ this.book = book;
+ }
+
+ public Review(String summary, Integer vote)
+ {
+ this.summary = summary;
+ this.vote = vote;
+ }
+
+ public Review(String summary)
+ {
+ this.summary = summary;
+ }
+
+ public Integer getId()
+ {
+ return id;
+ }
+
+ public Integer getVote()
+ {
+ return vote;
+ }
+
+ public void setVote(Integer vote)
+ {
+ this.vote = vote;
+ }
+
+ public void setId(Integer id)
+ {
+ this.id = id;
+ }
+
+ public Integer getFkBook()
+ {
+ return fkBook;
+ }
+
+ public void setFkBook(Integer fkBook)
+ {
+ this.fkBook = fkBook;
+ }
+
+ public String getSummary()
+ {
+ return summary;
+ }
+
+ public void setSummary(String summary)
+ {
+ this.summary = summary;
+ }
+
+ public Integer getVersion()
+ {
+ return version;
+ }
+
+ public void setVersion(Integer version)
+ {
+ this.version = version;
+ }
+
+ public Author getAuthor()
+ {
+ return author;
+ }
+
+ public void setAuthor(Author author)
+ {
+ this.author = author;
+ }
+
+ public Book getBook()
+ {
+ return book;
+ }
+
+ public void setBook(Book book)
+ {
+ this.book = book;
+ }
+
+ public boolean equals(Object obj)
+ {
+ boolean result = false;
+ if(obj instanceof Review)
+ {
+ Review other = (Review) obj;
+ result = new EqualsBuilder()
+ .append(id, other.id)
+ .append(summary, other.summary)
+ .append(version, other.version)
+ .append(fkBook, other.fkBook)
+ .append(author, other.author)
+ .isEquals();
+ }
+ return result;
+ }
+
+ public String toString()
+ {
+ return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE, false);
+ }
+ }
+
+}
Modified: db/ojb/trunk/src/test/org/apache/ojb/broker/PersistenceBrokerTest.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/test/org/apache/ojb/broker/PersistenceBrokerTest.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/test/org/apache/ojb/broker/PersistenceBrokerTest.java (original)
+++ db/ojb/trunk/src/test/org/apache/ojb/broker/PersistenceBrokerTest.java Thu Mar 1 17:33:44 2007
@@ -1155,7 +1155,7 @@
Criteria criteria = new Criteria();
criteria.addEqualTo("articleName", name);
// criteria.addEqualTo("isSelloutArticle", new Boolean(true));
- Query query = QueryFactory.newQuery(Article.class, criteria);
+ QueryByCriteria query = QueryFactory.newQuery(Article.class, criteria);
Collection col = broker.getCollectionByQuery(query);
assertEquals("size of collection should be zero", 0, col.size());
//2. insert 5 matching items
@@ -1171,8 +1171,15 @@
Article a5 = createArticle(null, name);
broker.store(a5);
broker.commitTransaction();
-
broker.clearCache();
+
+ // NOTE: If pagination/limit is used it's strongly recommended to order by
+ // a unique column to avoid problems with different result order
+ query.addOrderByAscending("articleId");
+ // if we use pagination it's mandatory not to query "extents" too,
+ // because else it will end in multiple limit queries (one for each extent)
+ // thus the result will be pagination_size * extents
+ query.setWithExtents(false);
// 3. set query start and end
query.setStartAtIndex(2);
query.setEndAtIndex(5);
@@ -1191,6 +1198,13 @@
assertTrue("Id should be a number of the generated articles", range.containsInteger(id));
}
+ // NOTE: If pagination/limit is used it's strongly recommended to order by
+ // a unique column to avoid problems with different result order
+ query.addOrderByAscending("articleId");
+ // if we use pagination it's mandatory not to query "extents" too,
+ // because else it will end in multiple limit queries (one for each extent)
+ // thus the result will be pagination_size * extents
+ query.setWithExtents(false);
// read one item only
// 1. set query start equals end
query.setStartAtIndex(4);
@@ -1675,6 +1689,7 @@
Identity oid = broker.serviceIdentity().buildIdentity(person);
Person serializedPerson = (Person) SerializationUtils.clone(person);
broker.store(person);
+ broker.store(person);
broker.store(serializedPerson);
broker.commitTransaction();
@@ -1759,142 +1774,6 @@
iterSize = ojbIter.size();
assertEquals("collSize == iterSize", collSize , iterSize);
- ojbIter.releaseDbResources();
- }
-
- public void testPaging()
- {
- OJBIterator ojbIter;
- Criteria crit;
- QueryByCriteria query;
-
- // All Articles index in range
- crit = new Criteria();
- query = QueryFactory.newQuery(Article.class, crit);
- int fullSize = broker.getCollectionByQuery(query).size();
-
- query.setStartAtIndex(10);
- query.setEndAtIndex(14);
- ojbIter = (OJBIterator)broker.getIteratorByQuery(query);
- assertEquals("index 10 - 14 expecting 5 rows", 5,ojbIter.size());
- ojbIter.releaseDbResources();
- }
-
- public void testPagingPosition()
- {
- String name = "testPagingPosition_" + System.currentTimeMillis();
- broker.beginTransaction();
- for(int i=1; i<21; i++)
- {
- Article a = createArticle(null, name);
- a.setStock(i);
- broker.store(a);
- }
- broker.commitTransaction();
-
- OJBIterator ojbIter;
- Criteria crit;
- QueryByCriteria query;
- Collection fullColl, pagedColl;
- InterfaceArticle article;
-
- // All Articles index in range
- crit = new Criteria();
- crit.addEqualTo("articleName", name);
- query = QueryFactory.newQuery(Article.class, crit);
- query.addOrderByAscending("stock");
- fullColl = broker.getCollectionByQuery(query);
- assertEquals(20, fullColl.size());
-
- // limited query
- query.setStartAtIndex(10);
- query.setEndAtIndex(14);
- pagedColl = broker.getCollectionByQuery(query);
-
- ojbIter = (OJBIterator)broker.getIteratorByQuery(query);
-
- assertEquals("collection- and iterator-size must match", pagedColl.size(), ojbIter.size());
- assertEquals("index 10 - 14 expecting 5 rows", 5,ojbIter.size());
-
- ojbIter.absolute(2);
- article = (InterfaceArticle)ojbIter.next();
- assertEquals("Article stock=12", article.getStock(), 12);
-
- ojbIter.relative(-1);
- article = (InterfaceArticle)ojbIter.next();
- assertEquals("Article id=12", article.getStock(), 12);
-
- ojbIter.relative(-1);
- article = (InterfaceArticle)ojbIter.next();
- assertEquals("Article id=12", article.getStock(), 12);
-
- // last
- ojbIter.absolute(12);
- article = (InterfaceArticle)ojbIter.next();
- assertEquals("Article id=15", article.getStock(), 15);
-
- // first
- ojbIter.absolute(-12);
- article = (InterfaceArticle)ojbIter.next();
- assertEquals("Article id=10", article.getStock(), 10);
-
- ojbIter.releaseDbResources();
- }
-
- public void testPagingIndicesOutOfRange()
- {
- OJBIterator ojbIter;
- Criteria crit;
- QueryByCriteria query;
- int fullSize;
-
- // All Articles index out of range
- crit = new Criteria();
- query = QueryFactory.newQuery(Article.class, crit);
- fullSize = broker.getCollectionByQuery(query).size();
-
- query.setStartAtIndex(fullSize + 5);
- query.setEndAtIndex(fullSize + 14);
- ojbIter = (OJBIterator)broker.getIteratorByQuery(query);
- assertEquals("indices out of range expecting 0 rows", 0,ojbIter.size());
- ojbIter.releaseDbResources();
- }
-
- public void testPagingEndIndexOutOfRange()
- {
- OJBIterator ojbIter;
- Criteria crit;
- QueryByCriteria query;
- int fullSize;
-
- // All Articles index out of range
- crit = new Criteria();
- query = QueryFactory.newQuery(Article.class, crit);
- fullSize = broker.getCollectionByQuery(query).size();
-
- query.setStartAtIndex(fullSize - 9);
- query.setEndAtIndex(fullSize + 9);
- ojbIter = (OJBIterator)broker.getIteratorByQuery(query);
- assertEquals("end index out of range expecting 10 rows", 10,ojbIter.size());
- ojbIter.releaseDbResources();
- }
-
- public void testPagingEmptyIterator()
- {
- OJBIterator ojbIter;
- Criteria crit;
- QueryByCriteria query;
-
- // looking for inexistent Article
- crit = new Criteria();
- crit.addEqualTo("articleId",new Integer(-777));
- query = QueryFactory.newQuery(Article.class, crit);
- int fullSize = broker.getCollectionByQuery(query).size();
-
- query.setStartAtIndex(10);
- query.setEndAtIndex(14);
- ojbIter = (OJBIterator)broker.getIteratorByQuery(query);
- assertEquals("index 10 - 14 expecting 0 rows for empty iterator", 0,ojbIter.size());
ojbIter.releaseDbResources();
}
}
Modified: db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityHsqlTest.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityHsqlTest.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityHsqlTest.java (original)
+++ db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityHsqlTest.java Thu Mar 1 17:33:44 2007
@@ -38,7 +38,8 @@
protected void initDBDependend() throws Exception
{
dropConstraintMainTable = "ALTER TABLE NATIVE_MAIN_OBJECT DROP CONSTRAINT MAIN_REF_FK";
- createMainTable = "CREATE TABLE NATIVE_MAIN_OBJECT(NATIVE_ID IDENTITY NOT NULL PRIMARY KEY, REF_ID int,NAME VARCHAR(250))";
+ createMainTable = "CREATE TABLE NATIVE_MAIN_OBJECT(NATIVE_ID IDENTITY NOT NULL PRIMARY KEY, CLASS_NAME VARCHAR(250), REF_ID int,NAME VARCHAR(250))";
+ createDerivedTable = "CREATE TABLE NATIVE_DERIVED_OBJECT(NATIVE_ID IDENTITY NOT NULL PRIMARY KEY, CLASS_NAME VARCHAR(250), REF_ID int,NAME VARCHAR(250))";
createRefTable = "CREATE TABLE NATIVE_REFERENCE_OBJECT (NATIVE_ID IDENTITY NOT NULL PRIMARY KEY," +
" NAME VARCHAR(250), OJB_CONCRETE_CLASS VARCHAR(250), FK_ID int, REF_ID int, SINGLE_REF_FK BIGINT" +
" , FOREIGN KEY (FK_ID) REFERENCES NATIVE_MAIN_OBJECT (NATIVE_ID) )";
Modified: db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityMaxDBTest.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityMaxDBTest.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityMaxDBTest.java (original)
+++ db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityMaxDBTest.java Thu Mar 1 17:33:44 2007
@@ -40,7 +40,9 @@
{
dropConstraintMainTable = "ALTER TABLE NATIVE_MAIN_OBJECT DROP FOREIGN KEY MAIN_REF_FK";
createMainTable = "CREATE TABLE NATIVE_MAIN_OBJECT" +
- "(NATIVE_ID SERIAL PRIMARY KEY, REF_ID FIXED(10), NAME VARCHAR(250))";
+ "(NATIVE_ID SERIAL PRIMARY KEY, CLASS_NAME VARCHAR(250), REF_ID FIXED(10), NAME VARCHAR(250))";
+ createDerivedTable = "CREATE TABLE NATIVE_DERIVED_OBJECT" +
+ "(NATIVE_ID SERIAL PRIMARY KEY, CLASS_NAME VARCHAR(250), REF_ID FIXED(10), NAME VARCHAR(250))";
createRefTable =
"CREATE TABLE NATIVE_REFERENCE_OBJECT(NATIVE_ID SERIAL PRIMARY KEY," +
" NAME VARCHAR(250), OJB_CONCRETE_CLASS VARCHAR(250), FK_ID FIXED(10), REF_ID FIXED(10)," +
Modified: db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityMySqlTest.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityMySqlTest.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityMySqlTest.java (original)
+++ db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityMySqlTest.java Thu Mar 1 17:33:44 2007
@@ -38,7 +38,12 @@
protected void initDBDependend() throws Exception
{
dropConstraintMainTable = "ALTER TABLE NATIVE_MAIN_OBJECT DROP FOREIGN KEY MAIN_REF_FK";
- createMainTable = "CREATE TABLE NATIVE_MAIN_OBJECT(NATIVE_ID int(11) NOT NULL PRIMARY KEY auto_increment,REF_ID int(11),NAME VARCHAR(250))";
+ createMainTable = "CREATE TABLE NATIVE_MAIN_OBJECT(" +
+ "NATIVE_ID int(11) NOT NULL PRIMARY KEY auto_increment," +
+ "CLASS_NAME VARCHAR(250),REF_ID int(11),NAME VARCHAR(250))";
+ createDerivedTable = "CREATE TABLE NATIVE_DERIVED_OBJECT(" +
+ "NATIVE_ID int(11) NOT NULL PRIMARY KEY auto_increment," +
+ "CLASS_NAME VARCHAR(250),REF_ID int(11),NAME VARCHAR(250))";
createRefTable =
"CREATE TABLE NATIVE_REFERENCE_OBJECT (NATIVE_ID int(11) NOT NULL PRIMARY KEY auto_increment," +
" NAME VARCHAR(250), OJB_CONCRETE_CLASS VARCHAR(250), FK_ID int, REF_ID int(11), SINGLE_REF_FK BIGINT" +
Modified: db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityTest.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityTest.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityTest.java (original)
+++ db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityTest.java Thu Mar 1 17:33:44 2007
@@ -71,8 +71,10 @@
// Statements for MainObject table
protected String dropMainTable = "DROP TABLE NATIVE_MAIN_OBJECT";
+ protected String dropDerivedTable = "DROP TABLE NATIVE_DERIVED_OBJECT";
protected String dropRefTable = "DROP TABLE NATIVE_REFERENCE_OBJECT";
protected String insertDummyRowMainTable = "INSERT INTO NATIVE_MAIN_OBJECT (NAME) VALUES ('Dummy_1')";
+ protected String insertDummyRowDerivedTable = "INSERT INTO NATIVE_DERIVED_OBJECT (NAME) VALUES ('Dummy_1')";
protected String insertDummyRowRefTable = "INSERT INTO NATIVE_REFERENCE_OBJECT (NAME) VALUES ('Dummy_2')";
protected String addConstraintMainTableToRefTable = "ALTER TABLE NATIVE_MAIN_OBJECT ADD CONSTRAINT " +
@@ -80,6 +82,7 @@
protected String dropConstraintMainTable;
protected String createMainTable;
+ protected String createDerivedTable;
protected String createRefTable;
protected Platform platform;
@@ -102,10 +105,13 @@
try{executeStatement(dropConstraintMainTable);}catch(Exception e){}
try{executeStatement(dropRefTable);}catch(Exception e){}
try{executeStatement(dropMainTable);}catch(Exception e){}
+ try{executeStatement(dropDerivedTable);}catch(Exception e){}
executeStatement(createMainTable);
+ executeStatement(createDerivedTable);
executeStatement(createRefTable);
executeStatement(addConstraintMainTableToRefTable);
executeStatement(insertDummyRowMainTable);
+ executeStatement(insertDummyRowDerivedTable);
executeStatement(insertDummyRowRefTable);
}
@@ -1128,6 +1134,7 @@
public static class MainObject implements DatabaseIdentityTest.MainObjectIF
{
private Long identifier;
+ private String ojbConcreteClass;
private String name;
private List allReferences;
// we use anonymous field for FK
@@ -1136,10 +1143,12 @@
public MainObject()
{
+ ojbConcreteClass = this.getClass().getName();
}
public MainObject(Long identifier, String name)
{
+ this();
this.identifier = identifier;
this.name = name;
}
@@ -1199,6 +1208,18 @@
.append("allReferences", (allReferences != null ? allReferences.toString() : "null"))
.append("singleReference", (singleReference != null ? singleReference.getClass().toString(): "null"))
.toString();
+ }
+ }
+
+ public static class DerivedObject extends MainObject
+ {
+ public DerivedObject()
+ {
+ }
+
+ public DerivedObject(Long identifier, String name)
+ {
+ super(identifier, name);
}
}
Modified: db/ojb/trunk/src/test/org/apache/ojb/odmg/DListTest.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/test/org/apache/ojb/odmg/DListTest.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/test/org/apache/ojb/odmg/DListTest.java (original)
+++ db/ojb/trunk/src/test/org/apache/ojb/odmg/DListTest.java Thu Mar 1 17:33:44 2007
@@ -450,6 +450,7 @@
c = createObject(name);
d = createObject(name);
e = createObject(name);
+ tx.checkpoint();
bag1.add(a);
bag1.add(b);
bag1.add(c);
Modified: db/ojb/trunk/src/test/org/apache/ojb/odmg/ObjectImageTest.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/test/org/apache/ojb/odmg/ObjectImageTest.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/test/org/apache/ojb/odmg/ObjectImageTest.java (original)
+++ db/ojb/trunk/src/test/org/apache/ojb/odmg/ObjectImageTest.java Thu Mar 1 17:33:44 2007
@@ -132,7 +132,6 @@
tx.begin();
database.makePersistent(book);
tx.commit();
-
Integer version = book.getVersion();
assertTrue(book.getVersion().intValue() > 0);
@@ -144,6 +143,11 @@
Collection result = (Collection) query.execute();
assertEquals(1, result.size());
Book b = (Book) result.iterator().next();
+
+ // replace date value with real date stored in the DB (this can
+ // differ dependend on the used DB, e.g. with/without nano sec support, ...)
+ date = b.getPublicationDate();
+
assertEquals(version, b.getVersion());
tx.commit();
@@ -206,6 +210,11 @@
Collection result = (Collection) query.execute();
assertEquals(1, result.size());
Book b = (Book) result.iterator().next();
+
+ // replace date value with real date stored in the DB (this can
+ // differ dependend on the used DB, e.g. with/without nano sec support, ...)
+ date = b.getPublicationDate();
+
assertEquals(version, b.getVersion());
tx.commit();
Modified: db/ojb/trunk/src/test/org/apache/ojb/repository.xml
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/test/org/apache/ojb/repository.xml?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/test/org/apache/ojb/repository.xml (original)
+++ db/ojb/trunk/src/test/org/apache/ojb/repository.xml Thu Mar 1 17:33:44 2007
@@ -49,6 +49,7 @@
<!ENTITY junit_cloneable SYSTEM "repository_junit_cloneable.xml">
<!ENTITY junit_inheritance SYSTEM "repository_junit_inheritance.xml">
<!ENTITY junit_pathClass SYSTEM "repository_junit_pathClass.xml">
+<!ENTITY junit_pagination SYSTEM "repository_junit_pagination.xml">
<!ENTITY junit_perf_test SYSTEM "repository_perf_test.xml">
<!ENTITY user SYSTEM "repository_user.xml">
@@ -62,14 +63,15 @@
<!-- include all used database connections -->
&database;
- <!-- include ojb internal mappings here -->
+ <!-- include ojb internal mappings here, can be removed (with <!ENTITY entry)
+ if internal tables not used. See documentation platform-guide -->
&internal;
<!-- include user defined mappings here -->
&user;
<!-- include mappings for JUnit tests -->
- <!-- This could be removed (with <!ENTITY entry),
+ <!-- This can be removed (with <!ENTITY entry),
if junit test suite was not used
-->
&junit;
@@ -81,8 +83,10 @@
&junit_cloneable;
&junit_inheritance;
&junit_pathClass;
+ &junit_pagination;
&junit_perf_test;
- <!-- include mappings for the EJB-examples -->
+ <!-- include mappings for the EJB-examples, comment in before run
+ the ejb-example tests -->
<!-- &ejb; -->
</descriptor-repository>
Modified: db/ojb/trunk/src/test/org/apache/ojb/repository_database.xml
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/test/org/apache/ojb/repository_database.xml?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/test/org/apache/ojb/repository_database.xml (original)
+++ db/ojb/trunk/src/test/org/apache/ojb/repository_database.xml Thu Mar 1 17:33:44 2007
@@ -16,20 +16,21 @@
*/
-->
<!--
-Define here all used connections.
+Define all database connections here.
One defined connection should be defined as the default one,
-by set default-connection="true" - this could be done at runtime too.
+by setingt default-connection="true" - this could be done at runtime too.
It is possible to set user/password at
-runtime or let login different users at runtime using the same
-database. Use different PBKey with same jcdAlias name but
-different user/password.
+runtime or to let different users login at runtime
+using the same database.
+Use PBKey objects for the same jcdAlias name,
+but with different user/password.
-Ditto it is possible to add jdbc-connection-descriptor at runtime
-using the MetadataManager.
+It is also possible to add jdbc-connection-descriptor elements
+at runtime, using the MetadataManager.
-->
- <!-- this connection was used as the default one within OJB -->
+ <!-- This connection is used as the default one within OJB -->
<jdbc-connection-descriptor
jcd-alias="@JCD_ALIAS@"
default-connection="true"
@@ -46,6 +47,15 @@
ignoreAutoCommitExceptions="false"
>
+ <!--
+ If set 'true' OJB use the native database LIMIT and OFFSET syntax
+ for limit and paging queries (if it's supported by the database and OJB's Platform
+ implementation class). If set 'false' OJB simulate limit and paging by a specific
+ result set iterator (this can result in bad performance on big result sets).
+ -->
+ <attribute attribute-name="nativeLimitOffset" attribute-value="true" />
+
+
<!-- ** Attributes with name prefix "platform." are used to allow database
platform class specific settings (PlatformXYZImpl classes) -->
@@ -53,11 +63,13 @@
Number of cached statements per connection using implicit caching with Oracle9i Connections.
See http://otn.oracle.com/sample_code/tech/java/sqlj_jdbc/files/jdbc30/StmtCacheSample/Readme.html-->
<attribute attribute-name="platform.oracle.statementCacheSize" attribute-value="15" />
+
<!-- Number of rows pre-fetched by the JDBC-driver for each executed query, when using row
pre-fetching with Oracle Connections (Oracle9i or higher). Note: this setting can be overridden
by specifying a connection-pool attribute with name="jdbc.defaultRowPrefetch".
See http://otn.oracle.com/sample_code/tech/java/sqlj_jdbc/files/advanced/RowPrefetchSample/Readme.html -->
<attribute attribute-name="platform.oracle.prefetchSize" attribute-value="20" />
+
<!-- If set to value >0 Oracle's native batch statement handling will be enabled by OJB
(Oracle9i or higher). If 0 or not specified the JDBC standard batch methods are used.
See http://technet.oracle.com/products/oracle9i/daily/jun07.html -->
@@ -204,8 +216,15 @@
<!-- attribute attribute-name="seq.cycle" attribute-value="false"/ -->
<!-- attribute attribute-name="seq.cache" attribute-value="20"/ -->
<!-- attribute attribute-name="seq.order" attribute-value="false"/ -->
- </sequence-manager>
+ <!-- optional attributes supported by SequenceManagerIdentityImpl, more details
+ please see "Sequence Manager" guide or/and javadoc of classes for more information -->
+ <!-- If set 'true' OJB use the JDBC 3.0 method "Statement.getGeneratedKeys()"
+ to obtain generated database identity keys. If set 'false' OJB use a separate
+ database specific "last identity call" query to request the generated identity key. -->
+ <attribute attribute-name="seq.generatedKeys" attribute-value="true"/>
+
+ </sequence-manager>
</jdbc-connection-descriptor>
<!-- Datasource example -->
@@ -217,6 +236,7 @@
jndi-datasource-name="java:DefaultDS"
username="sa"
password=""
+ batch-mode="false"
useAutoCommit="0"
ignoreAutoCommitExceptions="false"
>
Modified: db/ojb/trunk/src/test/org/apache/ojb/repository_junit_meta_seq.xml
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/test/org/apache/ojb/repository_junit_meta_seq.xml?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/test/org/apache/ojb/repository_junit_meta_seq.xml (original)
+++ db/ojb/trunk/src/test/org/apache/ojb/repository_junit_meta_seq.xml Thu Mar 1 17:33:44 2007
@@ -518,6 +518,8 @@
class="org.apache.ojb.broker.sequence.DatabaseIdentityTest$MainObject"
table="NATIVE_MAIN_OBJECT"
>
+ <extent-class class-ref="org.apache.ojb.broker.sequence.DatabaseIdentityTest$DerivedObject" />
+
<field-descriptor
name="identifier"
column="NATIVE_ID"
@@ -525,6 +527,66 @@
primarykey="true"
autoincrement="true"
access="readonly"
+ />
+
+ <field-descriptor
+ name="ojbConcreteClass"
+ column="CLASS_NAME"
+ jdbc-type="VARCHAR"
+ />
+
+ <field-descriptor
+ name="refFK"
+ column="REF_ID"
+ jdbc-type="BIGINT"
+ access="anonymous"
+ />
+
+ <field-descriptor
+ name="name"
+ column="NAME"
+ jdbc-type="VARCHAR"
+ />
+
+ <reference-descriptor
+ name="singleReference"
+ class-ref="org.apache.ojb.broker.sequence.DatabaseIdentityTest$SingleReference"
+ proxy="false"
+ auto-retrieve="true"
+ auto-update="none"
+ auto-delete="none">
+ <foreignkey field-ref="refFK"/>
+ </reference-descriptor>
+
+ <collection-descriptor
+ name="allReferences"
+ element-class-ref="org.apache.ojb.broker.sequence.DatabaseIdentityTest$CollectionReference"
+ auto-retrieve="true"
+ auto-update="none"
+ auto-delete="none"
+ >
+ <orderby name="refIdentifier" sort="DESC"/>
+ <inverse-foreignkey field-ref="fkIdentifier"/>
+ </collection-descriptor>
+ </class-descriptor>
+
+ <class-descriptor
+ class="org.apache.ojb.broker.sequence.DatabaseIdentityTest$DerivedObject"
+ table="NATIVE_DERIVED_OBJECT"
+ >
+ <field-descriptor
+ name="identifier"
+ column="NATIVE_ID"
+ jdbc-type="BIGINT"
+ primarykey="true"
+ autoincrement="true"
+ access="readonly"
+ />
+
+ <field-descriptor
+ name="ojbConcreteClass"
+ column="CLASS_NAME"
+ jdbc-type="VARCHAR"
/>
<field-descriptor
Added: db/ojb/trunk/src/test/org/apache/ojb/repository_junit_pagination.xml
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/test/org/apache/ojb/repository_junit_pagination.xml?view=auto&rev=513577
==============================================================================
--- db/ojb/trunk/src/test/org/apache/ojb/repository_junit_pagination.xml (added)
+++ db/ojb/trunk/src/test/org/apache/ojb/repository_junit_pagination.xml Thu Mar 1 17:33:44 2007
@@ -0,0 +1,262 @@
+
+<!-- =================================================== -->
+<!-- Mapping for ImageContainerTest -->
+<!-- =================================================== -->
+<class-descriptor
+ class="org.apache.ojb.broker.PaginationTest$Book"
+ table="PAGE_BOOK"
+ >
+ <field-descriptor
+ name="id"
+ column="ID_"
+ jdbc-type="INTEGER"
+ primarykey="true"
+ autoincrement="true"
+ />
+
+ <field-descriptor
+ name="title"
+ column="TITLE_"
+ jdbc-type="VARCHAR"
+ />
+
+ <field-descriptor
+ name="publicationDate"
+ column="DATE_"
+ jdbc-type="TIMESTAMP"
+ conversion="org.apache.ojb.broker.accesslayer.conversions.JavaDate2SqlTimestampFieldConversion"
+ />
+
+ <field-descriptor
+ name="cover"
+ column="COVER_"
+ jdbc-type="LONGVARBINARY"
+ />
+
+ <field-descriptor
+ name="version"
+ column="VERSION_"
+ jdbc-type="INTEGER"
+ locking="true"
+ />
+
+ <field-descriptor
+ name="fkPublisher"
+ column="FK_PUBLISHER"
+ jdbc-type="INTEGER"
+ field-class="org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldDirectImpl"
+ />
+
+ <reference-descriptor name="publisher"
+ class-ref="org.apache.ojb.broker.PaginationTest$Publisher"
+ proxy="true"
+ auto-retrieve="true"
+ auto-update="object"
+ auto-delete="object"
+ >
+ <foreignkey field-ref="fkPublisher"/>
+ </reference-descriptor>
+
+ <collection-descriptor
+ name="reviews"
+ element-class-ref="org.apache.ojb.broker.PaginationTest$Review"
+ proxy="true"
+ auto-retrieve="true"
+ auto-update="object"
+ auto-delete="object"
+ >
+ <orderby name="fkBook" sort="ASC"/>
+ <inverse-foreignkey field-ref="fkBook"/>
+ </collection-descriptor>
+
+ <collection-descriptor
+ name="authors"
+ collection-class="org.apache.ojb.broker.util.collections.ManageableArrayList"
+ element-class-ref="org.apache.ojb.broker.PaginationTest$Author"
+ indirection-table="PAGE_PUBLICATION"
+ proxy="true"
+ auto-retrieve="true"
+ auto-update="object"
+ auto-delete="object"
+ >
+ <fk-pointing-to-this-class column="BOOK_ID"/>
+ <fk-pointing-to-element-class column="AUTHOR_ID"/>
+ </collection-descriptor>
+</class-descriptor>
+
+<class-descriptor class="org.apache.ojb.broker.PaginationTest$Publisher">
+ <extent-class class-ref="org.apache.ojb.broker.PaginationTest$PublisherImpl"/>
+</class-descriptor>
+
+<class-descriptor
+ class="org.apache.ojb.broker.PaginationTest$PublisherImpl"
+ table="PAGE_PUBLISHER"
+ >
+ <field-descriptor
+ name="id"
+ column="ID_"
+ jdbc-type="INTEGER"
+ primarykey="true"
+ autoincrement="true"
+ />
+
+ <field-descriptor
+ name="name"
+ column="NAME_"
+ jdbc-type="VARCHAR"
+ />
+
+ <field-descriptor
+ name="version"
+ column="VERSION_"
+ jdbc-type="INTEGER"
+ locking="true"
+ />
+
+ <collection-descriptor
+ name="authors"
+ element-class-ref="org.apache.ojb.broker.PaginationTest$Author"
+ proxy="true"
+ auto-retrieve="true"
+ auto-update="object"
+ auto-delete="object"
+ >
+ <inverse-foreignkey field-ref="fkPublisher"/>
+ </collection-descriptor>
+
+ <collection-descriptor
+ name="books"
+ element-class-ref="org.apache.ojb.broker.PaginationTest$Book"
+ proxy="true"
+ auto-retrieve="true"
+ auto-update="object"
+ auto-delete="object"
+ >
+ <inverse-foreignkey field-ref="fkPublisher"/>
+ </collection-descriptor>
+
+</class-descriptor>
+
+<class-descriptor
+ class="org.apache.ojb.broker.PaginationTest$Author"
+ table="PAGE_AUTHOR"
+ >
+ <field-descriptor
+ name="id"
+ column="ID_"
+ jdbc-type="INTEGER"
+ primarykey="true"
+ autoincrement="true"
+ />
+
+ <field-descriptor
+ name="name"
+ column="NAME_"
+ jdbc-type="VARCHAR"
+ />
+
+ <field-descriptor
+ name="version"
+ column="VERSION_"
+ jdbc-type="INTEGER"
+ locking="true"
+ />
+
+ <field-descriptor
+ name="fkPublisher"
+ column="FK_PUBLISHER"
+ jdbc-type="INTEGER"
+ field-class="org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldDirectImpl"
+ />
+
+ <reference-descriptor name="publisher"
+ class-ref="org.apache.ojb.broker.PaginationTest$Publisher"
+ proxy="true"
+ auto-retrieve="true"
+ auto-update="object"
+ auto-delete="object"
+ >
+ <foreignkey field-ref="fkPublisher"/>
+ </reference-descriptor>
+
+ <collection-descriptor
+ name="books"
+ collection-class="org.apache.ojb.broker.util.collections.ManageableArrayList"
+ element-class-ref="org.apache.ojb.broker.PaginationTest$Book"
+ indirection-table="PAGE_PUBLICATION"
+ proxy="true"
+ auto-retrieve="true"
+ auto-update="object"
+ auto-delete="object"
+ >
+ <fk-pointing-to-this-class column="AUTHOR_ID"/>
+ <fk-pointing-to-element-class column="BOOK_ID"/>
+ </collection-descriptor>
+
+</class-descriptor>
+
+<class-descriptor
+ class="org.apache.ojb.broker.PaginationTest$Review"
+ table="PAGE_REVIEW"
+ >
+ <field-descriptor
+ name="id"
+ column="ID_"
+ jdbc-type="INTEGER"
+ primarykey="true"
+ autoincrement="true"
+ />
+
+ <field-descriptor
+ name="vote"
+ column="VOTE_"
+ jdbc-type="INTEGER"
+ />
+
+ <field-descriptor
+ name="summary"
+ column="SUMMARY_"
+ jdbc-type="VARCHAR"
+ />
+
+ <field-descriptor
+ name="version"
+ column="VERSION_"
+ jdbc-type="INTEGER"
+ locking="true"
+ />
+
+ <field-descriptor
+ name="fkAuthor"
+ column="FK_AUTHOR"
+ jdbc-type="INTEGER"
+ access="anonymous"
+ />
+
+ <field-descriptor
+ name="fkBook"
+ column="FK_BOOK"
+ jdbc-type="INTEGER"
+ />
+
+ <reference-descriptor name="author"
+ class-ref="org.apache.ojb.broker.PaginationTest$Author"
+ proxy="true"
+ auto-retrieve="true"
+ auto-update="object"
+ auto-delete="object"
+ >
+ <foreignkey field-ref="fkAuthor"/>
+ </reference-descriptor>
+
+ <reference-descriptor name="book"
+ class-ref="org.apache.ojb.broker.PaginationTest$Book"
+ proxy="true"
+ auto-retrieve="true"
+ auto-update="object"
+ auto-delete="object"
+ >
+ <foreignkey field-ref="fkBook"/>
+ </reference-descriptor>
+
+</class-descriptor>
\ No newline at end of file