KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ojb > odmg > CircularTest


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

17
18 import java.util.ArrayList JavaDoc;
19 import java.util.Collection JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.List JavaDoc;
22
23 import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
24 import org.apache.ojb.broker.metadata.ClassDescriptor;
25 import org.apache.ojb.junit.ODMGTestCase;
26 import org.odmg.OQLQuery;
27 import org.odmg.Transaction;
28
29 /**
30  * Testing complex object graphs with circular and bidirectional references when
31  * using database foreign key settings (without support of deferred foreign keys).
32  * <p/>
33  * The classes hierarchy looks like:
34  * <br/>
35  * Class Shop has a bidirectional 1:1 reference with ShopDetail.<br/>
36  * Shop has a 1:n relation with Product, Product has a 1:1 reference to Shop.<br/>
37  * Shop has a m:n relation with Distributor.<br/>
38  * Product has a 1:n relation to itself to handle sub-Products.<br/>
39  * <p/>
40  * In the database the following foreign keys are declared:
41  * <br/>
42  * - Shop has a FK to ShopDetail<br/>
43  * - Product has a FK to Product<br/>
44  * - Product has a FK to Shop<br/>
45  * - CT_SHOP_DISTRIBUTOR indirection table has FK's to Shop and Distributor<br/>
46  * <p/>
47  * Here a summery of the dependencies:<br/>
48  * Shop--1:1-->ShopDetail--1:1-->Shop<br/>
49  * Shop--1:n-->Product--1:1-->Shop<br/>
50  * Product--1:n-->Product<br/>
51  * Shop--m:n-->Distributor<br/>
52  * <p/>
53  * <p/>
54  * Class ObjectA has a 1:1 reference to ObjectAA,<br/>
55  * ObjectAA has 1:1 to ObjectAAA,<br/>
56  * ObjectAAA has 1:1 to ObjectA and to ObjectAAAA,<br/>
57  * ObjectAAAA has 1:1 to ObjectA<br/>
58  * <br/>
59  * - ObjectA has FK to ObjectAA<br/>
60  * - ObjectAA has FK to ObjectAAA<br/>
61  * - ObjectAAA has FK to ObjectAAAA<br/>
62  * <p/>
63  * Here a summery of the dependencies:<br/>
64  * ObjetA--1:1-->ObjectAA--1:1-->ObjectAAA--1:1-->ObjectA
65  * ObjetA--1:1-->ObjectAA--1:1-->ObjectAAA--1:1-->ObjectAAAA--1:1-->ObjectA
66  *
67  * @version $Id: CircularTest.java,v 1.1.2.10 2005/12/21 22:31:28 tomdz Exp $
68  */

69 public class CircularTest extends ODMGTestCase
70 {
71     public static void main(String JavaDoc[] args)
72     {
73         String JavaDoc[] arr = {CircularTest.class.getName()};
74         junit.textui.TestRunner.main(arr);
75     }
76
77     /**
78      * Handling circular 1:n references with FK settings and use of
79      * auto-delete setting to delete object graph.
80      */

81     public void testCircularOneToN_1() throws Exception JavaDoc
82     {
83         String JavaDoc name = "testCircularOneToN_1_" + System.currentTimeMillis();
84         ojbChangeReferenceSetting(Product.class, "subProducts", true, ObjectReferenceDescriptor.CASCADE_NONE, ObjectReferenceDescriptor.CASCADE_OBJECT, false);
85
86         Product p1 = new Product(name + "_p1");
87         Product p2 = new Product(name + "_p2");
88         Product p3 = new Product(name + "_p3");
89
90         TransactionExt tx = (TransactionExt) odmg.newTransaction();
91         tx.begin();
92         p1.addSubProduct(p2);
93         p2.addSubProduct(p3);
94         database.makePersistent(p3);
95         // before establishing the circular references write
96
// all objects to DB
97
tx.flush();
98         // now close the circular references
99
p3.addSubProduct(p1);
100         tx.commit();
101
102         tx.begin();
103         // on delete break the circular references first, then delete the
104
// start object
105
tx.lock(p3, Transaction.WRITE);
106         // this call is only needed if auto-delete setting in repository is 'object'
107
tx.setCascadingDelete(Product.class, "subProducts", false);
108         p3.setSubProducts(null);
109         tx.flush();
110         database.deletePersistent(p3);
111         database.deletePersistent(p2);
112         database.deletePersistent(p1);
113         tx.commit();
114
115         tx.begin();
116         OQLQuery query = odmg.newOQLQuery();
117         query.create("select objects from " + Product.class.getName() + " where name like $1");
118         query.bind(name + "%");
119         Collection JavaDoc result = (Collection JavaDoc) query.execute();
120         tx.commit();
121
122         assertEquals(0, result.size());
123     }
124
125     /**
126      * Handling circular 1:n references with FK settings and use of
127      * auto-delete setting to delete object graph.
128      */

129     public void testCircularOneToN_2() throws Exception JavaDoc
130     {
131         String JavaDoc name = "testCircularOneToN_2_" + System.currentTimeMillis();
132         ojbChangeReferenceSetting(Product.class, "subProducts", true, ObjectReferenceDescriptor.CASCADE_NONE, ObjectReferenceDescriptor.CASCADE_OBJECT, false);
133
134         Product p1 = new Product(name + "_p1");
135         Product p2 = new Product(name + "_p2");
136         Product p3 = new Product(name + "_p3");
137         Product p4 = new Product(name + "_p4");
138         Product p5 = new Product(name + "_p5");
139         Product p6 = new Product(name + "_p6");
140         Product p7 = new Product(name + "_p7");
141
142         TransactionExt tx = (TransactionExt) odmg.newTransaction();
143         tx.begin();
144         p1.addSubProduct(p2);
145         p1.addSubProduct(p3);
146         p3.addSubProduct(p4);
147         p3.addSubProduct(p5);
148         p5.addSubProduct(p6);
149         p6.addSubProduct(p7);
150         database.makePersistent(p1);
151         // before establishing the circular references write
152
// all objects to DB
153
tx.flush();
154         // now close the circular references
155
p6.addSubProduct(p1);
156         tx.commit();
157
158         tx.begin();
159         // on delete break the circular references first, then delete the
160
// start object
161
tx.lock(p6, Transaction.WRITE);
162         tx.setCascadingDelete(Product.class, "subProducts", false);
163         p6.setSubProducts(null);
164         tx.flush();
165         tx.setCascadingDelete(Product.class, "subProducts", true);
166         database.deletePersistent(p1);
167         tx.commit();
168
169         tx.begin();
170         OQLQuery query = odmg.newOQLQuery();
171         query.create("select objects from " + Product.class.getName() + " where name like $1");
172         query.bind(name + "%");
173         Collection JavaDoc result = (Collection JavaDoc) query.execute();
174         tx.commit();
175
176         // we expect one Product object, because we set cascading delete 'false'
177
// when do 'p6.setSubProducts(null);', so the '..._p7' Product will only be unlinked
178
assertEquals(1, result.size());
179         Product p7_new = (Product) result.iterator().next();
180         assertEquals(name + "_p7", p7_new.getName());
181     }
182
183     /**
184      * Handling circular 1:n references with FK settings and use of
185      * auto-delete setting to delete object graph.
186      */

187     public void testCircularOneToN_3() throws Exception JavaDoc
188     {
189         String JavaDoc name = "testCircularOneToN_3_" + System.currentTimeMillis();
190         ojbChangeReferenceSetting(Product.class, "subProducts", true, ObjectReferenceDescriptor.CASCADE_NONE, ObjectReferenceDescriptor.CASCADE_OBJECT, false);
191
192         Product p1 = new Product(name + "_p1");
193         Product p2 = new Product(name + "_p2");
194         Product p3 = new Product(name + "_p3");
195
196         TransactionExt tx = (TransactionExt) odmg.newTransaction();
197         tx.begin();
198         p1.addSubProduct(p2);
199         p2.addSubProduct(p3);
200         database.makePersistent(p3);
201         // before establishing the circular references write
202
// all objects to DB
203
tx.flush();
204         // now close the circular references
205
p3.addSubProduct(p1);
206         tx.commit();
207
208         tx.begin();
209         // on delete break the circular references first, then delete the
210
// start object
211
tx.lock(p3, Transaction.WRITE);
212         // this call is only needed if auto-delete setting in repository is 'object'
213
tx.setCascadingDelete(Product.class, "subProducts", false);
214         p3.setSubProducts(null);
215         tx.flush();
216         // this call is only needed if auto-delete setting in repository is 'none'
217
// to enable cascade delete, else we have to delete each object by hand
218
tx.setCascadingDelete(Product.class, "subProducts", true);
219         database.deletePersistent(p1);
220         tx.commit();
221
222         tx.begin();
223         OQLQuery query = odmg.newOQLQuery();
224         query.create("select objects from " + Product.class.getName() + " where name like $1");
225         query.bind(name + "%");
226         Collection JavaDoc result = (Collection JavaDoc) query.execute();
227         tx.commit();
228
229         assertEquals(0, result.size());
230     }
231
232     /**
233      * Use auto-delete setting to delete object graph.
234      */

235     public void testCircularWithAutoDeleteEnabled() throws Exception JavaDoc
236     {
237         String JavaDoc name = "testCircularWithAutoDeleteEnabled_" + System.currentTimeMillis();
238
239         ojbChangeReferenceSetting(ObjectA.class, "refAA", true, ObjectReferenceDescriptor.CASCADE_NONE, ObjectReferenceDescriptor.CASCADE_OBJECT, false);
240         ojbChangeReferenceSetting(ObjectAA.class, "refAAA", true, ObjectReferenceDescriptor.CASCADE_NONE, ObjectReferenceDescriptor.CASCADE_OBJECT, false);
241         ojbChangeReferenceSetting(ObjectAAA.class, "refAAAA", true, ObjectReferenceDescriptor.CASCADE_NONE, ObjectReferenceDescriptor.CASCADE_OBJECT, false);
242         ojbChangeReferenceSetting(ObjectAAAA.class, "refA", true, ObjectReferenceDescriptor.CASCADE_NONE, ObjectReferenceDescriptor.CASCADE_OBJECT, false);
243
244         ObjectA a = new ObjectA(name + "_ObjectA");
245         ObjectAA aa = new ObjectAA(name + "_ObjectAA");
246         ObjectAAA aaa = new ObjectAAA(name + "_ObjectAAA");
247         ObjectAAAA aaaa = new ObjectAAAA(name + "_ObjectAAAA");
248         // now set the circular references
249
a.setRefAA(aa);
250         aa.setRefAAA(aaa);
251         aaa.setRefAAAA(aaaa);
252         aaaa.setRefA(a);
253
254         TransactionExt tx = (TransactionExt) odmg.newTransaction();
255         tx.begin();
256         database.makePersistent(a);
257         tx.commit();
258
259         tx.begin();
260         OQLQuery query = odmg.newOQLQuery();
261         query.create("select objects from " + ObjectA.class.getName() + " where name like $1");
262         query.bind(name + "%");
263         Collection JavaDoc result = (Collection JavaDoc) query.execute();
264         assertEquals(1, result.size());
265
266         query = odmg.newOQLQuery();
267         query.create("select objects from " + ObjectAA.class.getName() + " where name like $1");
268         query.bind(name + "%");
269         result = (Collection JavaDoc) query.execute();
270         assertEquals(1, result.size());
271
272         query = odmg.newOQLQuery();
273         query.create("select objects from " + ObjectAAA.class.getName() + " where name like $1");
274         query.bind(name + "%");
275         result = (Collection JavaDoc) query.execute();
276         assertEquals(1, result.size());
277
278         query = odmg.newOQLQuery();
279         query.create("select objects from " + ObjectAAAA.class.getName() + " where name like $1");
280         query.bind(name + "%");
281         result = (Collection JavaDoc) query.execute();
282         assertEquals(1, result.size());
283         tx.commit();
284
285         tx.begin();
286         /*
287         arminw: When deleting a object which is part of circular 1:1 references
288         with cascade delete enabled it's mandatory to break the circular reference
289         before deleting it.
290         */

291         tx.lock(aaaa, Transaction.WRITE);
292         // break the circular references
293
aaaa.setRefA(null);
294         database.deletePersistent(a);
295         tx.commit();
296
297         tx.begin();
298         query = odmg.newOQLQuery();
299         query.create("select objects from " + ObjectA.class.getName() + " where name like $1");
300         query.bind(name + "%");
301         result = (Collection JavaDoc) query.execute();
302         assertEquals(0, result.size());
303
304         query = odmg.newOQLQuery();
305         query.create("select objects from " + ObjectAA.class.getName() + " where name like $1");
306         query.bind(name + "%");
307         result = (Collection JavaDoc) query.execute();
308         assertEquals(0, result.size());
309
310         query = odmg.newOQLQuery();
311         query.create("select objects from " + ObjectAAA.class.getName() + " where name like $1");
312         query.bind(name + "%");
313         result = (Collection JavaDoc) query.execute();
314         assertEquals(0, result.size());
315
316         query = odmg.newOQLQuery();
317         query.create("select objects from " + ObjectAAAA.class.getName() + " where name like $1");
318         query.bind(name + "%");
319         result = (Collection JavaDoc) query.execute();
320         assertEquals(0, result.size());
321         tx.commit();
322     }
323
324     /**
325      * Use auto-delete setting to delete object graph.
326      */

327     public void testAutoDeleteEnabledNonCircular() throws Exception JavaDoc
328     {
329         String JavaDoc name = "testAutoDeleteEnabledNonCircular_" + System.currentTimeMillis();
330
331         ojbChangeReferenceSetting(ObjectA.class, "refAA", true, ObjectReferenceDescriptor.CASCADE_NONE, ObjectReferenceDescriptor.CASCADE_OBJECT, false);
332         ojbChangeReferenceSetting(ObjectAA.class, "refAAA", true, ObjectReferenceDescriptor.CASCADE_NONE, ObjectReferenceDescriptor.CASCADE_OBJECT, false);
333         ojbChangeReferenceSetting(ObjectAAA.class, "refAAAA", true, ObjectReferenceDescriptor.CASCADE_NONE, ObjectReferenceDescriptor.CASCADE_OBJECT, false);
334         ojbChangeReferenceSetting(ObjectAAAA.class, "refA", true, ObjectReferenceDescriptor.CASCADE_NONE, ObjectReferenceDescriptor.CASCADE_OBJECT, false);
335
336         ObjectA a = new ObjectA(name + "_ObjectA");
337         ObjectAA aa = new ObjectAA(name + "_ObjectAA");
338         ObjectAAA aaa = new ObjectAAA(name + "_ObjectAAA");
339         ObjectAAAA aaaa = new ObjectAAAA(name + "_ObjectAAAA");
340         // now set the references
341
a.setRefAA(aa);
342         aa.setRefAAA(aaa);
343         aaa.setRefAAAA(aaaa);
344
345         TransactionExt tx = (TransactionExt) odmg.newTransaction();
346         tx.begin();
347         database.makePersistent(a);
348         tx.commit();
349
350         tx.begin();
351         OQLQuery query = odmg.newOQLQuery();
352         query.create("select objects from " + ObjectA.class.getName() + " where name like $1");
353         query.bind(name + "%");
354         Collection JavaDoc result = (Collection JavaDoc) query.execute();
355         assertEquals(1, result.size());
356
357         query = odmg.newOQLQuery();
358         query.create("select objects from " + ObjectAA.class.getName() + " where name like $1");
359         query.bind(name + "%");
360         result = (Collection JavaDoc) query.execute();
361         assertEquals(1, result.size());
362
363         query = odmg.newOQLQuery();
364         query.create("select objects from " + ObjectAAA.class.getName() + " where name like $1");
365         query.bind(name + "%");
366         result = (Collection JavaDoc) query.execute();
367         assertEquals(1, result.size());
368
369         query = odmg.newOQLQuery();
370         query.create("select objects from " + ObjectAAAA.class.getName() + " where name like $1");
371         query.bind(name + "%");
372         result = (Collection JavaDoc) query.execute();
373         assertEquals(1, result.size());
374         tx.commit();
375
376         tx.begin();
377         database.deletePersistent(a);
378         tx.commit();
379
380         tx.begin();
381         query = odmg.newOQLQuery();
382         query.create("select objects from " + ObjectA.class.getName() + " where name like $1");
383         query.bind(name + "%");
384         result = (Collection JavaDoc) query.execute();
385         assertEquals(0, result.size());
386
387         query = odmg.newOQLQuery();
388         query.create("select objects from " + ObjectAA.class.getName() + " where name like $1");
389         query.bind(name + "%");
390         result = (Collection JavaDoc) query.execute();
391         assertEquals(0, result.size());
392
393         query = odmg.newOQLQuery();
394         query.create("select objects from " + ObjectAAA.class.getName() + " where name like $1");
395         query.bind(name + "%");
396         result = (Collection JavaDoc) query.execute();
397         assertEquals(0, result.size());
398
399         query = odmg.newOQLQuery();
400         query.create("select objects from " + ObjectAAAA.class.getName() + " where name like $1");
401         query.bind(name + "%");
402         result = (Collection JavaDoc) query.execute();
403         assertEquals(0, result.size());
404         tx.commit();
405     }
406
407     /**
408      * Handle circuler 1:1 with default methods.
409      */

410     public void testBidirectionalWithConstraint_1a() throws Exception JavaDoc
411     {
412         String JavaDoc name = "testBidirectionalWithConstraint_1a_" + System.currentTimeMillis();
413
414         Shop s1 = new Shop(name + "_1");
415         ShopDetail sd = new ShopDetail(name + "_1");
416         s1.setDetail(sd);
417         sd.setShop(s1);
418
419         TransactionExt tx = (TransactionExt) odmg.newTransaction();
420         tx.begin();
421         database.makePersistent(s1);
422         tx.commit();
423
424         tx.begin();
425         database.deletePersistent(s1);
426         tx.commit();
427     }
428
429     /**
430      * Define order of object operations using flush() method.
431      */

432     public void testBidirectionalWithConstraint_1b() throws Exception JavaDoc
433     {
434         String JavaDoc name = "testBidirectionalWithConstraint_1b_" + System.currentTimeMillis();
435         TransactionExt tx = (TransactionExt) odmg.newTransaction();
436         tx.begin();
437
438         Shop s1 = new Shop(name + "_1");
439         // when using flush() we can use the "natural" order
440
// without getting DB constraint violence.
441
database.makePersistent(s1);
442         // write to DB object without references
443
tx.flush();
444         ShopDetail sd = new ShopDetail(name + "_1");
445         // now set references
446
s1.setDetail(sd);
447         sd.setShop(s1);
448         // no need to persist the ShopDetail object
449
// (will be detected by OJB)
450
// but it doesn't matter if you do
451
// database.makePersistent(sd);
452
tx.commit();
453
454         tx.begin();
455         // madatory to mark object with DB FK constraint first on delete
456
// (FK from Shop to ShopDetail) then OJB will use this order to
457
// delete the bidirectional objects
458
database.deletePersistent(s1);
459         tx.flush();
460         database.deletePersistent(sd);
461         tx.commit();
462     }
463
464     /**
465      * If the user take care of the ordering itself the test pass.
466      */

467     public void testBidirectionalWithConstraint_1c() throws Exception JavaDoc
468     {
469         String JavaDoc name = "testBidirectionalWithConstraint_1c_" + System.currentTimeMillis();
470         TransactionExt tx = (TransactionExt) odmg.newTransaction();
471
472         Shop s1 = new Shop(name + "_1");
473         ShopDetail sd = new ShopDetail(name + "_1");
474         s1.setDetail(sd);
475         sd.setShop(s1);
476
477         // set implicit locking false to determine order of objects
478
tx.setImplicitLocking(false);
479         // to prevent reordering of object, disable ordering
480
// in many cases this is not needed, because OJB will leave ordering
481
// tx.setOrdering(false);
482
tx.begin();
483         // madatory to persist referenced ShopDetail first, the Shop
484
// object will be detected automatic. In this case first the ShopDetail
485
// will be created and then the Shop
486
database.makePersistent(sd);
487         database.makePersistent(s1);
488         tx.commit();
489
490         // we using the same tx, thus locking and (ordering) is still disabled
491
tx.begin();
492         // madatory to mark object with DB FK constraint first on delete
493
// then OJB will use this order to delete the bidirectional objects
494
database.deletePersistent(s1);
495         database.deletePersistent(sd);
496         tx.commit();
497     }
498
499     /**
500      * This test is only for comparison of ODMG- with PB-api. It's not recommended
501      * to do this in ODMG production environment.
502      *
503      * @throws Exception
504      */

505     public void testBidirectionalWithConstraint_1d_PB() throws Exception JavaDoc
506     {
507         ojbChangeReferenceSetting(Shop.class, "detail", true, ObjectReferenceDescriptor.CASCADE_OBJECT, ObjectReferenceDescriptor.CASCADE_OBJECT, false);
508         ojbChangeReferenceSetting(ShopDetail.class, "shop", true, ObjectReferenceDescriptor.CASCADE_OBJECT, ObjectReferenceDescriptor.CASCADE_OBJECT, false);
509         String JavaDoc name = "testBidirectionalWithConstraint_1a_" + System.currentTimeMillis();
510         TransactionExt tx = (TransactionExt) odmg.newTransaction();
511         tx.begin();
512
513         Shop s1 = new Shop(name + "_1");
514         ShopDetail sd = new ShopDetail(name + "_1");
515         s1.setDetail(sd);
516         sd.setShop(s1);
517
518         // only for testing, we completely bypass odmg
519
tx.getBroker().beginTransaction();
520         tx.getBroker().store(s1);
521         tx.commit();
522
523
524         tx.begin();
525         // only for testing, we completely bypass odmg
526
tx.getBroker().beginTransaction();
527         // madatory to mark object with DB FK constraint first on delete
528
// then OJB will use this order to delete the bidirectional objects
529
tx.getBroker().delete(s1);
530         tx.commit();
531     }
532
533     /**
534      * Handle circular 1:1 by using a 'constraint'-flag property in
535      * reference-descriptor to make OJB's ordering algorithm more
536      * sophisticated.
537      */

538     public void testBidirectionalWithConstraint_1e() throws Exception JavaDoc
539     {
540         String JavaDoc name = "testBidirectionalWithConstraint_1e_" + System.currentTimeMillis();
541         ObjectReferenceDescriptor ord = null;
542
543         try
544         {
545             CircularTest.Shop s1 = new CircularTest.Shop(name + "_1");
546             CircularTest.ShopDetail sd = new CircularTest.ShopDetail(name + "_1");
547             s1.setDetail(sd);
548             sd.setShop(s1);
549
550             TransactionExt tx = (TransactionExt) odmg.newTransaction();
551             tx.begin();
552             // now we tell OJB that one 1:1 reference of the bidirectional 1:1 reference
553
// between Shop and ShopDetail has a FK constraint
554
ClassDescriptor cld = tx.getBroker().getClassDescriptor(CircularTest.Shop.class);
555             ord = cld.getObjectReferenceDescriptorByName("detail");
556             // current DB schema create a foreign key constraint and we can
557
// inform OJB
558
ord.setConstraint(true);
559             // now it doesn't matter in which order we persist the new objects, OJB should
560
// always reorder the objects before insert/update call
561
database.makePersistent(sd);
562             // or
563
// database.makePersistent(s1);
564
tx.commit();
565
566             tx.begin();
567             // with cascading delete and the declared FK constraint OJB
568
// always use the correct order on delete.
569
tx.setCascadingDelete(CircularTest.ShopDetail.class, true);
570             database.deletePersistent(sd);
571             // or
572
// database.deletePersistent(s1);
573
tx.commit();
574         }
575         finally
576         {
577             // restore old setting
578
if(ord != null) ord.setConstraint(false);
579         }
580     }
581
582     /**
583      * Test show handling with circular references and database FK settings.
584      */

585     public void testCircularOneToOne_1a() throws Exception JavaDoc
586     {
587         String JavaDoc name = "testCircularOneToOne_1a_" + System.currentTimeMillis();
588
589         TransactionExt tx = (TransactionExt) odmg.newTransaction();
590         tx.begin();
591
592         ObjectA a = new ObjectA(name + "_ObjectA");
593         ObjectAA aa = new ObjectAA(name + "_ObjectAA");
594         ObjectAAA aaa = new ObjectAAA(name + "_ObjectAAA");
595         // now set the circular references
596
a.setRefAA(aa);
597         aa.setRefAAA(aaa);
598         aaa.setRefA(a);
599         database.makePersistent(a);
600         tx.commit();
601
602         tx.begin();
603         database.deletePersistent(a);
604         tx.commit();
605
606         tx.begin();
607         OQLQuery query = odmg.newOQLQuery();
608         query.create("select objects from " + ObjectA.class.getName() + " where name like $1");
609         query.bind(name + "%");
610         Collection JavaDoc result = (Collection JavaDoc) query.execute();
611         assertEquals(0, result.size());
612
613         query = odmg.newOQLQuery();
614         query.create("select objects from " + ObjectAA.class.getName() + " where name like $1");
615         query.bind(name + "%");
616         result = (Collection JavaDoc) query.execute();
617         assertEquals(1, result.size());
618
619         query = odmg.newOQLQuery();
620         query.create("select objects from " + ObjectAAA.class.getName() + " where name like $1");
621         query.bind(name + "%");
622         result = (Collection JavaDoc) query.execute();
623         assertEquals(1, result.size());
624
625         query = odmg.newOQLQuery();
626         query.create("select objects from " + ObjectAAAA.class.getName() + " where name like $1");
627         query.bind(name + "%");
628         result = (Collection JavaDoc) query.execute();
629         assertEquals(0, result.size());
630         tx.commit();
631     }
632
633     /**
634      * Test show handling with circular references and database FK settings.
635      */

636     public void testCircularOneToOne_1b() throws Exception JavaDoc
637     {
638         String JavaDoc name = "testCircularOneToOne_1b_" + System.currentTimeMillis();
639
640         TransactionExt tx = (TransactionExt) odmg.newTransaction();
641         tx.begin();
642
643         ObjectA a = new ObjectA(name + "_ObjectA");
644         ObjectAA aa = new ObjectAA(name + "_ObjectAA");
645         ObjectAAA aaa = new ObjectAAA(name + "_ObjectAAA");
646         ObjectAAAA aaaa = new ObjectAAAA(name + "_ObjectAAAA");
647         // now set the circular references
648
a.setRefAA(aa);
649         aa.setRefAAA(aaa);
650         aaa.setRefAAAA(aaaa);
651         aaaa.setRefA(a);
652         database.makePersistent(a);
653         tx.commit();
654
655         tx.begin();
656         OQLQuery query = odmg.newOQLQuery();
657         query.create("select objects from " + ObjectA.class.getName() + " where name like $1");
658         query.bind(name + "%");
659         Collection JavaDoc result = (Collection JavaDoc) query.execute();
660         assertEquals(1, result.size());
661
662         query = odmg.newOQLQuery();
663         query.create("select objects from " + ObjectAA.class.getName() + " where name like $1");
664         query.bind(name + "%");
665         result = (Collection JavaDoc) query.execute();
666         assertEquals(1, result.size());
667
668         query = odmg.newOQLQuery();
669         query.create("select objects from " + ObjectAAA.class.getName() + " where name like $1");
670         query.bind(name + "%");
671         result = (Collection JavaDoc) query.execute();
672         assertEquals(1, result.size());
673
674         query = odmg.newOQLQuery();
675         query.create("select objects from " + ObjectAAAA.class.getName() + " where name like $1");
676         query.bind(name + "%");
677         result = (Collection JavaDoc) query.execute();
678         assertEquals(1, result.size());
679         tx.commit();
680
681         tx.begin();
682         database.deletePersistent(a);
683         tx.commit();
684
685         tx.begin();
686         query = odmg.newOQLQuery();
687         query.create("select objects from " + ObjectA.class.getName() + " where name like $1");
688         query.bind(name + "%");
689         result = (Collection JavaDoc) query.execute();
690         assertEquals(0, result.size());
691
692         query = odmg.newOQLQuery();
693         query.create("select objects from " + ObjectAA.class.getName() + " where name like $1");
694         query.bind(name + "%");
695         result = (Collection JavaDoc) query.execute();
696         assertEquals(1, result.size());
697
698         query = odmg.newOQLQuery();
699         query.create("select objects from " + ObjectAAA.class.getName() + " where name like $1");
700         query.bind(name + "%");
701         result = (Collection JavaDoc) query.execute();
702         assertEquals(1, result.size());
703
704         query = odmg.newOQLQuery();
705         query.create("select objects from " + ObjectAAAA.class.getName() + " where name like $1");
706         query.bind(name + "%");
707         result = (Collection JavaDoc) query.execute();
708         assertEquals(1, result.size());
709         tx.commit();
710     }
711
712     /**
713      * Do manually ordering using {@link TransactionExt#setOrdering(boolean)} to disable
714      * OJB's ordering algorithm (and implicit locking).
715      */

716     public void testCircularOneToOne_1c() throws Exception JavaDoc
717     {
718         String JavaDoc name = "testCircularOneToOne_1d_" + System.currentTimeMillis();
719
720         TransactionExt tx = (TransactionExt) odmg.newTransaction();
721         tx.begin();
722
723         ObjectA a = new ObjectA(name + "_ObjectA");
724         ObjectAA aa = new ObjectAA(name + "_ObjectAA");
725         ObjectAAA aaa = new ObjectAAA(name + "_ObjectAAA");
726         ObjectAAAA aaaa = new ObjectAAAA(name + "_ObjectAAAA");
727         // now set the circular references
728
a.setRefAA(aa);
729         aa.setRefAAA(aaa);
730         aaa.setRefAAAA(aaaa);
731         aaaa.setRefA(a);
732
733         /*
734         we want to manually insert new object, so we disable
735         OJB's ordering and implicit object locking
736         */

737         tx.setOrdering(false);
738         tx.setImplicitLocking(false);
739
740         database.makePersistent(aaaa);
741         database.makePersistent(aaa);
742         database.makePersistent(aa);
743         database.makePersistent(a);
744         tx.commit();
745
746         tx.begin();
747         OQLQuery query = odmg.newOQLQuery();
748         query.create("select objects from " + ObjectA.class.getName() + " where name like $1");
749         query.bind(name + "%");
750         Collection JavaDoc result = (Collection JavaDoc) query.execute();
751         assertEquals(1, result.size());
752
753         query = odmg.newOQLQuery();
754         query.create("select objects from " + ObjectAA.class.getName() + " where name like $1");
755         query.bind(name + "%");
756         result = (Collection JavaDoc) query.execute();
757         assertEquals(1, result.size());
758
759         query = odmg.newOQLQuery();
760         query.create("select objects from " + ObjectAAA.class.getName() + " where name like $1");
761         query.bind(name + "%");
762         result = (Collection JavaDoc) query.execute();
763         assertEquals(1, result.size());
764
765         query = odmg.newOQLQuery();
766         query.create("select objects from " + ObjectAAAA.class.getName() + " where name like $1");
767         query.bind(name + "%");
768         result = (Collection JavaDoc) query.execute();
769         assertEquals(1, result.size());
770         tx.commit();
771
772         tx.begin();
773         /*
774         the ordering/implicit locking of the tx is still disabled (tx instance hasn't changed),
775         so we have to take care of correct order of objects while deletion
776         */

777         database.deletePersistent(a);
778         database.deletePersistent(aa);
779         database.deletePersistent(aaa);
780         database.deletePersistent(aaaa);
781         tx.commit();
782
783         tx.begin();
784         query = odmg.newOQLQuery();
785         query.create("select objects from " + ObjectA.class.getName() + " where name like $1");
786         query.bind(name + "%");
787         result = (Collection JavaDoc) query.execute();
788         assertEquals(0, result.size());
789
790         query = odmg.newOQLQuery();
791         query.create("select objects from " + ObjectAA.class.getName() + " where name like $1");
792         query.bind(name + "%");
793         result = (Collection JavaDoc) query.execute();
794         assertEquals(0, result.size());
795
796         query = odmg.newOQLQuery();
797         query.create("select objects from " + ObjectAAA.class.getName() + " where name like $1");
798         query.bind(name + "%");
799         result = (Collection JavaDoc) query.execute();
800         assertEquals(0, result.size());
801
802         query = odmg.newOQLQuery();
803         query.create("select objects from " + ObjectAAAA.class.getName() + " where name like $1");
804         query.bind(name + "%");
805         result = (Collection JavaDoc) query.execute();
806         assertEquals(0, result.size());
807         tx.commit();
808     }
809
810     /**
811      * Do manually ordering using in conjunction with OJB's ordering.
812      */

813     public void testCircularOneToOne_1dd() throws Exception JavaDoc
814     {
815         String JavaDoc name = "testCircularOneToOne_1dd_" + System.currentTimeMillis();
816
817         TransactionExt tx = (TransactionExt) odmg.newTransaction();
818         tx.begin();
819
820         ObjectA a = new ObjectA(name + "_ObjectA");
821         ObjectAA aa = new ObjectAA(name + "_ObjectAA");
822         ObjectAAA aaa = new ObjectAAA(name + "_ObjectAAA");
823         ObjectAAAA aaaa = new ObjectAAAA(name + "_ObjectAAAA");
824         // now set the circular references
825
a.setRefAA(aa);
826         aa.setRefAAA(aaa);
827         aaa.setRefAAAA(aaaa);
828         aaaa.setRefA(a);
829
830         /*
831         we manually determine the insert object order
832         */

833         tx.setOrdering(false);
834         tx.setImplicitLocking(false);
835
836         database.makePersistent(aaaa);
837         database.makePersistent(aaa);
838         database.makePersistent(aa);
839         database.makePersistent(a);
840         tx.commit();
841
842         tx.begin();
843         /*
844         the ordering/implicit locking/noteOrdering settings are still enabled
845         */

846         database.deletePersistent(a);
847         database.deletePersistent(aa);
848         database.deletePersistent(aaa);
849         database.deletePersistent(aaaa);
850         tx.commit();
851
852   &nbs