0001: package org.apache.ojb.odmg;
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.util.ArrayList;
0019: import java.util.Collection;
0020: import java.util.Iterator;
0021: import java.util.List;
0022:
0023: import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
0024: import org.apache.ojb.broker.metadata.ClassDescriptor;
0025: import org.apache.ojb.junit.ODMGTestCase;
0026: import org.odmg.OQLQuery;
0027: import org.odmg.Transaction;
0028:
0029: /**
0030: * Testing complex object graphs with circular and bidirectional references when
0031: * using database foreign key settings (without support of deferred foreign keys).
0032: * <p/>
0033: * The classes hierarchy looks like:
0034: * <br/>
0035: * Class Shop has a bidirectional 1:1 reference with ShopDetail.<br/>
0036: * Shop has a 1:n relation with Product, Product has a 1:1 reference to Shop.<br/>
0037: * Shop has a m:n relation with Distributor.<br/>
0038: * Product has a 1:n relation to itself to handle sub-Products.<br/>
0039: * <p/>
0040: * In the database the following foreign keys are declared:
0041: * <br/>
0042: * - Shop has a FK to ShopDetail<br/>
0043: * - Product has a FK to Product<br/>
0044: * - Product has a FK to Shop<br/>
0045: * - CT_SHOP_DISTRIBUTOR indirection table has FK's to Shop and Distributor<br/>
0046: * <p/>
0047: * Here a summery of the dependencies:<br/>
0048: * Shop--1:1-->ShopDetail--1:1-->Shop<br/>
0049: * Shop--1:n-->Product--1:1-->Shop<br/>
0050: * Product--1:n-->Product<br/>
0051: * Shop--m:n-->Distributor<br/>
0052: * <p/>
0053: * <p/>
0054: * Class ObjectA has a 1:1 reference to ObjectAA,<br/>
0055: * ObjectAA has 1:1 to ObjectAAA,<br/>
0056: * ObjectAAA has 1:1 to ObjectA and to ObjectAAAA,<br/>
0057: * ObjectAAAA has 1:1 to ObjectA<br/>
0058: * <br/>
0059: * - ObjectA has FK to ObjectAA<br/>
0060: * - ObjectAA has FK to ObjectAAA<br/>
0061: * - ObjectAAA has FK to ObjectAAAA<br/>
0062: * <p/>
0063: * Here a summery of the dependencies:<br/>
0064: * ObjetA--1:1-->ObjectAA--1:1-->ObjectAAA--1:1-->ObjectA
0065: * ObjetA--1:1-->ObjectAA--1:1-->ObjectAAA--1:1-->ObjectAAAA--1:1-->ObjectA
0066: *
0067: * @version $Id: CircularTest.java,v 1.1.2.10 2005/12/21 22:31:28 tomdz Exp $
0068: */
0069: public class CircularTest extends ODMGTestCase {
0070: public static void main(String[] args) {
0071: String[] arr = { CircularTest.class.getName() };
0072: junit.textui.TestRunner.main(arr);
0073: }
0074:
0075: /**
0076: * Handling circular 1:n references with FK settings and use of
0077: * auto-delete setting to delete object graph.
0078: */
0079: public void testCircularOneToN_1() throws Exception {
0080: String name = "testCircularOneToN_1_"
0081: + System.currentTimeMillis();
0082: ojbChangeReferenceSetting(Product.class, "subProducts", true,
0083: ObjectReferenceDescriptor.CASCADE_NONE,
0084: ObjectReferenceDescriptor.CASCADE_OBJECT, false);
0085:
0086: Product p1 = new Product(name + "_p1");
0087: Product p2 = new Product(name + "_p2");
0088: Product p3 = new Product(name + "_p3");
0089:
0090: TransactionExt tx = (TransactionExt) odmg.newTransaction();
0091: tx.begin();
0092: p1.addSubProduct(p2);
0093: p2.addSubProduct(p3);
0094: database.makePersistent(p3);
0095: // before establishing the circular references write
0096: // all objects to DB
0097: tx.flush();
0098: // now close the circular references
0099: p3.addSubProduct(p1);
0100: tx.commit();
0101:
0102: tx.begin();
0103: // on delete break the circular references first, then delete the
0104: // start object
0105: tx.lock(p3, Transaction.WRITE);
0106: // this call is only needed if auto-delete setting in repository is 'object'
0107: tx.setCascadingDelete(Product.class, "subProducts", false);
0108: p3.setSubProducts(null);
0109: tx.flush();
0110: database.deletePersistent(p3);
0111: database.deletePersistent(p2);
0112: database.deletePersistent(p1);
0113: tx.commit();
0114:
0115: tx.begin();
0116: OQLQuery query = odmg.newOQLQuery();
0117: query.create("select objects from " + Product.class.getName()
0118: + " where name like $1");
0119: query.bind(name + "%");
0120: Collection result = (Collection) query.execute();
0121: tx.commit();
0122:
0123: assertEquals(0, result.size());
0124: }
0125:
0126: /**
0127: * Handling circular 1:n references with FK settings and use of
0128: * auto-delete setting to delete object graph.
0129: */
0130: public void testCircularOneToN_2() throws Exception {
0131: String name = "testCircularOneToN_2_"
0132: + System.currentTimeMillis();
0133: ojbChangeReferenceSetting(Product.class, "subProducts", true,
0134: ObjectReferenceDescriptor.CASCADE_NONE,
0135: ObjectReferenceDescriptor.CASCADE_OBJECT, false);
0136:
0137: Product p1 = new Product(name + "_p1");
0138: Product p2 = new Product(name + "_p2");
0139: Product p3 = new Product(name + "_p3");
0140: Product p4 = new Product(name + "_p4");
0141: Product p5 = new Product(name + "_p5");
0142: Product p6 = new Product(name + "_p6");
0143: Product p7 = new Product(name + "_p7");
0144:
0145: TransactionExt tx = (TransactionExt) odmg.newTransaction();
0146: tx.begin();
0147: p1.addSubProduct(p2);
0148: p1.addSubProduct(p3);
0149: p3.addSubProduct(p4);
0150: p3.addSubProduct(p5);
0151: p5.addSubProduct(p6);
0152: p6.addSubProduct(p7);
0153: database.makePersistent(p1);
0154: // before establishing the circular references write
0155: // all objects to DB
0156: tx.flush();
0157: // now close the circular references
0158: p6.addSubProduct(p1);
0159: tx.commit();
0160:
0161: tx.begin();
0162: // on delete break the circular references first, then delete the
0163: // start object
0164: tx.lock(p6, Transaction.WRITE);
0165: tx.setCascadingDelete(Product.class, "subProducts", false);
0166: p6.setSubProducts(null);
0167: tx.flush();
0168: tx.setCascadingDelete(Product.class, "subProducts", true);
0169: database.deletePersistent(p1);
0170: tx.commit();
0171:
0172: tx.begin();
0173: OQLQuery query = odmg.newOQLQuery();
0174: query.create("select objects from " + Product.class.getName()
0175: + " where name like $1");
0176: query.bind(name + "%");
0177: Collection result = (Collection) query.execute();
0178: tx.commit();
0179:
0180: // we expect one Product object, because we set cascading delete 'false'
0181: // when do 'p6.setSubProducts(null);', so the '..._p7' Product will only be unlinked
0182: assertEquals(1, result.size());
0183: Product p7_new = (Product) result.iterator().next();
0184: assertEquals(name + "_p7", p7_new.getName());
0185: }
0186:
0187: /**
0188: * Handling circular 1:n references with FK settings and use of
0189: * auto-delete setting to delete object graph.
0190: */
0191: public void testCircularOneToN_3() throws Exception {
0192: String name = "testCircularOneToN_3_"
0193: + System.currentTimeMillis();
0194: ojbChangeReferenceSetting(Product.class, "subProducts", true,
0195: ObjectReferenceDescriptor.CASCADE_NONE,
0196: ObjectReferenceDescriptor.CASCADE_OBJECT, false);
0197:
0198: Product p1 = new Product(name + "_p1");
0199: Product p2 = new Product(name + "_p2");
0200: Product p3 = new Product(name + "_p3");
0201:
0202: TransactionExt tx = (TransactionExt) odmg.newTransaction();
0203: tx.begin();
0204: p1.addSubProduct(p2);
0205: p2.addSubProduct(p3);
0206: database.makePersistent(p3);
0207: // before establishing the circular references write
0208: // all objects to DB
0209: tx.flush();
0210: // now close the circular references
0211: p3.addSubProduct(p1);
0212: tx.commit();
0213:
0214: tx.begin();
0215: // on delete break the circular references first, then delete the
0216: // start object
0217: tx.lock(p3, Transaction.WRITE);
0218: // this call is only needed if auto-delete setting in repository is 'object'
0219: tx.setCascadingDelete(Product.class, "subProducts", false);
0220: p3.setSubProducts(null);
0221: tx.flush();
0222: // this call is only needed if auto-delete setting in repository is 'none'
0223: // to enable cascade delete, else we have to delete each object by hand
0224: tx.setCascadingDelete(Product.class, "subProducts", true);
0225: database.deletePersistent(p1);
0226: tx.commit();
0227:
0228: tx.begin();
0229: OQLQuery query = odmg.newOQLQuery();
0230: query.create("select objects from " + Product.class.getName()
0231: + " where name like $1");
0232: query.bind(name + "%");
0233: Collection result = (Collection) query.execute();
0234: tx.commit();
0235:
0236: assertEquals(0, result.size());
0237: }
0238:
0239: /**
0240: * Use auto-delete setting to delete object graph.
0241: */
0242: public void testCircularWithAutoDeleteEnabled() throws Exception {
0243: String name = "testCircularWithAutoDeleteEnabled_"
0244: + System.currentTimeMillis();
0245:
0246: ojbChangeReferenceSetting(ObjectA.class, "refAA", true,
0247: ObjectReferenceDescriptor.CASCADE_NONE,
0248: ObjectReferenceDescriptor.CASCADE_OBJECT, false);
0249: ojbChangeReferenceSetting(ObjectAA.class, "refAAA", true,
0250: ObjectReferenceDescriptor.CASCADE_NONE,
0251: ObjectReferenceDescriptor.CASCADE_OBJECT, false);
0252: ojbChangeReferenceSetting(ObjectAAA.class, "refAAAA", true,
0253: ObjectReferenceDescriptor.CASCADE_NONE,
0254: ObjectReferenceDescriptor.CASCADE_OBJECT, false);
0255: ojbChangeReferenceSetting(ObjectAAAA.class, "refA", true,
0256: ObjectReferenceDescriptor.CASCADE_NONE,
0257: ObjectReferenceDescriptor.CASCADE_OBJECT, false);
0258:
0259: ObjectA a = new ObjectA(name + "_ObjectA");
0260: ObjectAA aa = new ObjectAA(name + "_ObjectAA");
0261: ObjectAAA aaa = new ObjectAAA(name + "_ObjectAAA");
0262: ObjectAAAA aaaa = new ObjectAAAA(name + "_ObjectAAAA");
0263: // now set the circular references
0264: a.setRefAA(aa);
0265: aa.setRefAAA(aaa);
0266: aaa.setRefAAAA(aaaa);
0267: aaaa.setRefA(a);
0268:
0269: TransactionExt tx = (TransactionExt) odmg.newTransaction();
0270: tx.begin();
0271: database.makePersistent(a);
0272: tx.commit();
0273:
0274: tx.begin();
0275: OQLQuery query = odmg.newOQLQuery();
0276: query.create("select objects from " + ObjectA.class.getName()
0277: + " where name like $1");
0278: query.bind(name + "%");
0279: Collection result = (Collection) query.execute();
0280: assertEquals(1, result.size());
0281:
0282: query = odmg.newOQLQuery();
0283: query.create("select objects from " + ObjectAA.class.getName()
0284: + " where name like $1");
0285: query.bind(name + "%");
0286: result = (Collection) query.execute();
0287: assertEquals(1, result.size());
0288:
0289: query = odmg.newOQLQuery();
0290: query.create("select objects from " + ObjectAAA.class.getName()
0291: + " where name like $1");
0292: query.bind(name + "%");
0293: result = (Collection) query.execute();
0294: assertEquals(1, result.size());
0295:
0296: query = odmg.newOQLQuery();
0297: query.create("select objects from "
0298: + ObjectAAAA.class.getName() + " where name like $1");
0299: query.bind(name + "%");
0300: result = (Collection) query.execute();
0301: assertEquals(1, result.size());
0302: tx.commit();
0303:
0304: tx.begin();
0305: /*
0306: arminw: When deleting a object which is part of circular 1:1 references
0307: with cascade delete enabled it's mandatory to break the circular reference
0308: before deleting it.
0309: */
0310: tx.lock(aaaa, Transaction.WRITE);
0311: // break the circular references
0312: aaaa.setRefA(null);
0313: database.deletePersistent(a);
0314: tx.commit();
0315:
0316: tx.begin();
0317: query = odmg.newOQLQuery();
0318: query.create("select objects from " + ObjectA.class.getName()
0319: + " where name like $1");
0320: query.bind(name + "%");
0321: result = (Collection) query.execute();
0322: assertEquals(0, result.size());
0323:
0324: query = odmg.newOQLQuery();
0325: query.create("select objects from " + ObjectAA.class.getName()
0326: + " where name like $1");
0327: query.bind(name + "%");
0328: result = (Collection) query.execute();
0329: assertEquals(0, result.size());
0330:
0331: query = odmg.newOQLQuery();
0332: query.create("select objects from " + ObjectAAA.class.getName()
0333: + " where name like $1");
0334: query.bind(name + "%");
0335: result = (Collection) query.execute();
0336: assertEquals(0, result.size());
0337:
0338: query = odmg.newOQLQuery();
0339: query.create("select objects from "
0340: + ObjectAAAA.class.getName() + " where name like $1");
0341: query.bind(name + "%");
0342: result = (Collection) query.execute();
0343: assertEquals(0, result.size());
0344: tx.commit();
0345: }
0346:
0347: /**
0348: * Use auto-delete setting to delete object graph.
0349: */
0350: public void testAutoDeleteEnabledNonCircular() throws Exception {
0351: String name = "testAutoDeleteEnabledNonCircular_"
0352: + System.currentTimeMillis();
0353:
0354: ojbChangeReferenceSetting(ObjectA.class, "refAA", true,
0355: ObjectReferenceDescriptor.CASCADE_NONE,
0356: ObjectReferenceDescriptor.CASCADE_OBJECT, false);
0357: ojbChangeReferenceSetting(ObjectAA.class, "refAAA", true,
0358: ObjectReferenceDescriptor.CASCADE_NONE,
0359: ObjectReferenceDescriptor.CASCADE_OBJECT, false);
0360: ojbChangeReferenceSetting(ObjectAAA.class, "refAAAA", true,
0361: ObjectReferenceDescriptor.CASCADE_NONE,
0362: ObjectReferenceDescriptor.CASCADE_OBJECT, false);
0363: ojbChangeReferenceSetting(ObjectAAAA.class, "refA", true,
0364: ObjectReferenceDescriptor.CASCADE_NONE,
0365: ObjectReferenceDescriptor.CASCADE_OBJECT, false);
0366:
0367: ObjectA a = new ObjectA(name + "_ObjectA");
0368: ObjectAA aa = new ObjectAA(name + "_ObjectAA");
0369: ObjectAAA aaa = new ObjectAAA(name + "_ObjectAAA");
0370: ObjectAAAA aaaa = new ObjectAAAA(name + "_ObjectAAAA");
0371: // now set the references
0372: a.setRefAA(aa);
0373: aa.setRefAAA(aaa);
0374: aaa.setRefAAAA(aaaa);
0375:
0376: TransactionExt tx = (TransactionExt) odmg.newTransaction();
0377: tx.begin();
0378: database.makePersistent(a);
0379: tx.commit();
0380:
0381: tx.begin();
0382: OQLQuery query = odmg.newOQLQuery();
0383: query.create("select objects from " + ObjectA.class.getName()
0384: + " where name like $1");
0385: query.bind(name + "%");
0386: Collection result = (Collection) query.execute();
0387: assertEquals(1, result.size());
0388:
0389: query = odmg.newOQLQuery();
0390: query.create("select objects from " + ObjectAA.class.getName()
0391: + " where name like $1");
0392: query.bind(name + "%");
0393: result = (Collection) query.execute();
0394: assertEquals(1, result.size());
0395:
0396: query = odmg.newOQLQuery();
0397: query.create("select objects from " + ObjectAAA.class.getName()
0398: + " where name like $1");
0399: query.bind(name + "%");
0400: result = (Collection) query.execute();
0401: assertEquals(1, result.size());
0402:
0403: query = odmg.newOQLQuery();
0404: query.create("select objects from "
0405: + ObjectAAAA.class.getName() + " where name like $1");
0406: query.bind(name + "%");
0407: result = (Collection) query.execute();
0408: assertEquals(1, result.size());
0409: tx.commit();
0410:
0411: tx.begin();
0412: database.deletePersistent(a);
0413: tx.commit();
0414:
0415: tx.begin();
0416: query = odmg.newOQLQuery();
0417: query.create("select objects from " + ObjectA.class.getName()
0418: + " where name like $1");
0419: query.bind(name + "%");
0420: result = (Collection) query.execute();
0421: assertEquals(0, result.size());
0422:
0423: query = odmg.newOQLQuery();
0424: query.create("select objects from " + ObjectAA.class.getName()
0425: + " where name like $1");
0426: query.bind(name + "%");
0427: result = (Collection) query.execute();
0428: assertEquals(0, result.size());
0429:
0430: query = odmg.newOQLQuery();
0431: query.create("select objects from " + ObjectAAA.class.getName()
0432: + " where name like $1");
0433: query.bind(name + "%");
0434: result = (Collection) query.execute();
0435: assertEquals(0, result.size());
0436:
0437: query = odmg.newOQLQuery();
0438: query.create("select objects from "
0439: + ObjectAAAA.class.getName() + " where name like $1");
0440: query.bind(name + "%");
0441: result = (Collection) query.execute();
0442: assertEquals(0, result.size());
0443: tx.commit();
0444: }
0445:
0446: /**
0447: * Handle circuler 1:1 with default methods.
0448: */
0449: public void testBidirectionalWithConstraint_1a() throws Exception {
0450: String name = "testBidirectionalWithConstraint_1a_"
0451: + System.currentTimeMillis();
0452:
0453: Shop s1 = new Shop(name + "_1");
0454: ShopDetail sd = new ShopDetail(name + "_1");
0455: s1.setDetail(sd);
0456: sd.setShop(s1);
0457:
0458: TransactionExt tx = (TransactionExt) odmg.newTransaction();
0459: tx.begin();
0460: database.makePersistent(s1);
0461: tx.commit();
0462:
0463: tx.begin();
0464: database.deletePersistent(s1);
0465: tx.commit();
0466: }
0467:
0468: /**
0469: * Define order of object operations using flush() method.
0470: */
0471: public void testBidirectionalWithConstraint_1b() throws Exception {
0472: String name = "testBidirectionalWithConstraint_1b_"
0473: + System.currentTimeMillis();
0474: TransactionExt tx = (TransactionExt) odmg.newTransaction();
0475: tx.begin();
0476:
0477: Shop s1 = new Shop(name + "_1");
0478: // when using flush() we can use the "natural" order
0479: // without getting DB constraint violence.
0480: database.makePersistent(s1);
0481: // write to DB object without references
0482: tx.flush();
0483: ShopDetail sd = new ShopDetail(name + "_1");
0484: // now set references
0485: s1.setDetail(sd);
0486: sd.setShop(s1);
0487: // no need to persist the ShopDetail object
0488: // (will be detected by OJB)
0489: // but it doesn't matter if you do
0490: // database.makePersistent(sd);
0491: tx.commit();
0492:
0493: tx.begin();
0494: // madatory to mark object with DB FK constraint first on delete
0495: // (FK from Shop to ShopDetail) then OJB will use this order to
0496: // delete the bidirectional objects
0497: database.deletePersistent(s1);
0498: tx.flush();
0499: database.deletePersistent(sd);
0500: tx.commit();
0501: }
0502:
0503: /**
0504: * If the user take care of the ordering itself the test pass.
0505: */
0506: public void testBidirectionalWithConstraint_1c() throws Exception {
0507: String name = "testBidirectionalWithConstraint_1c_"
0508: + System.currentTimeMillis();
0509: TransactionExt tx = (TransactionExt) odmg.newTransaction();
0510:
0511: Shop s1 = new Shop(name + "_1");
0512: ShopDetail sd = new ShopDetail(name + "_1");
0513: s1.setDetail(sd);
0514: sd.setShop(s1);
0515:
0516: // set implicit locking false to determine order of objects
0517: tx.setImplicitLocking(false);
0518: // to prevent reordering of object, disable ordering
0519: // in many cases this is not needed, because OJB will leave ordering
0520: // tx.setOrdering(false);
0521: tx.begin();
0522: // madatory to persist referenced ShopDetail first, the Shop
0523: // object will be detected automatic. In this case first the ShopDetail
0524: // will be created and then the Shop
0525: database.makePersistent(sd);
0526: database.makePersistent(s1);
0527: tx.commit();
0528:
0529: // we using the same tx, thus locking and (ordering) is still disabled
0530: tx.begin();
0531: // madatory to mark object with DB FK constraint first on delete
0532: // then OJB will use this order to delete the bidirectional objects
0533: database.deletePersistent(s1);
0534: database.deletePersistent(sd);
0535: tx.commit();
0536: }
0537:
0538: /**
0539: * This test is only for comparison of ODMG- with PB-api. It's not recommended
0540: * to do this in ODMG production environment.
0541: *
0542: * @throws Exception
0543: */
0544: public void testBidirectionalWithConstraint_1d_PB()
0545: throws Exception {
0546: ojbChangeReferenceSetting(Shop.class, "detail", true,
0547: ObjectReferenceDescriptor.CASCADE_OBJECT,
0548: ObjectReferenceDescriptor.CASCADE_OBJECT, false);
0549: ojbChangeReferenceSetting(ShopDetail.class, "shop", true,
0550: ObjectReferenceDescriptor.CASCADE_OBJECT,
0551: ObjectReferenceDescriptor.CASCADE_OBJECT, false);
0552: String name = "testBidirectionalWithConstraint_1a_"
0553: + System.currentTimeMillis();
0554: TransactionExt tx = (TransactionExt) odmg.newTransaction();
0555: tx.begin();
0556:
0557: Shop s1 = new Shop(name + "_1");
0558: ShopDetail sd = new ShopDetail(name + "_1");
0559: s1.setDetail(sd);
0560: sd.setShop(s1);
0561:
0562: // only for testing, we completely bypass odmg
0563: tx.getBroker().beginTransaction();
0564: tx.getBroker().store(s1);
0565: tx.commit();
0566:
0567: tx.begin();
0568: // only for testing, we completely bypass odmg
0569: tx.getBroker().beginTransaction();
0570: // madatory to mark object with DB FK constraint first on delete
0571: // then OJB will use this order to delete the bidirectional objects
0572: tx.getBroker().delete(s1);
0573: tx.commit();
0574: }
0575:
0576: /**
0577: * Handle circular 1:1 by using a 'constraint'-flag property in
0578: * reference-descriptor to make OJB's ordering algorithm more
0579: * sophisticated.
0580: */
0581: public void testBidirectionalWithConstraint_1e() throws Exception {
0582: String name = "testBidirectionalWithConstraint_1e_"
0583: + System.currentTimeMillis();
0584: ObjectReferenceDescriptor ord = null;
0585:
0586: try {
0587: CircularTest.Shop s1 = new CircularTest.Shop(name + "_1");
0588: CircularTest.ShopDetail sd = new CircularTest.ShopDetail(
0589: name + "_1");
0590: s1.setDetail(sd);
0591: sd.setShop(s1);
0592:
0593: TransactionExt tx = (TransactionExt) odmg.newTransaction();
0594: tx.begin();
0595: // now we tell OJB that one 1:1 reference of the bidirectional 1:1 reference
0596: // between Shop and ShopDetail has a FK constraint
0597: ClassDescriptor cld = tx.getBroker().getClassDescriptor(
0598: CircularTest.Shop.class);
0599: ord = cld.getObjectReferenceDescriptorByName("detail");
0600: // current DB schema create a foreign key constraint and we can
0601: // inform OJB
0602: ord.setConstraint(true);
0603: // now it doesn't matter in which order we persist the new objects, OJB should
0604: // always reorder the objects before insert/update call
0605: database.makePersistent(sd);
0606: // or
0607: // database.makePersistent(s1);
0608: tx.commit();
0609:
0610: tx.begin();
0611: // with cascading delete and the declared FK constraint OJB
0612: // always use the correct order on delete.
0613: tx.setCascadingDelete(CircularTest.ShopDetail.class, true);
0614: database.deletePersistent(sd);
0615: // or
0616: // database.deletePersistent(s1);
0617: tx.commit();
0618: } finally {
0619: // restore old setting
0620: if (ord != null)
0621: ord.setConstraint(false);
0622: }
0623: }
0624:
0625: /**
0626: * Test show handling with circular references and database FK settings.
0627: */
0628: public void testCircularOneToOne_1a() throws Exception {
0629: String name = "testCircularOneToOne_1a_"
0630: + System.currentTimeMillis();
0631:
0632: TransactionExt tx = (TransactionExt) odmg.newTransaction();
0633: tx.begin();
0634:
0635: ObjectA a = new ObjectA(name + "_ObjectA");
0636: ObjectAA aa = new ObjectAA(name + "_ObjectAA");
0637: ObjectAAA aaa = new ObjectAAA(name + "_ObjectAAA");
0638: // now set the circular references
0639: a.setRefAA(aa);
0640: aa.setRefAAA(aaa);
0641: aaa.setRefA(a);
0642: database.makePersistent(a);
0643: tx.commit();
0644:
0645: tx.begin();
0646: database.deletePersistent(a);
0647: tx.commit();
0648:
0649: tx.begin();
0650: OQLQuery query = odmg.newOQLQuery();
0651: query.create("select objects from " + ObjectA.class.getName()
0652: + " where name like $1");
0653: query.bind(name + "%");
0654: Collection result = (Collection) query.execute();
0655: assertEquals(0, result.size());
0656:
0657: query = odmg.newOQLQuery();
0658: query.create("select objects from " + ObjectAA.class.getName()
0659: + " where name like $1");
0660: query.bind(name + "%");
0661: result = (Collection) query.execute();
0662: assertEquals(1, result.size());
0663:
0664: query = odmg.newOQLQuery();
0665: query.create("select objects from " + ObjectAAA.class.getName()
0666: + " where name like $1");
0667: query.bind(name + "%");
0668: result = (Collection) query.execute();
0669: assertEquals(1, result.size());
0670:
0671: query = odmg.newOQLQuery();
0672: query.create("select objects from "
0673: + ObjectAAAA.class.getName() + " where name like $1");
0674: query.bind(name + "%");
0675: result = (Collection) query.execute();
0676: assertEquals(0, result.size());
0677: tx.commit();
0678: }
0679:
0680: /**
0681: * Test show handling with circular references and database FK settings.
0682: */
0683: public void testCircularOneToOne_1b() throws Exception {
0684: String name = "testCircularOneToOne_1b_"
0685: + System.currentTimeMillis();
0686:
0687: TransactionExt tx = (TransactionExt) odmg.newTransaction();
0688: tx.begin();
0689:
0690: ObjectA a = new ObjectA(name + "_ObjectA");
0691: ObjectAA aa = new ObjectAA(name + "_ObjectAA");
0692: ObjectAAA aaa = new ObjectAAA(name + "_ObjectAAA");
0693: ObjectAAAA aaaa = new ObjectAAAA(name + "_ObjectAAAA");
0694: // now set the circular references
0695: a.setRefAA(aa);
0696: aa.setRefAAA(aaa);
0697: aaa.setRefAAAA(aaaa);
0698: aaaa.setRefA(a);
0699: database.makePersistent(a);
0700: tx.commit();
0701:
0702: tx.begin();
0703: OQLQuery query = odmg.newOQLQuery();
0704: query.create("select objects from " + ObjectA.class.getName()
0705: + " where name like $1");
0706: query.bind(name + "%");
0707: Collection result = (Collection) query.execute();
0708: assertEquals(1, result.size());
0709:
0710: query = odmg.newOQLQuery();
0711: query.create("select objects from " + ObjectAA.class.getName()
0712: + " where name like $1");
0713: query.bind(name + "%");
0714: result = (Collection) query.execute();
0715: assertEquals(1, result.size());
0716:
0717: query = odmg.newOQLQuery();
0718: query.create("select objects from " + ObjectAAA.class.getName()
0719: + " where name like $1");
0720: query.bind(name + "%");
0721: result = (Collection) query.execute();
0722: assertEquals(1, result.size());
0723:
0724: query = odmg.newOQLQuery();
0725: query.create("select objects from "
0726: + ObjectAAAA.class.getName() + " where name like $1");
0727: query.bind(name + "%");
0728: result = (Collection) query.execute();
0729: assertEquals(1, result.size());
0730: tx.commit();
0731:
0732: tx.begin();
0733: database.deletePersistent(a);
0734: tx.commit();
0735:
0736: tx.begin();
0737: query = odmg.newOQLQuery();
0738: query.create("select objects from " + ObjectA.class.getName()
0739: + " where name like $1");
0740: query.bind(name + "%");
0741: result = (Collection) query.execute();
0742: assertEquals(0, result.size());
0743:
0744: query = odmg.newOQLQuery();
0745: query.create("select objects from " + ObjectAA.class.getName()
0746: + " where name like $1");
0747: query.bind(name + "%");
0748: result = (Collection) query.execute();
0749: assertEquals(1, result.size());
0750:
0751: query = odmg.newOQLQuery();
0752: query.create("select objects from " + ObjectAAA.class.getName()
0753: + " where name like $1");
0754: query.bind(name + "%");
0755: result = (Collection) query.execute();
0756: assertEquals(1, result.size());
0757:
0758: query = odmg.newOQLQuery();
0759: query.create("select objects from "
0760: + ObjectAAAA.class.getName() + " where name like $1");
0761: query.bind(name + "%");
0762: result = (Collection) query.execute();
0763: assertEquals(1, result.size());
0764: tx.commit();
0765: }
0766:
0767: /**
0768: * Do manually ordering using {@link TransactionExt#setOrdering(boolean)} to disable
0769: * OJB's ordering algorithm (and implicit locking).
0770: */
0771: public void testCircularOneToOne_1c() throws Exception {
0772: String name = "testCircularOneToOne_1d_"
0773: + System.currentTimeMillis();
0774:
0775: TransactionExt tx = (TransactionExt) odmg.newTransaction();
0776: tx.begin();
0777:
0778: ObjectA a = new ObjectA(name + "_ObjectA");
0779: ObjectAA aa = new ObjectAA(name + "_ObjectAA");
0780: ObjectAAA aaa = new ObjectAAA(name + "_ObjectAAA");
0781: ObjectAAAA aaaa = new ObjectAAAA(name + "_ObjectAAAA");
0782: // now set the circular references
0783: a.setRefAA(aa);
0784: aa.setRefAAA(aaa);
0785: aaa.setRefAAAA(aaaa);
0786: aaaa.setRefA(a);
0787:
0788: /*
0789: we want to manually insert new object, so we disable
0790: OJB's ordering and implicit object locking
0791: */
0792: tx.setOrdering(false);
0793: tx.setImplicitLocking(false);
0794:
0795: database.makePersistent(aaaa);
0796: database.makePersistent(aaa);
0797: database.makePersistent(aa);
0798: database.makePersistent(a);
0799: tx.commit();
0800:
0801: tx.begin();
0802: OQLQuery query = odmg.newOQLQuery();
0803: query.create("select objects from " + ObjectA.class.getName()
0804: + " where name like $1");
0805: query.bind(name + "%");
0806: Collection result = (Collection) query.execute();
0807: assertEquals(1, result.size());
0808:
0809: query = odmg.newOQLQuery();
0810: query.create("select objects from " + ObjectAA.class.getName()
0811: + " where name like $1");
0812: query.bind(name + "%");
0813: result = (Collection) query.execute();
0814: assertEquals(1, result.size());
0815:
0816: query = odmg.newOQLQuery();
0817: query.create("select objects from " + ObjectAAA.class.getName()
0818: + " where name like $1");
0819: query.bind(name + "%");
0820: result = (Collection) query.execute();
0821: assertEquals(1, result.size());
0822:
0823: query = odmg.newOQLQuery();
0824: query.create("select objects from "
0825: + ObjectAAAA.class.getName() + " where name like $1");
0826: query.bind(name + "%");
0827: result = (Collection) query.execute();
0828: assertEquals(1, result.size());
0829: tx.commit();
0830:
0831: tx.begin();
0832: /*
0833: the ordering/implicit locking of the tx is still disabled (tx instance hasn't changed),
0834: so we have to take care of correct order of objects while deletion
0835: */
0836: database.deletePersistent(a);
0837: database.deletePersistent(aa);
0838: database.deletePersistent(aaa);
0839: database.deletePersistent(aaaa);
0840: tx.commit();
0841:
0842: tx.begin();
0843: query = odmg.newOQLQuery();
0844: query.create("select objects from " + ObjectA.class.getName()
0845: + " where name like $1");
0846: query.bind(name + "%");
0847: result = (Collection) query.execute();
0848: assertEquals(0, result.size());
0849:
0850: query = odmg.newOQLQuery();
0851: query.create("select objects from " + ObjectAA.class.getName()
0852: + " where name like $1");
0853: query.bind(name + "%");
0854: result = (Collection) query.execute();
0855: assertEquals(0, result.size());
0856:
0857: query = odmg.newOQLQuery();
0858: query.create("select objects from " + ObjectAAA.class.getName()
0859: + " where name like $1");
0860: query.bind(name + "%");
0861: result = (Collection) query.execute();
0862: assertEquals(0, result.size());
0863:
0864: query = odmg.newOQLQuery();
0865: query.create("select objects from "
0866: + ObjectAAAA.class.getName() + " where name like $1");
0867: query.bind(name + "%");
0868: result = (Collection) query.execute();
0869: assertEquals(0, result.size());
0870: tx.commit();
0871: }
0872:
0873: /**
0874: * Do manually ordering using in conjunction with OJB's ordering.
0875: */
0876: public void testCircularOneToOne_1dd() throws Exception {
0877: String name = "testCircularOneToOne_1dd_"
0878: + System.currentTimeMillis();
0879:
0880: TransactionExt tx = (TransactionExt) odmg.newTransaction();
0881: tx.begin();
0882:
0883: ObjectA a = new ObjectA(name + "_ObjectA");
0884: ObjectAA aa = new ObjectAA(name + "_ObjectAA");
0885: ObjectAAA aaa = new ObjectAAA(name + "_ObjectAAA");
0886: ObjectAAAA aaaa = new ObjectAAAA(name + "_ObjectAAAA");
0887: // now set the circular references
0888: a.setRefAA(aa);
0889: aa.setRefAAA(aaa);
0890: aaa.setRefAAAA(aaaa);
0891: aaaa.setRefA(a);
0892:
0893: /*
0894: we manually determine the insert object order
0895: */
0896: tx.setOrdering(false);
0897: tx.setImplicitLocking(false);
0898:
0899: database.makePersistent(aaaa);
0900: database.makePersistent(aaa);
0901: database.makePersistent(aa);
0902: database.makePersistent(a);
0903: tx.commit();
0904:
0905: tx.begin();
0906: /*
0907: the ordering/implicit locking/noteOrdering settings are still enabled
0908: */
0909: database.deletePersistent(a);
0910: database.deletePersistent(aa);
0911: database.deletePersistent(aaa);
0912: database.deletePersistent(aaaa);
0913: tx.commit();
0914:
0915: tx.begin();
0916: OQLQuery query = odmg.newOQLQuery();
0917: query.create("select objects from " + ObjectA.class.getName()
0918: + " where name like $1");
0919: query.bind(name + "%");
0920: Collection result = (Collection) query.execute();
0921: assertEquals(0, result.size());
0922:
0923: query = odmg.newOQLQuery();
0924: query.create("select objects from " + ObjectAA.class.getName()
0925: + " where name like $1");
0926: query.bind(name + "%");
0927: result = (Collection) query.execute();
0928: assertEquals(0, result.size());
0929:
0930: query = odmg.newOQLQuery();
0931: query.create("select objects from " + ObjectAAA.class.getName()
0932: + " where name like $1");
0933: query.bind(name + "%");
0934: result = (Collection) query.execute();
0935: assertEquals(0, result.size());
0936:
0937: query = odmg.newOQLQuery();
0938: query.create("select objects from "
0939: + ObjectAAAA.class.getName() + " where name like $1");
0940: query.bind(name + "%");
0941: result = (Collection) query.execute();
0942: assertEquals(0, result.size());
0943: tx.commit();
0944: }
0945:
0946: public void testCircularOneToOne_1e() throws Exception {
0947: String name = "testCircularOneToOne_1e_"
0948: + System.currentTimeMillis();
0949:
0950: TransactionExt tx = (TransactionExt) odmg.newTransaction();
0951: tx.begin();
0952:
0953: ObjectA a = new ObjectA(name + "_ObjectA");
0954: ObjectAA aa = new ObjectAA(name + "_ObjectAA");
0955: ObjectAAA aaa = new ObjectAAA(name + "_ObjectAAA");
0956: ObjectAAAA aaaa = new ObjectAAAA(name + "_ObjectAAAA");
0957: // now set the circular references
0958: a.setRefAA(aa);
0959: aa.setRefAAA(aaa);
0960: aaa.setRefAAAA(aaaa);
0961: aaaa.setRefA(a);
0962:
0963: database.makePersistent(a);
0964: tx.commit();
0965:
0966: tx.begin();
0967: // delete one object from an object graph
0968: tx.lock(aa, Transaction.WRITE);
0969: aa.setRefAAA(null);
0970: database.deletePersistent(aaa);
0971: tx.commit();
0972:
0973: tx.begin();
0974: OQLQuery query = odmg.newOQLQuery();
0975: query.create("select objects from " + ObjectA.class.getName()
0976: + " where name like $1");
0977: query.bind(name + "%");
0978: Collection result = (Collection) query.execute();
0979: assertEquals(1, result.size());
0980:
0981: query = odmg.newOQLQuery();
0982: query.create("select objects from " + ObjectAA.class.getName()
0983: + " where name like $1");
0984: query.bind(name + "%");
0985: result = (Collection) query.execute();
0986: assertEquals(1, result.size());
0987:
0988: query = odmg.newOQLQuery();
0989: query.create("select objects from " + ObjectAAA.class.getName()
0990: + " where name like $1");
0991: query.bind(name + "%");
0992: result = (Collection) query.execute();
0993: assertEquals(0, result.size());
0994:
0995: query = odmg.newOQLQuery();
0996: query.create("select objects from "
0997: + ObjectAAAA.class.getName() + " where name like $1");
0998: query.bind(name + "%");
0999: result = (Collection) query.execute();
1000: assertEquals(1, result.size());
1001: tx.commit();
1002: }
1003:
1004: /**
1005: * User take care of the ordering itself.
1006: */
1007: public void testCircularOneToOne_2a() throws Exception {
1008: String name = "testCircularOneToOne_2_"
1009: + System.currentTimeMillis();
1010:
1011: ObjectA a = new ObjectA(name + "_ObjectA");
1012: ObjectAA aa = new ObjectAA(name + "_ObjectAA");
1013: ObjectAAA aaa = new ObjectAAA(name + "_ObjectAAA");
1014: // now set the circular references
1015: a.setRefAA(aa);
1016: aa.setRefAAA(aaa);
1017: aaa.setRefA(a);
1018:
1019: TransactionExt tx = (TransactionExt) odmg.newTransaction();
1020: // we want control object insert order itself, thus
1021: // disable implicite locking and ordering
1022: tx.setImplicitLocking(false);
1023: tx.setOrdering(false);
1024: tx.begin();
1025: database.makePersistent(aaa);
1026: database.makePersistent(aa);
1027: database.makePersistent(a);
1028: tx.commit();
1029:
1030: // we use the same tx again, thus implicite locking
1031: // and ordering is still disabled
1032: tx.begin();
1033: database.deletePersistent(a);
1034: database.deletePersistent(aa);
1035: database.deletePersistent(aaa);
1036: tx.commit();
1037:
1038: tx.begin();
1039: OQLQuery query = odmg.newOQLQuery();
1040: query.create("select objects from " + ObjectA.class.getName()
1041: + " where name like $1");
1042: query.bind(name + "%");
1043: Collection result = (Collection) query.execute();
1044: assertEquals(0, result.size());
1045:
1046: query = odmg.newOQLQuery();
1047: query.create("select objects from " + ObjectAA.class.getName()
1048: + " where name like $1");
1049: query.bind(name + "%");
1050: result = (Collection) query.execute();
1051: assertEquals(0, result.size());
1052:
1053: query = odmg.newOQLQuery();
1054: query.create("select objects from " + ObjectAAA.class.getName()
1055: + " where name like $1");
1056: query.bind(name + "%");
1057: result = (Collection) query.execute();
1058: assertEquals(0, result.size());
1059:
1060: query = odmg.newOQLQuery();
1061: query.create("select objects from "
1062: + ObjectAAAA.class.getName() + " where name like $1");
1063: query.bind(name + "%");
1064: result = (Collection) query.execute();
1065: assertEquals(0, result.size());
1066: tx.commit();
1067: }
1068:
1069: /**
1070: * This test is only for comparison of ODMG- with PB-api. It's not recommended
1071: * to do this in ODMG production environment.
1072: * Handling of circular 1:1 reference: ObjetA--1:1-->ObjectAA--1:1-->ObjectAAA--1:1-->ObjectA
1073: * when each object has a FK constraint to it's reference.
1074: *
1075: * @throws Exception
1076: */
1077: public void testCircularOneToOne_PB_a() throws Exception {
1078: ojbChangeReferenceSetting(ObjectA.class, "refAA", true,
1079: ObjectReferenceDescriptor.CASCADE_OBJECT,
1080: ObjectReferenceDescriptor.CASCADE_OBJECT, false);
1081: ojbChangeReferenceSetting(ObjectAA.class, "refAAA", true,
1082: ObjectReferenceDescriptor.CASCADE_OBJECT,
1083: ObjectReferenceDescriptor.CASCADE_OBJECT, false);
1084: //ojbChangeReferenceSetting(ObjectAAA.class, "refA", true, ObjectReferenceDescriptor.CASCADE_OBJECT, ObjectReferenceDescriptor.CASCADE_OBJECT, false);
1085: String name = "testCircularOneToOne_PB"
1086: + System.currentTimeMillis();
1087: TransactionExt tx = (TransactionExt) odmg.newTransaction();
1088: tx.begin();
1089:
1090: ObjectA a = new ObjectA(name + "_ObjectA");
1091: // only for testing, we completely bypass odmg
1092: tx.getBroker().beginTransaction();
1093: //tx.getBroker().store(a);
1094:
1095: ObjectAA aa = new ObjectAA(name + "_ObjectAA");
1096: ObjectAAA aaa = new ObjectAAA(name + "_ObjectAAA");
1097: // now set the circular references
1098: a.setRefAA(aa);
1099: aa.setRefAAA(aaa);
1100: aaa.setRefA(a);
1101: tx.getBroker().store(a);
1102: tx.commit();
1103:
1104: tx.begin();
1105: OQLQuery query = odmg.newOQLQuery();
1106: query.create("select objects from " + ObjectA.class.getName()
1107: + " where name like $1");
1108: query.bind(name + "%");
1109: Collection result = (Collection) query.execute();
1110: assertEquals(1, result.size());
1111:
1112: query = odmg.newOQLQuery();
1113: query.create("select objects from " + ObjectAA.class.getName()
1114: + " where name like $1");
1115: query.bind(name + "%");
1116: result = (Collection) query.execute();
1117: assertEquals(1, result.size());
1118:
1119: query = odmg.newOQLQuery();
1120: query.create("select objects from " + ObjectAAA.class.getName()
1121: + " where name like $1");
1122: query.bind(name + "%");
1123: result = (Collection) query.execute();
1124: assertEquals(1, result.size());
1125:
1126: query = odmg.newOQLQuery();
1127: query.create("select objects from "
1128: + ObjectAAAA.class.getName() + " where name like $1");
1129: query.bind(name + "%");
1130: result = (Collection) query.execute();
1131: assertEquals(0, result.size());
1132: tx.commit();
1133:
1134: tx.begin();
1135: // only for testing, we completely bypass odmg
1136: tx.getBroker().beginTransaction();
1137: // madatory to mark object with DB FK constraint first on delete
1138: // then OJB will use this order to delete the bidirectional objects
1139: //aaa.setRefA(null);
1140: //tx.getBroker().store(aaa);
1141: tx.getBroker().delete(a);
1142: tx.commit();
1143:
1144: tx.begin();
1145: query = odmg.newOQLQuery();
1146: query.create("select objects from " + ObjectA.class.getName()
1147: + " where name like $1");
1148: query.bind(name + "%");
1149: result = (Collection) query.execute();
1150: assertEquals(0, result.size());
1151:
1152: query = odmg.newOQLQuery();
1153: query.create("select objects from " + ObjectAA.class.getName()
1154: + " where name like $1");
1155: query.bind(name + "%");
1156: result = (Collection) query.execute();
1157: assertEquals(0, result.size());
1158:
1159: query = odmg.newOQLQuery();
1160: query.create("select objects from " + ObjectAAA.class.getName()
1161: + " where name like $1");
1162: query.bind(name + "%");
1163: result = (Collection) query.execute();
1164: assertEquals(0, result.size());
1165:
1166: query = odmg.newOQLQuery();
1167: query.create("select objects from "
1168: + ObjectAAAA.class.getName() + " where name like $1");
1169: query.bind(name + "%");
1170: result = (Collection) query.execute();
1171: assertEquals(0, result.size());
1172: tx.commit();
1173: }
1174:
1175: /**
1176: * This test is only for comparison of ODMG- with PB-api. It's not recommended
1177: * to do this in ODMG production environment.
1178: * Handling of circular 1:1 reference: ObjetA--1:1-->ObjectAA--1:1-->ObjectAAA--1:1-->ObjectA
1179: * when each object has a FK constraint to it's reference.
1180: *
1181: * @throws Exception
1182: */
1183: public void testCircularOneToOne_PB_b() throws Exception {
1184: ojbChangeReferenceSetting(ObjectA.class, "refAA", true,
1185: ObjectReferenceDescriptor.CASCADE_OBJECT,
1186: ObjectReferenceDescriptor.CASCADE_OBJECT, false);
1187: ojbChangeReferenceSetting(ObjectAA.class, "refAAA", true,
1188: ObjectReferenceDescriptor.CASCADE_OBJECT,
1189: ObjectReferenceDescriptor.CASCADE_OBJECT, false);
1190: //ojbChangeReferenceSetting(ObjectAAA.class, "refA", true, ObjectReferenceDescriptor.CASCADE_OBJECT, ObjectReferenceDescriptor.CASCADE_OBJECT, false);
1191: String name = "testCircularOneToOne_PB"
1192: + System.currentTimeMillis();
1193: TransactionExt tx = (TransactionExt) odmg.newTransaction();
1194: tx.begin();
1195:
1196: // only for testing, we completely bypass odmg
1197: tx.getBroker().beginTransaction();
1198: //tx.getBroker().store(a);
1199:
1200: ObjectA a = new ObjectA(name + "_ObjectA");
1201: ObjectAA aa = new ObjectAA(name + "_ObjectAA");
1202: ObjectAAA aaa = new ObjectAAA(name + "_ObjectAAA");
1203: ObjectAAAA aaaa = new ObjectAAAA(name + "_ObjectAAAA");
1204: // now set the circular references
1205: a.setRefAA(aa);
1206: aa.setRefAAA(aaa);
1207: aaa.setRefAAAA(aaaa);
1208: aaaa.setRefA(a);
1209:
1210: tx.getBroker().store(a);
1211:
1212: tx.commit();
1213:
1214: tx.begin();
1215: // only for testing, we completely bypass odmg
1216: tx.getBroker().beginTransaction();
1217: // madatory to mark object with DB FK constraint first on delete
1218: // then OJB will use this order to delete the bidirectional objects
1219: //aaa.setRefA(null);
1220: //tx.getBroker().store(aaa);
1221: tx.getBroker().delete(a);
1222: tx.commit();
1223: }
1224:
1225: /**
1226: * Class Shop has a bidirectional 1:1 reference with ShopDetail
1227: * (FK constraint from SHOP to SHOP_DETAIL table).
1228: * Shop has a m:n relation with Distributor.
1229: */
1230: public void testBidirectionalWithConstraint_2a() throws Exception {
1231: String name = "testBidirectionalWithConstraint_2a_"
1232: + System.currentTimeMillis();
1233:
1234: Shop s1 = new Shop(name + "_1");
1235: ShopDetail sd = new ShopDetail(name + "_1");
1236: s1.setDetail(sd);
1237: sd.setShop(s1);
1238: Distributor d1 = new Distributor(name + "_1");
1239: s1.addDistributor(d1);
1240: d1.addShop(s1);
1241:
1242: TransactionExt tx = (TransactionExt) odmg.newTransaction();
1243: tx.begin();
1244: database.makePersistent(s1);
1245: tx.commit();
1246:
1247: // Now we delete the Shop with ShopDetail, but don't
1248: // touch the Distributor object
1249: tx.begin();
1250: database.deletePersistent(s1);
1251: // flush to avoid constraint error
1252: tx.flush();
1253: database.deletePersistent(sd);
1254: tx.commit();
1255: }
1256:
1257: /**
1258: * Class Shop has a bidirectional 1:1 reference with ShopDetail and the DB table of Shop
1259: * has a foreign key constraint on ShopDetail table. Shop has a m:n relation with Distributor.
1260: * <p/>
1261: * If the user take care of the ordering itself the test pass.
1262: */
1263: public void testBidirectionalWithConstraint_2b() throws Exception {
1264: String name = "testBidirectionalWithConstraint_2c_"
1265: + System.currentTimeMillis();
1266:
1267: Shop s1 = new Shop(name + "_1");
1268: Distributor d1 = new Distributor(name + "_1");
1269: s1.addDistributor(d1);
1270: d1.addShop(s1);
1271:
1272: TransactionExt tx = (TransactionExt) odmg.newTransaction();
1273: tx.begin();
1274: // When using flush() we can add objects step by step
1275: database.makePersistent(s1);
1276: tx.flush();
1277:
1278: // add the shop detail object to Shop
1279: ShopDetail sd = new ShopDetail(name + "_1");
1280: s1.setDetail(sd);
1281: sd.setShop(s1);
1282:
1283: tx.commit();
1284:
1285: // Delete all created objects, we disable implicit
1286: // locking and ordering to avoid constraint error
1287: tx.setImplicitLocking(false);
1288: tx.setOrdering(false);
1289: tx.begin();
1290: database.deletePersistent(d1);
1291: database.deletePersistent(s1);
1292: database.deletePersistent(sd);
1293: tx.commit();
1294: }
1295:
1296: /**
1297: * Class Shop has a bidirectional 1:1 reference with ShopDetail and the DB table of Shop
1298: * has a foreign key constraint on ShopDetail table. Shop has a m:n relation with Distributor.
1299: * <p/>
1300: * If the user take care of the ordering itself the test pass.
1301: */
1302: public void testBidirectionalWithConstraint_2d() throws Exception {
1303: String name = "testBidirectionalWithConstraint_2d_"
1304: + System.currentTimeMillis();
1305: Shop s1 = new Shop(name + "_1");
1306: ShopDetail sd = new ShopDetail(name + "_1");
1307: s1.setDetail(sd);
1308: sd.setShop(s1);
1309: Shop s2 = new Shop(name + "_2");
1310: Shop s3 = new Shop(name + "_3");
1311: Distributor d1 = new Distributor(name + "_1");
1312: Distributor d2 = new Distributor(name + "_2");
1313: Distributor d3 = new Distributor(name + "_3");
1314: Distributor d4 = new Distributor(name + "_4");
1315: s1.addDistributor(d1);
1316: d1.addShop(s1);
1317: s1.addDistributor(d2);
1318: d2.addShop(s1);
1319: s1.addDistributor(d3);
1320: d3.addShop(s1); // one
1321: s2.addDistributor(d1);
1322: d1.addShop(s2);
1323: s3.addDistributor(d4);
1324: d4.addShop(s3);
1325: s3.addDistributor(d1);
1326: d1.addShop(s3);
1327: d3.addShop(s2); // two
1328: s2.addDistributor(d3);
1329: d3.addShop(s3); // three
1330: s3.addDistributor(d3);
1331:
1332: TransactionExt tx = (TransactionExt) odmg.newTransaction();
1333: tx.begin();
1334: // mandatory to add the ShopDetail object first, because of the ordering bug
1335: database.makePersistent(sd);
1336: database.makePersistent(s1);
1337: database.makePersistent(s2);
1338: database.makePersistent(s3);
1339: tx.commit();
1340:
1341: tx.begin();
1342: database.deletePersistent(d1);
1343: database.deletePersistent(s1);
1344: database.deletePersistent(d4);
1345: tx.commit();
1346:
1347: tx.begin();
1348: // clear the cache to make this test work with all cache implementations
1349: tx.getBroker().clearCache();
1350:
1351: OQLQuery query = odmg.newOQLQuery();
1352: query.create("select shops from " + Shop.class.getName()
1353: + " where name like $1");
1354: query.bind(name + "%");
1355: Collection result = (Collection) query.execute();
1356:
1357: assertEquals(2, result.size());
1358:
1359: query = odmg.newOQLQuery();
1360: query.create("select objects from "
1361: + Distributor.class.getName() + " where name like $1");
1362: query.bind(name + "%");
1363: result = (Collection) query.execute();
1364:
1365: assertEquals(2, result.size());
1366: tx.commit();
1367:
1368: tx.begin();
1369: query = odmg.newOQLQuery();
1370: query.create("select objects from "
1371: + Distributor.class.getName() + " where name like $1");
1372: query.bind(name + "_3");
1373: result = (Collection) query.execute();
1374: tx.commit();
1375:
1376: assertEquals(1, result.size());
1377: Distributor d3New = (Distributor) result.iterator().next();
1378:
1379: assertNotNull(d3New.getShops());
1380: assertEquals(2, d3New.getShops().size());
1381: }
1382:
1383: public void testMtoNWithBackReference_2() throws Exception {
1384: String name = "testMtoNWithBackReference_2_"
1385: + System.currentTimeMillis();
1386: Shop s1 = new Shop(name + "_1");
1387: Shop s2 = new Shop(name + "_2");
1388: Shop s3 = new Shop(name + "_3");
1389: Distributor d1 = new Distributor(name + "_1");
1390: Distributor d2 = new Distributor(name + "_2");
1391: Distributor d3 = new Distributor(name + "_3");
1392: Distributor d4 = new Distributor(name + "_4");
1393: s1.addDistributor(d1);
1394: d1.addShop(s1);
1395: s1.addDistributor(d2);
1396: d2.addShop(s1);
1397: s1.addDistributor(d3);
1398: d3.addShop(s1);
1399: s2.addDistributor(d1);
1400: d1.addShop(s2);
1401: s3.addDistributor(d4);
1402: d4.addShop(s3);
1403: s3.addDistributor(d1);
1404: d1.addShop(s3);
1405: d3.addShop(s2);
1406: s2.addDistributor(d3);
1407: d3.addShop(s3);
1408: s3.addDistributor(d3);
1409:
1410: TransactionExt tx = (TransactionExt) odmg.newTransaction();
1411: tx.begin();
1412: // madatory to add the ShopDetail object first
1413: database.makePersistent(s1);
1414: database.makePersistent(s2);
1415: database.makePersistent(s3);
1416: tx.commit();
1417:
1418: tx.begin();
1419: tx.setCascadingDelete(Distributor.class, "shops", true);
1420: database.deletePersistent(d1);
1421: database.deletePersistent(s1);
1422: database.deletePersistent(d4);
1423: tx.commit();
1424:
1425: tx.begin();
1426: // clear cache to make it work with all caching implementations
1427: tx.getBroker().clearCache();
1428: OQLQuery query = odmg.newOQLQuery();
1429: query.create("select shops from " + Shop.class.getName()
1430: + " where name like $1");
1431: query.bind(name + "%");
1432: Collection result = (Collection) query.execute();
1433:
1434: assertEquals(0, result.size());
1435:
1436: query = odmg.newOQLQuery();
1437: query.create("select objects from "
1438: + Distributor.class.getName() + " where name like $1");
1439: query.bind(name + "%");
1440: result = (Collection) query.execute();
1441:
1442: assertEquals(2, result.size());
1443: tx.commit();
1444:
1445: tx.begin();
1446: query = odmg.newOQLQuery();
1447: query.create("select objects from "
1448: + Distributor.class.getName() + " where name like $1");
1449: query.bind(name + "_3");
1450: result = (Collection) query.execute();
1451: tx.commit();
1452:
1453: assertEquals(1, result.size());
1454: Distributor d3New = (Distributor) result.iterator().next();
1455:
1456: assertNotNull(d3New.getShops());
1457: assertEquals(0, d3New.getShops().size());
1458: }
1459:
1460: public void testOneToNWithSelfReference_1() throws Exception {
1461: String name = "testOneToNWithSelfReference_1_"
1462: + System.currentTimeMillis();
1463: Shop s = new Shop();
1464: s.setName(name);
1465: Product p1 = new Product();
1466: p1.setName(name + "_product_1");
1467: Product p2 = new Product();
1468: p2.setName(name + "_product_2");
1469:
1470: List products = new ArrayList();
1471: products.add(p1);
1472: products.add(p2);
1473:
1474: s.setProducts(products);
1475: p1.setShop(s);
1476: p2.setShop(s);
1477:
1478: Product p1a = new Product();
1479: p1a.setName(name + "_subProduct_A");
1480: Product p1b = new Product();
1481: p1b.setName(name + "_subProduct_B");
1482: Product p1c = new Product();
1483: p1c.setName(name + "_subProduct_C");
1484:
1485: List subProducts = new ArrayList();
1486: subProducts.add(p1a);
1487: subProducts.add(p1b);
1488: subProducts.add(p1c);
1489:
1490: p1.setSubProducts(subProducts);
1491:
1492: TransactionExt tx = (TransactionExt) odmg.newTransaction();
1493: tx.begin();
1494: database.makePersistent(s);
1495: tx.commit();
1496:
1497: tx.begin();
1498: tx.getBroker().clearCache();
1499:
1500: OQLQuery query = odmg.newOQLQuery();
1501: query.create("select products from " + Shop.class.getName()
1502: + " where name like $1");
1503: query.bind(name + "%");
1504: Collection result = (Collection) query.execute();
1505: tx.commit();
1506:
1507: assertEquals(1, result.size());
1508: Shop newShop = (Shop) result.iterator().next();
1509: assertNotNull(newShop.getProducts());
1510: assertEquals(2, newShop.getProducts().size());
1511:
1512: boolean match = false;
1513: for (Iterator iterator = newShop.getProducts().iterator(); iterator
1514: .hasNext();) {
1515: Product p = (Product) iterator.next();
1516: if (p.getSubProducts() != null
1517: && p.getSubProducts().size() > 0) {
1518: match = true;
1519: assertEquals(3, p.getSubProducts().size());
1520: }
1521: }
1522: assertTrue("Sub products aren't stored", match);
1523:
1524: tx.begin();
1525: database.deletePersistent(s);
1526: tx.commit();
1527:
1528: tx.begin();
1529: tx.getBroker().clearCache();
1530: query = odmg.newOQLQuery();
1531: query.create("select products from " + Product.class.getName()
1532: + " where name like $1");
1533: query.bind(name + "_subPro%");
1534: result = (Collection) query.execute();
1535: tx.commit();
1536: assertEquals(3, result.size());
1537:
1538: tx.begin();
1539: query = odmg.newOQLQuery();
1540: query.create("select products from " + Product.class.getName()
1541: + " where name like $1");
1542: query.bind(name + "_product_1");
1543: result = (Collection) query.execute();
1544: assertEquals(1, result.size());
1545:
1546: database.deletePersistent(result.iterator().next());
1547: tx.commit();
1548:
1549: tx.begin();
1550: tx.getBroker().clearCache();
1551: query = odmg.newOQLQuery();
1552: query.create("select products from " + Product.class.getName()
1553: + " where name like $1");
1554: query.bind(name + "_subPro%");
1555: result = (Collection) query.execute();
1556: tx.commit();
1557: assertEquals(3, result.size());
1558: }
1559:
1560: public void testOneToNWithSelfReference_2() throws Exception {
1561: String name = "testOneToNWithSelfReference_2_"
1562: + System.currentTimeMillis();
1563: Shop s = new Shop();
1564: s.setName(name);
1565: Product p1 = new Product();
1566: p1.setName(name + "_product_1");
1567: Product p2 = new Product();
1568: p2.setName(name + "_product_2");
1569:
1570: List products = new ArrayList();
1571: products.add(p1);
1572: products.add(p2);
1573:
1574: s.setProducts(products);
1575: p1.setShop(s);
1576: p2.setShop(s);
1577:
1578: Product p1a = new Product();
1579: p1a.setName(name + "_subProduct_A");
1580: Product p1b = new Product();
1581: p1b.setName(name + "_subProduct_B");
1582: Product p1c = new Product();
1583: p1c.setName(name + "_subProduct_C");
1584:
1585: List subProducts = new ArrayList();
1586: subProducts.add(p1a);
1587: subProducts.add(p1b);
1588: subProducts.add(p1c);
1589:
1590: p1.setSubProducts(subProducts);
1591:
1592: TransactionExt tx = (TransactionExt) odmg.newTransaction();
1593: tx.begin();
1594: database.makePersistent(s);
1595: tx.commit();
1596:
1597: tx.begin();
1598: tx.getBroker().clearCache();
1599:
1600: OQLQuery query = odmg.newOQLQuery();
1601: query.create("select products from " + Shop.class.getName()
1602: + " where name like $1");
1603: query.bind(name + "%");
1604: Collection result = (Collection) query.execute();
1605: tx.commit();
1606:
1607: assertEquals(1, result.size());
1608: Shop newShop = (Shop) result.iterator().next();
1609: assertNotNull(newShop.getProducts());
1610: assertEquals(2, newShop.getProducts().size());
1611:
1612: boolean match = false;
1613: for (Iterator iterator = newShop.getProducts().iterator(); iterator
1614: .hasNext();) {
1615: Product p = (Product) iterator.next();
1616: if (p.getSubProducts() != null
1617: && p.getSubProducts().size() > 0) {
1618: match = true;
1619: assertEquals(3, p.getSubProducts().size());
1620: }
1621: }
1622: assertTrue("Sub products aren't stored", match);
1623:
1624: tx.begin();
1625: // now we enable cascading delete
1626: tx.setCascadingDelete(Shop.class, true);
1627: database.deletePersistent(s);
1628: tx.commit();
1629:
1630: tx.begin();
1631: tx.getBroker().clearCache();
1632: query = odmg.newOQLQuery();
1633: query.create("select products from " + Product.class.getName()
1634: + " where name like $1");
1635: query.bind(name + "_subPro%");
1636: result = (Collection) query.execute();
1637: assertEquals(3, result.size());
1638:
1639: query = odmg.newOQLQuery();
1640: query.create("select products from " + Product.class.getName()
1641: + " where name like $1");
1642: query.bind(name + "_product_1");
1643: result = (Collection) query.execute();
1644: assertEquals(0, result.size());
1645:
1646: tx.commit();
1647: }
1648:
1649: public void testOneToNWithSelfReference_3() throws Exception {
1650: String name = "testOneToNWithSelfReference_3_"
1651: + System.currentTimeMillis();
1652: Shop s = new Shop();
1653: s.setName(name);
1654: Product p1 = new Product();
1655: p1.setName(name + "_product_1");
1656: Product p2 = new Product();
1657: p2.setName(name + "_product_2");
1658:
1659: List products = new ArrayList();
1660: products.add(p1);
1661: products.add(p2);
1662:
1663: s.setProducts(products);
1664: p1.setShop(s);
1665: p2.setShop(s);
1666:
1667: Product p1a = new Product();
1668: p1a.setName(name + "_subProduct_A");
1669: Product p1b = new Product();
1670: p1b.setName(name + "_subProduct_B");
1671: Product p1c = new Product();
1672: p1c.setName(name + "_subProduct_C");
1673:
1674: List subProducts = new ArrayList();
1675: subProducts.add(p1a);
1676: subProducts.add(p1b);
1677: subProducts.add(p1c);
1678:
1679: p1.setSubProducts(subProducts);
1680:
1681: TransactionExt tx = (TransactionExt) odmg.newTransaction();
1682: tx.begin();
1683: database.makePersistent(s);
1684: tx.commit();
1685:
1686: tx.begin();
1687: tx.getBroker().clearCache();
1688:
1689: OQLQuery query = odmg.newOQLQuery();
1690: query.create("select products from " + Shop.class.getName()
1691: + " where name like $1");
1692: query.bind(name + "%");
1693: Collection result = (Collection) query.execute();
1694: tx.commit();
1695:
1696: assertEquals(1, result.size());
1697: Shop newShop = (Shop) result.iterator().next();
1698: assertNotNull(newShop.getProducts());
1699: assertEquals(2, newShop.getProducts().size());
1700:
1701: boolean match = false;
1702: for (Iterator iterator = newShop.getProducts().iterator(); iterator
1703: .hasNext();) {
1704: Product p = (Product) iterator.next();
1705: if (p.getSubProducts() != null
1706: && p.getSubProducts().size() > 0) {
1707: match = true;
1708: assertEquals(3, p.getSubProducts().size());
1709: }
1710: }
1711: assertTrue("Sub products aren't stored", match);
1712:
1713: tx.begin();
1714: // now we enable cascading delete
1715: tx.setCascadingDelete(Shop.class, true);
1716: tx.setCascadingDelete(Product.class, true);
1717: database.deletePersistent(s);
1718: tx.commit();
1719:
1720: tx.begin();
1721: tx.getBroker().clearCache();
1722: query = odmg.newOQLQuery();
1723: query.create("select products from " + Product.class.getName()
1724: + " where name like $1");
1725: query.bind(name + "_subPro%");
1726: result = (Collection) query.execute();
1727: assertEquals(0, result.size());
1728:
1729: query = odmg.newOQLQuery();
1730: query.create("select products from " + Product.class.getName()
1731: + " where name like $1");
1732: query.bind(name + "_product_1");
1733: result = (Collection) query.execute();
1734: assertEquals(0, result.size());
1735:
1736: tx.commit();
1737: }
1738:
1739: public void testOneToOneWithBackReference_1() throws Exception {
1740: String name = "testOneToOneWithBackReference_1_"
1741: + System.currentTimeMillis();
1742: Shop s = new Shop();
1743: s.setName(name);
1744: ShopDetail sd = new ShopDetail();
1745: sd.setName(name);
1746: s.setDetail(sd);
1747: sd.setShop(s);
1748:
1749: TransactionExt tx = (TransactionExt) odmg.newTransaction();
1750: tx.begin();
1751: database.makePersistent(s);
1752: // before establishing the circular references write
1753: // all objects to DB
1754: tx.flush();
1755: // now close the circular references
1756: tx.commit();
1757:
1758: tx.begin();
1759: tx.getBroker().clearCache();
1760:
1761: OQLQuery query = odmg.newOQLQuery();
1762: query.create("select detail from " + ShopDetail.class.getName()
1763: + " where name like $1");
1764: query.bind(name);
1765: Collection result = (Collection) query.execute();
1766: tx.commit();
1767:
1768: assertEquals(1, result.size());
1769: ShopDetail sdNew = (ShopDetail) result.iterator().next();
1770: assertNotNull(sdNew.getShop());
1771:
1772: tx.begin();
1773: tx.lock(sdNew, Transaction.WRITE);
1774: Shop tmp = sdNew.getShop();
1775: // it's bidirectional, so remove this references first
1776: tmp.setDetail(null);
1777: sdNew.setShop(null);
1778: database.deletePersistent(tmp);
1779: tx.flush();
1780:
1781: query = odmg.newOQLQuery();
1782: query.create("select detail from " + ShopDetail.class.getName()
1783: + " where name like $1");
1784: query.bind(name);
1785: result = (Collection) query.execute();
1786: assertEquals(1, result.size());
1787: ShopDetail newSd = (ShopDetail) result.iterator().next();
1788: assertNotNull(newSd);
1789: assertNull(newSd.getShop());
1790: tx.commit();
1791:
1792: tx.begin();
1793: query = odmg.newOQLQuery();
1794: query.create("select shops from " + Shop.class.getName()
1795: + " where name like $1");
1796: query.bind(name);
1797: Collection resultShop = (Collection) query.execute();
1798: assertEquals(0, resultShop.size());
1799:
1800: // delete ShopDetail too
1801: database.deletePersistent(newSd);
1802: tx.commit();
1803: }
1804:
1805: public void testOneToOneWithBackReference_3() throws Exception {
1806: String name = "testOneToOneWithBackReference_3_"
1807: + System.currentTimeMillis();
1808: Shop s = new Shop();
1809: s.setName(name);
1810: ShopDetail sd = new ShopDetail();
1811: sd.setName(name);
1812: s.setDetail(sd);
1813: sd.setShop(s);
1814:
1815: TransactionExt tx = (TransactionExt) odmg.newTransaction();
1816: tx.begin();
1817: database.makePersistent(s);
1818: database.deletePersistent(s);
1819: database.makePersistent(s);
1820: tx.commit();
1821:
1822: tx.begin();
1823: OQLQuery query = odmg.newOQLQuery();
1824: query.create("select shops from " + Shop.class.getName()
1825: + " where name like $1");
1826: query.bind(name);
1827: Collection result = (Collection) query.execute();
1828: tx.commit();
1829:
1830: assertEquals(1, result.size());
1831: Shop newShop = (Shop) result.iterator().next();
1832: assertNotNull(newShop.getDetail());
1833:
1834: tx.begin();
1835: database.deletePersistent(newShop);
1836: // add object again, we expect that nothing was deleted
1837: database.makePersistent(newShop);
1838: // flush changes to DB, we don't change anything
1839: tx.flush();
1840: query = odmg.newOQLQuery();
1841: query.create("select shops from " + Shop.class.getName()
1842: + " where name like $1");
1843: query.bind(name);
1844: result = (Collection) query.execute();
1845: tx.commit();
1846:
1847: assertEquals(1, result.size());
1848: Shop tmp = (Shop) result.iterator().next();
1849: assertNotNull(tmp.getDetail());
1850:
1851: tx.begin();
1852: database.deletePersistent(newShop);
1853: database.makePersistent(newShop);
1854: database.deletePersistent(newShop);
1855: tx.flush();
1856: database.deletePersistent(newShop.getDetail());
1857: tx.flush();
1858:
1859: query = odmg.newOQLQuery();
1860: query.create("select detail from " + ShopDetail.class.getName()
1861: + " where name like $1");
1862: query.bind(name);
1863: result = (Collection) query.execute();
1864: assertEquals(0, result.size());
1865:
1866: query = odmg.newOQLQuery();
1867: query.create("select shops from " + Shop.class.getName()
1868: + " where name like $1");
1869: query.bind(name);
1870: result = (Collection) query.execute();
1871: assertEquals(0, result.size());
1872: tx.commit();
1873:
1874: tx.begin();
1875: query = odmg.newOQLQuery();
1876: query.create("select detail from " + ShopDetail.class.getName()
1877: + " where name like $1");
1878: query.bind(name);
1879: result = (Collection) query.execute();
1880: assertEquals(0, result.size());
1881:
1882: query = odmg.newOQLQuery();
1883: query.create("select shops from " + Shop.class.getName()
1884: + " where name like $1");
1885: query.bind(name);
1886: result = (Collection) query.execute();
1887: assertEquals(0, result.size());
1888: tx.commit();
1889: }
1890:
1891: public void testOneToOneWithBackReference_2() throws Exception {
1892: String name = "testOneToOneWithBackReference_2_"
1893: + System.currentTimeMillis();
1894: Shop s = new Shop();
1895: s.setName(name);
1896: ShopDetail sd = new ShopDetail();
1897: sd.setName(name);
1898: s.setDetail(sd);
1899: sd.setShop(s);
1900:
1901: TransactionExt tx = (TransactionExt) odmg.newTransaction();
1902: tx.begin();
1903: database.makePersistent(s);
1904: // shop and shopDetail have a bidirectional 1:1 reference
1905: // on flush() OJB will insert both objects and set one FK
1906: tx.flush();
1907: // on commit() OJB will be aware of the bidirectional reference
1908: // and set the second FK
1909: tx.commit();
1910:
1911: tx.begin();
1912: tx.getBroker().clearCache();
1913:
1914: OQLQuery query = odmg.newOQLQuery();
1915: query.create("select detail from " + ShopDetail.class.getName()
1916: + " where name like $1");
1917: query.bind(name);
1918: Collection result = (Collection) query.execute();
1919: tx.commit();
1920:
1921: assertEquals(1, result.size());
1922: ShopDetail sdNew = (ShopDetail) result.iterator().next();
1923: assertNotNull(sdNew.getShop());
1924:
1925: tx.begin();
1926: // cascading delete should delete Shop too
1927: tx.setCascadingDelete(ShopDetail.class, true);
1928: database.deletePersistent(sdNew);
1929: tx.flush();
1930:
1931: query = odmg.newOQLQuery();
1932: query.create("select detail from " + ShopDetail.class.getName()
1933: + " where name like $1");
1934: query.bind(name);
1935: result = (Collection) query.execute();
1936: tx.commit();
1937: assertEquals(0, result.size());
1938:
1939: tx.begin();
1940: query = odmg.newOQLQuery();
1941: query.create("select detail from " + Shop.class.getName()
1942: + " where name like $1");
1943: query.bind(name);
1944: result = (Collection) query.execute();
1945: assertEquals(0, result.size());
1946: tx.commit();
1947: }
1948:
1949: public static class Shop {
1950: private Integer id;
1951: private String name;
1952: private ShopDetail detail;
1953: private List products;
1954: private List distributors;
1955:
1956: public Shop() {
1957: }
1958:
1959: public Shop(String name) {
1960: this .name = name;
1961: }
1962:
1963: public Integer getId() {
1964: return id;
1965: }
1966:
1967: public void setId(Integer id) {
1968: this .id = id;
1969: }
1970:
1971: public String getName() {
1972: return name;
1973: }
1974:
1975: public void setName(String name) {
1976: this .name = name;
1977: }
1978:
1979: public ShopDetail getDetail() {
1980: return detail;
1981: }
1982:
1983: public void setDetail(ShopDetail detail) {
1984: this .detail = detail;
1985: }
1986:
1987: public List getProducts() {
1988: return products;
1989: }
1990:
1991: public void setProducts(List products) {
1992: this .products = products;
1993: }
1994:
1995: public List getDistributors() {
1996: return distributors;
1997: }
1998:
1999: public void setDistributors(List distributors) {
2000: this .distributors = distributors;
2001: }
2002:
2003: public void addDistributor(Distributor d) {
2004: if (this .distributors == null) {
2005: this .distributors = new ArrayList();
2006: }
2007: this .distributors.add(d);
2008: }
2009: }
2010:
2011: public static class Distributor {
2012: private Integer id;
2013: private String name;
2014: private List shops;
2015:
2016: public Distributor() {
2017: }
2018:
2019: public Distributor(String name) {
2020: this .name = name;
2021: }
2022:
2023: public Integer getId() {
2024: return id;
2025: }
2026:
2027: public void setId(Integer id) {
2028: this .id = id;
2029: }
2030:
2031: public String getName() {
2032: return name;
2033: }
2034:
2035: public void setName(String name) {
2036: this .name = name;
2037: }
2038:
2039: public List getShops() {
2040: return shops;
2041: }
2042:
2043: public void setShops(List shops) {
2044: this .shops = shops;
2045: }
2046:
2047: public void addShop(Shop s) {
2048: if (this .shops == null) {
2049: this .shops = new ArrayList();
2050: }
2051: this .shops.add(s);
2052: }
2053: }
2054:
2055: public static class Product {
2056: private Integer id;
2057: private String name;
2058: private Shop shop;
2059: private Integer shopFk;
2060: private List subProducts;
2061: private Integer subProductFK;
2062:
2063: public Product() {
2064: }
2065:
2066: public Product(String name) {
2067: this .name = name;
2068: }
2069:
2070: public Integer getId() {
2071: return id;
2072: }
2073:
2074: public void setId(Integer id) {
2075: this .id = id;
2076: }
2077:
2078: public String getName() {
2079: return name;
2080: }
2081:
2082: public void setName(String name) {
2083: this .name = name;
2084: }
2085:
2086: public Shop getShop() {
2087: return shop;
2088: }
2089:
2090: public void setShop(Shop shop) {
2091: this .shop = shop;
2092: }
2093:
2094: public Integer getShopFk() {
2095: return shopFk;
2096: }
2097:
2098: public void setShopFk(Integer shopFk) {
2099: this .shopFk = shopFk;
2100: }
2101:
2102: public Integer getSubProductFK() {
2103: return subProductFK;
2104: }
2105:
2106: public void setSubProductFK(Integer subProductFK) {
2107: this .subProductFK = subProductFK;
2108: }
2109:
2110: public void addSubProduct(Product p) {
2111: if (subProducts == null) {
2112: subProducts = new ArrayList();
2113: }
2114: subProducts.add(p);
2115: }
2116:
2117: public List getSubProducts() {
2118: return subProducts;
2119: }
2120:
2121: public void setSubProducts(List subProducts) {
2122: this .subProducts = subProducts;
2123: }
2124: }
2125:
2126: public static class ShopDetail {
2127: private Integer id;
2128: private String name;
2129: private Shop shop;
2130:
2131: public ShopDetail() {
2132: }
2133:
2134: public ShopDetail(String name) {
2135: this .name = name;
2136: }
2137:
2138: public Integer getId() {
2139: return id;
2140: }
2141:
2142: public void setId(Integer id) {
2143: this .id = id;
2144: }
2145:
2146: public String getName() {
2147: return name;
2148: }
2149:
2150: public void setName(String name) {
2151: this .name = name;
2152: }
2153:
2154: public Shop getShop() {
2155: return shop;
2156: }
2157:
2158: public void setShop(Shop shop) {
2159: this .shop = shop;
2160: }
2161: }
2162:
2163: abstract static class BaseObject {
2164: private Integer id;
2165: private String name;
2166: private String ojbConcreteClass;
2167:
2168: public BaseObject() {
2169: this .ojbConcreteClass = this .getClass().getName();
2170: }
2171:
2172: public BaseObject(String name) {
2173: this ();
2174: this .name = name;
2175: }
2176:
2177: public Integer getId() {
2178: return id;
2179: }
2180:
2181: public void setId(Integer id) {
2182: this .id = id;
2183: }
2184:
2185: public String getName() {
2186: return name;
2187: }
2188:
2189: public void setName(String name) {
2190: this .name = name;
2191: }
2192:
2193: public String getOjbConcreteClass() {
2194: return ojbConcreteClass;
2195: }
2196:
2197: public void setOjbConcreteClass(String ojbConcreteClass) {
2198: this .ojbConcreteClass = ojbConcreteClass;
2199: }
2200: }
2201:
2202: public static class ObjectA extends BaseObject {
2203: private ObjectAA refAA;
2204:
2205: public ObjectA() {
2206: }
2207:
2208: public ObjectA(String name) {
2209: super (name);
2210: }
2211:
2212: public ObjectAA getRefAA() {
2213: return refAA;
2214: }
2215:
2216: public void setRefAA(ObjectAA refAA) {
2217: this .refAA = refAA;
2218: }
2219: }
2220:
2221: public static class ObjectAA extends BaseObject {
2222: private ObjectAAA refAAA;
2223:
2224: public ObjectAA() {
2225: }
2226:
2227: public ObjectAA(String name) {
2228: super (name);
2229: }
2230:
2231: public ObjectAAA getRefAAA() {
2232: return refAAA;
2233: }
2234:
2235: public void setRefAAA(ObjectAAA refAAA) {
2236: this .refAAA = refAAA;
2237: }
2238: }
2239:
2240: public static class ObjectAAA extends BaseObject {
2241: private ObjectAAAA refAAAA;
2242: private ObjectA refA;
2243:
2244: public ObjectAAA() {
2245: }
2246:
2247: public ObjectAAA(String name) {
2248: super (name);
2249: }
2250:
2251: public ObjectAAAA getRefAAAA() {
2252: return refAAAA;
2253: }
2254:
2255: public void setRefAAAA(ObjectAAAA refAAAA) {
2256: this .refAAAA = refAAAA;
2257: }
2258:
2259: public ObjectA getRefA() {
2260: return refA;
2261: }
2262:
2263: public void setRefA(ObjectA refA) {
2264: this .refA = refA;
2265: }
2266: }
2267:
2268: public static class ObjectAAAA extends BaseObject {
2269: private ObjectA refA;
2270:
2271: public ObjectAAAA() {
2272: }
2273:
2274: public ObjectAAAA(String name) {
2275: super (name);
2276: }
2277:
2278: public ObjectA getRefA() {
2279: return refA;
2280: }
2281:
2282: public void setRefA(ObjectA refA) {
2283: this.refA = refA;
2284: }
2285: }
2286: }
|