|
14 | 14 | import org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl;
|
15 | 15 | import org.hibernate.cfg.Configuration;
|
16 | 16 |
|
| 17 | +import org.hibernate.testing.orm.junit.Jira; |
17 | 18 | import org.hibernate.testing.orm.junit.JiraKey;
|
18 | 19 | import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
19 | 20 | import org.junit.Test;
|
@@ -78,6 +79,41 @@ public void testCriteriaRestrictionOnIdManyToOne() {
|
78 | 79 | } );
|
79 | 80 | }
|
80 | 81 |
|
| 82 | + @Test |
| 83 | + @Jira("https://hibernate.atlassian.net/browse/HHH-11026") |
| 84 | + public void testMerge() { |
| 85 | + inTransaction( s-> { |
| 86 | + Student student = new Student(); |
| 87 | + student.setName( "s1" ); |
| 88 | + Course course = new Course(); |
| 89 | + course.setName( "c1" ); |
| 90 | + s.persist( student ); |
| 91 | + s.persist( course ); |
| 92 | + |
| 93 | + CourseStudent courseStudent = new CourseStudent(); |
| 94 | + courseStudent.setStudent( student ); |
| 95 | + courseStudent.setCourse( course ); |
| 96 | + student.getCourses().add( courseStudent ); |
| 97 | + course.getStudents().add( courseStudent ); |
| 98 | + s.merge( student ); |
| 99 | + |
| 100 | + // Merge will cascade Student#courses and replace the CourseStudent instance within, |
| 101 | + // but the original CourseStudent is still contained in Student#courses that will be cascaded on flush, |
| 102 | + // which is when the NonUniqueObjectException is thrown, because at that point, |
| 103 | + // two CourseStudent objects with the same primary key exist. |
| 104 | + // This can be worked around by replacing the original CourseStudent with the merged on as hinted below, |
| 105 | + // but I'm not sure if copying the CourseStudent instance on merge really makes sense, |
| 106 | + // since the load for the merge showed that there is no row for that key in the database. |
| 107 | + // I tried avoiding the copy in org.hibernate.event.internal.DefaultMergeEventListener#copyEntity |
| 108 | + // which also required updating the child-parent state in StatefulPersistenceContext to point to |
| 109 | + // the new parent according to the MergeContext. This mostly worked, but required further investigation |
| 110 | + // to fix a few failing tests. This copy on merge topic needs to be discussed further before continuing. |
| 111 | + |
| 112 | +// course.getStudents().remove( courseStudent ); |
| 113 | +// course.getStudents().add( student.getCourses().iterator().next() ); |
| 114 | + } ); |
| 115 | + } |
| 116 | + |
81 | 117 | @Override
|
82 | 118 | protected Class[] getAnnotatedClasses() {
|
83 | 119 | return new Class[] {
|
|
0 commit comments