KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > test > hql > BulkManipulationTest


1 // $Id: BulkManipulationTest.java,v 1.33 2005/07/20 19:36:02 steveebersole Exp $
2
package org.hibernate.test.hql;
3
4 import java.util.List JavaDoc;
5 import java.util.Date JavaDoc;
6
7 import junit.framework.Test;
8 import junit.framework.TestSuite;
9
10 import org.hibernate.Transaction;
11 import org.hibernate.QueryException;
12 import org.hibernate.hql.ast.HqlSqlWalker;
13 import org.hibernate.id.IdentifierGenerator;
14 import org.hibernate.persister.entity.EntityPersister;
15 import org.hibernate.engine.SessionFactoryImplementor;
16 import org.hibernate.classic.Session;
17 import org.hibernate.dialect.HSQLDialect;
18 import org.hibernate.test.TestCase;
19
20
21 /**
22  * Tests execution of bulk UPDATE/DELETE statements through the new AST parser.
23  *
24  * @author Steve Ebersole
25  */

26 public class BulkManipulationTest extends TestCase {
27
28     public BulkManipulationTest(String JavaDoc name) {
29         super( name );
30     }
31
32     public static Test suite() {
33         return new TestSuite( BulkManipulationTest.class );
34     }
35
36     protected String JavaDoc[] getMappings() {
37         return new String JavaDoc[] {
38             "hql/Animal.hbm.xml",
39             "hql/Vehicle.hbm.xml",
40             "hql/KeyManyToOneEntity.hbm.xml",
41             "hql/Versions.hbm.xml"
42         };
43     }
44
45
46     // INSERTS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
47

48     public void testDeleteNonExistentEntity() {
49         Session s = openSession();
50         Transaction t = s.beginTransaction();
51
52         try {
53             s.createQuery( "delete NonExistentEntity" ).executeUpdate();
54             fail( "no exception thrown" );
55         }
56         catch( QueryException e ) {
57             System.out.println( "Caught expected error type : " + e.getMessage() );
58         }
59
60         t.commit();
61         s.close();
62     }
63
64     public void testUpdateNonExistentEntity() {
65         Session s = openSession();
66         Transaction t = s.beginTransaction();
67
68         try {
69             s.createQuery( "update NonExistentEntity e set e.someProp = ?" ).executeUpdate();
70             fail( "no exception thrown" );
71         }
72         catch( QueryException e ) {
73             System.out.println( "Caught expected error type : " + e.getMessage() );
74         }
75
76         t.commit();
77         s.close();
78     }
79
80     public void testSimpleInsert() {
81         TestData data = new TestData();
82         data.prepare();
83
84         Session s = openSession();
85         Transaction t = s.beginTransaction();
86
87         s.createQuery( "insert into Pickup (id, vin, owner) select id, vin, owner from Car" ).executeUpdate();
88
89         t.commit();
90         t = s.beginTransaction();
91
92         s.createQuery( "delete Vehicle" ).executeUpdate();
93
94         t.commit();
95         s.close();
96
97         data.cleanup();
98     }
99
100     public void testInsertWithMismatchedTypes() {
101         TestData data = new TestData();
102         data.prepare();
103
104         Session s = openSession();
105         Transaction t = s.beginTransaction();
106         try {
107             s.createQuery( "insert into Pickup (owner, vin, id) select id, vin, owner from Car" ).executeUpdate();
108             fail( "mismatched types did not error" );
109         }
110         catch( QueryException e ) {
111             // expected result
112
}
113
114         t.commit();
115         t = s.beginTransaction();
116
117         s.createQuery( "delete Vehicle" ).executeUpdate();
118
119         t.commit();
120         s.close();
121
122         data.cleanup();
123     }
124
125     public void testInsertIntoSuperclassPropertiesFails() {
126         TestData data = new TestData();
127         data.prepare();
128
129         Session s = openSession();
130         Transaction t = s.beginTransaction();
131
132         try {
133             s.createQuery( "insert into Human (id, bodyWeight) select id, bodyWeight from Lizard" ).executeUpdate();
134             fail( "superclass prop insertion did not error" );
135         }
136         catch( QueryException e ) {
137             // expected result
138
}
139
140         t.commit();
141         t = s.beginTransaction();
142
143         s.createQuery( "delete Animal where mother is not null" ).executeUpdate();
144         s.createQuery( "delete Animal" ).executeUpdate();
145
146         t.commit();
147         s.close();
148
149         data.cleanup();
150     }
151
152     public void testInsertAcrossMappedJoinFails() {
153         TestData data = new TestData();
154         data.prepare();
155
156         Session s = openSession();
157         Transaction t = s.beginTransaction();
158
159         try {
160             s.createQuery( "insert into Joiner (name, joinedName) select vin, owner from Car" ).executeUpdate();
161             fail( "mapped-join insertion did not error" );
162         }
163         catch( QueryException e ) {
164             // expected result
165
}
166
167         t.commit();
168         t = s.beginTransaction();
169
170         s.createQuery( "delete Joiner" ).executeUpdate();
171         s.createQuery( "delete Vehicle" ).executeUpdate();
172
173         t.commit();
174         s.close();
175
176         data.cleanup();
177     }
178
179     public void testInsertWithGeneratedId() {
180         // Make sure the env supports bulk inserts with generated ids...
181
EntityPersister persister = sfi().getEntityPersister( PettingZoo.class.getName() );
182         IdentifierGenerator generator = persister.getIdentifierGenerator();
183         if ( !HqlSqlWalker.supportsIdGenWithBulkInsertion( generator ) ) {
184             return;
185         }
186
187         // create a Zoo
188
Zoo zoo = new Zoo();
189         zoo.setName( "zoo" );
190
191         Session s = openSession();
192         Transaction t = s.beginTransaction();
193         s.save( zoo );
194         t.commit();
195         s.close();
196
197         s = openSession();
198         t = s.beginTransaction();
199         int count = s.createQuery( "insert into PettingZoo (name) select name from Zoo" ).executeUpdate();
200         t.commit();
201         s.close();
202
203         assertEquals( "unexpected insertion count", 1, count );
204
205         s = openSession();
206         t = s.beginTransaction();
207         PettingZoo pz = ( PettingZoo ) s.createQuery( "from PettingZoo" ).uniqueResult();
208         t.commit();
209         s.close();
210
211         assertEquals( zoo.getName(), pz.getName() );
212         assertTrue( zoo.getId() != pz.getId() );
213
214         s = openSession();
215         t = s.beginTransaction();
216         s.createQuery( "delete Zoo" ).executeUpdate();
217         t.commit();
218         s.close();
219     }
220
221     public void testInsertWithGeneratedVersionAndId() {
222         // Make sure the env supports bulk inserts with generated ids...
223
EntityPersister persister = sfi().getEntityPersister( IntegerVersioned.class.getName() );
224         IdentifierGenerator generator = persister.getIdentifierGenerator();
225         if ( !HqlSqlWalker.supportsIdGenWithBulkInsertion( generator ) ) {
226             return;
227         }
228
229         Session s = openSession();
230         Transaction t = s.beginTransaction();
231
232         IntegerVersioned entity = new IntegerVersioned( "int-vers" );
233         s.save( entity );
234         s.createQuery( "select id, name, version from IntegerVersioned" ).list();
235         t.commit();
236         s.close();
237
238         Long JavaDoc initialId = entity.getId();
239         int initialVersion = entity.getVersion();
240
241         s = openSession();
242         t = s.beginTransaction();
243         int count = s.createQuery( "insert into IntegerVersioned ( name ) select name from IntegerVersioned" ).executeUpdate();
244         t.commit();
245         s.close();
246
247         assertEquals( "unexpected insertion count", 1, count );
248
249         s = openSession();
250         t = s.beginTransaction();
251         IntegerVersioned created = ( IntegerVersioned ) s.createQuery( "from IntegerVersioned where id <> :initialId" )
252                 .setLong( "initialId", initialId.longValue() )
253                 .uniqueResult();
254         t.commit();
255         s.close();
256
257         assertEquals( "version was not seeded", initialVersion, created.getVersion() );
258
259         s = openSession();
260         t = s.beginTransaction();
261         s.createQuery( "delete IntegerVersioned" ).executeUpdate();
262         t.commit();
263         s.close();
264     }
265
266     public void testInsertWithGeneratedTimestampVersion() {
267
268     }
269
270     // UPDATES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
271

272     public void testIncrementCounterVersion() {
273         Session s = openSession();
274         Transaction t = s.beginTransaction();
275
276         IntegerVersioned entity = new IntegerVersioned( "int-vers" );
277         s.save( entity );
278         t.commit();
279         s.close();
280
281         int initialVersion = entity.getVersion();
282
283         s = openSession();
284         t = s.beginTransaction();
285         int count = s.createQuery( "update versioned IntegerVersioned set name = name" ).executeUpdate();
286         assertEquals( "incorrect exec count", 1, count );
287         t.commit();
288
289         t = s.beginTransaction();
290         entity = ( IntegerVersioned ) s.load( IntegerVersioned.class, entity.getId() );
291         assertEquals( "version not incremented", initialVersion + 1, entity.getVersion() );
292
293         s.delete( entity );
294         t.commit();
295         s.close();
296     }
297
298     public void testIncrementTimestampVersion() {
299         Session s = openSession();
300         Transaction t = s.beginTransaction();
301
302         TimestampVersioned entity = new TimestampVersioned( "ts-vers" );
303         s.save( entity );
304         t.commit();
305         s.close();
306
307         Date JavaDoc initialVersion = entity.getVersion();
308         
309         synchronized (this) {
310             try {
311                 wait(300);
312             }
313             catch (InterruptedException JavaDoc ie) {}
314         }
315
316         s = openSession();
317         t = s.beginTransaction();
318         int count = s.createQuery( "update versioned TimestampVersioned set name = name" ).executeUpdate();
319         assertEquals( "incorrect exec count", 1, count );
320         t.commit();
321
322         t = s.beginTransaction();
323         entity = ( TimestampVersioned ) s.load( TimestampVersioned.class, entity.getId() );
324         assertTrue( "version not incremented", entity.getVersion().after( initialVersion ) );
325
326         s.delete( entity );
327         t.commit();
328         s.close();
329     }
330
331     public void testUpdateOnComponent() {
332         Session s = openSession();
333         Transaction t = s.beginTransaction();
334
335         Human human = new Human();
336         human.setName( new Name() );
337         human.getName().setFirst("Stevee");
338         human.getName().setInitial('X');
339         human.getName().setLast("Ebersole");
340
341         s.save( human );
342         s.flush();
343
344         t.commit();
345
346         String JavaDoc correctName = "Steve";
347
348         t = s.beginTransaction();
349
350         int count = s.createQuery( "update Human set name.first = :correction where id = :id" )
351                 .setString( "correction", correctName )
352                 .setLong( "id", human.getId().longValue() )
353                 .executeUpdate();
354
355         assertEquals( "Incorrect update count", 1, count );
356
357         t.commit();
358
359         t = s.beginTransaction();
360
361         s.refresh( human );
362
363         assertEquals( "Update did not execute properly", correctName, human.getName().getFirst() );
364
365         s.createQuery( "delete Human" ).executeUpdate();
366         t.commit();
367
368         s.close();
369     }
370
371     public void testUpdateOnImplicitJoinFails() {
372         Session s = openSession();
373         Transaction t = s.beginTransaction();
374
375         Human human = new Human();
376         human.setName( new Name() );
377         human.getName().setFirst( "Steve" );
378
379         Human mother = new Human();
380         mother.setName( new Name() );
381         mother.getName().setFirst( "Jane" );
382         human.setMother( mother );
383
384         s.save( human );
385         s.save( mother );
386         s.flush();
387
388         t.commit();
389
390         t = s.beginTransaction();
391         try {
392             s.createQuery( "update Human set mother.name.initial = :initial" ).setString( "initial", "F" ).executeUpdate();
393             fail( "update allowed across implicit join" );
394         }
395         catch( QueryException e ) {
396             System.out.println( "TEST (OK) : " + e.getMessage() );
397             // expected condition
398
}
399
400         s.createQuery( "delete Human where mother is not null" ).executeUpdate();
401         s.createQuery( "delete Human" ).executeUpdate();
402         t.commit();
403         s.close();
404     }
405
406     public void testUpdateOnDiscriminatorSubclass() {
407         TestData data = new TestData();
408         data.prepare();
409
410         Session s = openSession();
411         Transaction t = s.beginTransaction();
412
413         int count = s.createQuery( "update PettingZoo set name = name" ).executeUpdate();
414         assertEquals( "Incorrect discrim subclass update count", 1, count );
415
416         t.rollback();
417         t = s.beginTransaction();
418
419         count = s.createQuery( "update PettingZoo pz set pz.name = pz.name where pz.id = :id" )
420                 .setLong( "id", data.pettingZoo.getId().longValue() )
421                 .executeUpdate();
422         assertEquals( "Incorrect discrim subclass update count", 1, count );
423
424         t.rollback();
425         t = s.beginTransaction();
426
427         count = s.createQuery( "update Zoo as z set z.name = z.name" ).executeUpdate();
428         assertEquals( "Incorrect discrim subclass update count", 2, count );
429
430         t.rollback();
431         t = s.beginTransaction();
432
433         // TODO : not so sure this should be allowed. Seems to me that if they specify an alias,
434
// property-refs should be required to be qualified.
435
count = s.createQuery( "update Zoo as z set name = name where id = :id" )
436                 .setLong( "id", data.zoo.getId().longValue() )
437                 .executeUpdate();
438         assertEquals( "Incorrect discrim subclass update count", 1, count );
439
440         t.commit();
441         s.close();
442
443         data.cleanup();
444     }
445
446     public void testUpdateOnAnimal() {
447         TestData data = new TestData();
448         data.prepare();
449
450         Session s = openSession();
451         Transaction t = s.beginTransaction();
452         int count = s.createQuery( "update Animal set description = description where description = :desc" )
453                 .setString( "desc", data.frog.getDescription() )
454                 .executeUpdate();
455         assertEquals( "Incorrect entity-updated count", 1, count );
456
457         count = s.createQuery( "update Animal set description = :newDesc where description = :desc" )
458                 .setString( "desc", data.polliwog.getDescription() )
459                 .setString( "newDesc", "Tadpole" )
460                 .executeUpdate();
461         assertEquals( "Incorrect entity-updated count", 1, count );
462
463         Animal tadpole = ( Animal ) s.load( Animal.class, data.polliwog.getId() );
464         assertEquals( "Update did not take effect", "Tadpole", tadpole.getDescription() );
465
466         count = s.createQuery( "update Animal set bodyWeight = bodyWeight + :w1 + :w2" )
467                 .setDouble( "w1", 1 )
468                 .setDouble( "w2", 2 )
469                 .executeUpdate();
470         assertEquals( "incorrect count on 'complex' update assignment", count, 6 );
471
472         count = s.createQuery( "update Animal set bodyWeight = ( select max(bodyWeight) from Animal )" )
473             .executeUpdate();
474         
475         t.commit();
476         s.close();
477
478         data.cleanup();
479     }
480
481     public void testUpdateOnMammal() {
482         TestData data = new TestData();
483         data.prepare();
484
485         Session s = openSession();
486         Transaction t = s.beginTransaction();
487
488         int count = s.createQuery( "update Mammal set description = description" ).executeUpdate();
489         assertEquals( "incorrect update count against 'middle' of joined-subclass hierarchy", 2, count );
490
491         t.commit();
492         s.close();
493
494         data.cleanup();
495     }
496
497
498     // DELETES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
499

500     public void testSimpleDeleteOnAnimal() {
501         if ( getDialect().hasSelfReferentialForeignKeyBug() || getDialect() instanceof HSQLDialect ) {
502             // This test fails on Hypersonic because there is a bug in HSQL where
503
// you cannot perform a bulk delete against a table with a self-referential
504
// association
505
return;
506         }
507
508         TestData data = new TestData();
509         data.prepare();
510
511         Session s = openSession();
512         Transaction t = s.beginTransaction();
513
514         int count = s.createQuery( "delete from Animal as a where a.id = :id" )
515                 .setLong( "id", data.polliwog.getId().longValue() )
516                 .executeUpdate();
517         assertEquals( "Incorrect delete count", 1, count );
518
519         count = s.createQuery( "delete Animal a" ).executeUpdate();
520         assertEquals( "Incorrect delete count", 5, count );
521
522         List JavaDoc list = s.createQuery( "select a from Animal as a" ).list();
523         assertTrue( "table not empty", list.isEmpty() );
524
525         t.commit();
526         s.close();
527         data.cleanup();
528     }
529
530     public void testDeleteOnDiscriminatorSubclass() {
531         TestData data = new TestData();
532         data.prepare();
533
534         Session s = openSession();
535         Transaction t = s.beginTransaction();
536
537         int count = s.createQuery( "delete PettingZoo" ).executeUpdate();
538         assertEquals( "Incorrect discrim subclass delete count", 1, count );
539
540         count = s.createQuery( "delete Zoo" ).executeUpdate();
541         assertEquals( "Incorrect discrim subclass delete count", 1, count );
542
543         t.commit();
544         s.close();
545
546         data.cleanup();
547     }
548
549     public void testDeleteOnJoinedSubclass() {
550         TestData data = new TestData();
551         data.prepare();
552
553         Session s = openSession();
554         Transaction t = s.beginTransaction();
555
556         int count = s.createQuery( "delete Mammal where bodyWeight > 150" ).executeUpdate();
557         assertEquals( "Incorrect deletion count on joined subclass", 1, count );
558
559         count = s.createQuery( "delete Mammal" ).executeUpdate();
560         assertEquals( "Incorrect deletion count on joined subclass", 1, count );
561
562         t.commit();
563         s.close();
564
565         data.cleanup();
566     }
567
568     public void testDeleteOnMappedJoin() {
569         TestData data = new TestData();
570         data.prepare();
571
572         Session s = openSession();
573         Transaction t = s.beginTransaction();
574
575         int count = s.createQuery( "delete Joiner where joinedName = :joinedName" ).setString( "joinedName", "joined-name" ).executeUpdate();
576         assertEquals( "Incorrect deletion count on joined subclass", 1, count );
577
578         t.commit();
579         s.close();
580
581         data.cleanup();
582     }
583
584     public void testDeleteUnionSubclassAbstractRoot() {
585         TestData data = new TestData();
586         data.prepare();
587
588         // These should reach out into *all* subclass tables...
589
Session s = openSession();
590         Transaction t = s.beginTransaction();
591
592         int count = s.createQuery( "delete Vehicle where owner = :owner" ).setString( "owner", "Steve" ).executeUpdate();
593         assertEquals( "incorrect restricted update count", 1, count );
594
595         count = s.createQuery( "delete Vehicle" ).executeUpdate();
596         assertEquals( "incorrect update count", 3, count );
597         t.commit();
598         s.close();
599
600         data.cleanup();
601     }
602
603     public void testDeleteUnionSubclassConcreteSubclass() {
604         TestData data = new TestData();
605         data.prepare();
606
607         // These should only affect the given table
608
Session s = openSession();
609         Transaction t = s.beginTransaction();
610
611         int count = s.createQuery( "delete Truck where owner = :owner" ).setString( "owner", "Steve" ).executeUpdate();
612         assertEquals( "incorrect restricted update count", 1, count );
613
614         count = s.createQuery( "delete Truck" ).executeUpdate();
615         assertEquals( "incorrect update count", 2, count );
616         t.commit();
617         s.close();
618
619         data.cleanup();
620     }
621
622     public void testDeleteUnionSubclassLeafSubclass() {
623         TestData data = new TestData();
624         data.prepare();
625
626         // These should only affect the given table
627
Session s = openSession();
628         Transaction t = s.beginTransaction();
629
630         int count = s.createQuery( "delete Car where owner = :owner" ).setString( "owner", "Kirsten" ).executeUpdate();
631         assertEquals( "incorrect restricted update count", 1, count );
632
633         count = s.createQuery( "delete Car" ).executeUpdate();
634         assertEquals( "incorrect update count", 0, count );
635         t.commit();
636         s.close();
637
638         data.cleanup();
639     }
640
641     private class TestData {
642
643         private Animal polliwog;
644         private Animal catepillar;
645         private Animal frog;
646         private Animal butterfly;
647
648         private Zoo zoo;
649         private Zoo pettingZoo;
650
651         private void prepare() {
652             Session s = openSession();
653             Transaction txn = s.beginTransaction();
654
655             polliwog = new Animal();
656             polliwog.setBodyWeight( 12 );
657             polliwog.setDescription( "Polliwog" );
658
659             catepillar = new Animal();
660             catepillar.setBodyWeight( 10 );
661             catepillar.setDescription( "Catepillar" );
662
663             frog = new Animal();
664             frog.setBodyWeight( 34 );
665             frog.setDescription( "Frog" );
666
667             polliwog.setFather( frog );
668             frog.addOffspring( polliwog );
669
670             butterfly = new Animal();
671             butterfly.setBodyWeight( 9 );
672             butterfly.setDescription( "Butterfly" );
673
674             catepillar.setMother( butterfly );
675             butterfly.addOffspring( catepillar );
676
677             s.save( frog );
678             s.save( polliwog );
679             s.save( butterfly );
680             s.save( catepillar );
681
682             Dog dog = new Dog();
683             dog.setBodyWeight( 200 );
684             dog.setDescription( "dog" );
685             s.save( dog );
686
687             Cat cat = new Cat();
688             cat.setBodyWeight( 100 );
689             cat.setDescription( "cat" );
690             s.save( cat );
691
692             zoo = new Zoo();
693             zoo.setName( "Zoo" );
694             pettingZoo = new PettingZoo();
695             pettingZoo.setName( "Petting Zoo" );
696
697             s.save( zoo );
698             s.save( pettingZoo );
699
700             Joiner joiner = new Joiner();
701             joiner.setJoinedName( "joined-name" );
702             joiner.setName( "name" );
703             s.save( joiner );
704
705             Car car = new Car();
706             car.setVin( "123c" );
707             car.setOwner( "Kirsten" );
708             s.save( car );
709
710             Truck truck = new Truck();
711             truck.setVin( "123t" );
712             truck.setOwner( "Steve" );
713             s.save( truck );
714
715             SUV suv = new SUV();
716             suv.setVin( "123s" );
717             suv.setOwner( "Joe" );
718             s.save( suv );
719
720             Pickup pickup = new Pickup();
721             pickup.setVin( "123p" );
722             pickup.setOwner( "Cecelia" );
723             s.save( pickup );
724
725             txn.commit();
726             s.close();
727         }
728
729         private void cleanup() {
730             Session s = openSession();
731             Transaction txn = s.beginTransaction();
732
733             s.createQuery("delete from Animal where mother is not null or father is not null").executeUpdate();
734             String JavaDoc[] entityNames = new String JavaDoc[] { "Animal", "Zoo", "Joiner", "Vehicle" };
735             for ( int i = 0; i < entityNames.length; i++ ) {
736                 s.createQuery( "delete from " + entityNames[i] ).executeUpdate();
737             }
738
739             txn.commit();
740             s.close();
741         }
742     }
743
744     private SessionFactoryImplementor sfi() {
745         return ( SessionFactoryImplementor ) getSessions();
746     }
747 }
748
Popular Tags