|
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