|
6 | 6 | */ |
7 | 7 | package org.hibernate.test.annotations.onetomany; |
8 | 8 |
|
9 | | -import javax.persistence.PersistenceException; |
10 | 9 | import java.util.ArrayList; |
11 | 10 | import java.util.Collection; |
| 11 | +import java.util.Collections; |
12 | 12 | import java.util.HashSet; |
13 | 13 | import java.util.Iterator; |
14 | 14 | import java.util.List; |
15 | 15 | import java.util.Set; |
16 | 16 | import java.util.SortedSet; |
17 | 17 | import java.util.TreeSet; |
| 18 | +import javax.persistence.CascadeType; |
| 19 | +import javax.persistence.Entity; |
| 20 | +import javax.persistence.GeneratedValue; |
| 21 | +import javax.persistence.Id; |
| 22 | +import javax.persistence.JoinColumn; |
| 23 | +import javax.persistence.OneToMany; |
| 24 | +import javax.persistence.PersistenceException; |
18 | 25 |
|
| 26 | +import org.hibernate.AnnotationException; |
19 | 27 | import org.hibernate.Hibernate; |
20 | | -import org.hibernate.HibernateException; |
21 | 28 | import org.hibernate.Session; |
22 | 29 | import org.hibernate.Transaction; |
| 30 | +import org.hibernate.annotations.OnDelete; |
| 31 | +import org.hibernate.annotations.OnDeleteAction; |
| 32 | +import org.hibernate.boot.MetadataSources; |
| 33 | +import org.hibernate.boot.registry.StandardServiceRegistry; |
| 34 | +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; |
23 | 35 | import org.hibernate.exception.ConstraintViolationException; |
24 | 36 | import org.hibernate.mapping.Column; |
25 | 37 | import org.hibernate.mapping.PersistentClass; |
|
36 | 48 | import org.junit.Test; |
37 | 49 |
|
38 | 50 | import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; |
| 51 | +import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; |
39 | 52 | import static org.junit.Assert.assertEquals; |
40 | 53 | import static org.junit.Assert.assertFalse; |
41 | 54 | import static org.junit.Assert.assertNotNull; |
@@ -345,6 +358,46 @@ public void testCascadeDelete() throws Exception { |
345 | 358 | s.close(); |
346 | 359 | } |
347 | 360 |
|
| 361 | +@Test |
| 362 | +public void testCascadeDeleteWithUnidirectionalAssociation() throws Exception { |
| 363 | +OnDeleteUnidirectionalOneToManyChild child = new OnDeleteUnidirectionalOneToManyChild(); |
| 364 | + |
| 365 | +doInHibernate( this::sessionFactory, session -> { |
| 366 | +OnDeleteUnidirectionalOneToManyParent parent = new OnDeleteUnidirectionalOneToManyParent(); |
| 367 | +parent.children = Collections.singletonList( child); |
| 368 | +session.persist( parent ); |
| 369 | +} ); |
| 370 | + |
| 371 | +doInHibernate( this::sessionFactory, session -> { |
| 372 | +session.createQuery("delete from OnDeleteUnidirectionalOneToManyParent").executeUpdate(); |
| 373 | +} ); |
| 374 | + |
| 375 | +doInHibernate( this::sessionFactory, session -> { |
| 376 | +OnDeleteUnidirectionalOneToManyChild e1 = session.get( OnDeleteUnidirectionalOneToManyChild.class, child.id ); |
| 377 | +assertNull( "delete cascade should work", e1 ); |
| 378 | +} ); |
| 379 | +} |
| 380 | + |
| 381 | +@Test |
| 382 | +public void testOnDeleteWithoutJoinColumn() throws Exception { |
| 383 | +StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() |
| 384 | +.build(); |
| 385 | + |
| 386 | +try { |
| 387 | +new MetadataSources( serviceRegistry ) |
| 388 | +.addAnnotatedClass( OnDeleteUnidirectionalOneToMany.class ) |
| 389 | +.addAnnotatedClass( ParentUnawareChild.class ) |
| 390 | +.getMetadataBuilder() |
| 391 | +.build(); |
| 392 | +} |
| 393 | +catch ( AnnotationException e ) { |
| 394 | +assertTrue(e.getMessage().contains( "Unidirectional one-to-many associations annotated with @OnDelete must define @JoinColumn" )); |
| 395 | +} |
| 396 | +finally { |
| 397 | +StandardServiceRegistryBuilder.destroy( serviceRegistry ); |
| 398 | +} |
| 399 | +} |
| 400 | + |
348 | 401 | @Test |
349 | 402 | public void testSimpleOneToManySet() throws Exception { |
350 | 403 | Session s; |
@@ -503,12 +556,53 @@ protected Class[] getAnnotatedClasses() { |
503 | 556 | Person.class, |
504 | 557 | Organisation.class, |
505 | 558 | OrganisationUser.class, |
506 | | -Model.class |
| 559 | +Model.class, |
| 560 | +OnDeleteUnidirectionalOneToManyParent.class, |
| 561 | +OnDeleteUnidirectionalOneToManyChild.class |
507 | 562 | }; |
508 | 563 | } |
509 | 564 |
|
510 | 565 | @Override |
511 | 566 | protected String[] getXmlFiles() { |
512 | 567 | return new String[] { "org/hibernate/test/annotations/onetomany/orm.xml" }; |
513 | 568 | } |
| 569 | + |
| 570 | +@Entity(name = "OnDeleteUnidirectionalOneToManyParent") |
| 571 | +public static class OnDeleteUnidirectionalOneToManyParent { |
| 572 | + |
| 573 | +@Id |
| 574 | +@GeneratedValue |
| 575 | +Long id; |
| 576 | + |
| 577 | +@OneToMany(cascade = CascadeType.ALL) |
| 578 | +@JoinColumn(name = "a_id") |
| 579 | +@OnDelete(action = OnDeleteAction.CASCADE) |
| 580 | +List<OnDeleteUnidirectionalOneToManyChild> children; |
| 581 | +} |
| 582 | + |
| 583 | +@Entity(name = "OnDeleteUnidirectionalOneToManyChild") |
| 584 | +public static class OnDeleteUnidirectionalOneToManyChild { |
| 585 | + |
| 586 | +@Id |
| 587 | +@GeneratedValue |
| 588 | +Long id; |
| 589 | +} |
| 590 | + |
| 591 | +@Entity(name = "OnDeleteUnidirectionalOneToMany") |
| 592 | +public static class OnDeleteUnidirectionalOneToMany { |
| 593 | + |
| 594 | +@Id |
| 595 | +Long id; |
| 596 | + |
| 597 | +@OneToMany(cascade = CascadeType.ALL) |
| 598 | +@OnDelete(action = OnDeleteAction.CASCADE) |
| 599 | +List<ParentUnawareChild> children; |
| 600 | +} |
| 601 | + |
| 602 | +@Entity(name = "ParentUnawareChild") |
| 603 | +public static class ParentUnawareChild { |
| 604 | + |
| 605 | +@Id |
| 606 | +Long id; |
| 607 | +} |
514 | 608 | } |
0 commit comments