HHH-13295 Test @EmbeddedId + @MapsId targeting a derived entity
This commit is contained in:
parent
7906a27b6a
commit
88a0afc8e2
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.test.ecid;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hibernate.test.util.SchemaUtil.getColumnNames;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.MapsId;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Test that bootstrap doesn't throw an exception
|
||||
* when an entity has an {@link EmbeddedId} and a {@link MapsId} that references a derived identity.
|
||||
* <p>
|
||||
* This test used to fail on bootstrap with the following error:
|
||||
* <p>
|
||||
* java.util.NoSuchElementException
|
||||
* at java.base/java.util.ArrayList$Itr.next(ArrayList.java:1000)
|
||||
* at org.hibernate.cfg.annotations.TableBinder.linkJoinColumnWithValueOverridingNameIfImplicit(TableBinder.java:714)
|
||||
* at org.hibernate.cfg.PkDrivenByDefaultMapsIdSecondPass.doSecondPass(PkDrivenByDefaultMapsIdSecondPass.java:37)
|
||||
* at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1693)
|
||||
* at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1650)
|
||||
* at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:295)
|
||||
* at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.build(MetadataBuildingProcess.java:86)
|
||||
* at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:479)
|
||||
* at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:85)
|
||||
* at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:709)
|
||||
* at org.hibernate.testing.junit4.BaseCoreFunctionalTestCase.buildSessionFactory(BaseCoreFunctionalTestCase.java:125)
|
||||
* at org.hibernate.testing.junit4.BaseCoreFunctionalTestCase.buildSessionFactory(BaseCoreFunctionalTestCase.java:110)
|
||||
* at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
|
||||
* at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
|
||||
* at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
|
||||
* at java.base/java.lang.reflect.Method.invoke(Method.java:566)
|
||||
* at org.hibernate.testing.junit4.TestClassMetadata.performCallbackInvocation(TestClassMetadata.java:205)
|
||||
*/
|
||||
@TestForIssue(jiraKey = "HHH-13295")
|
||||
public class EmbeddedIdWithMapsIdTargetingDerivedEntityTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { Attendance.class, AttendanceId.class, Lecture.class, Student.class, User.class };
|
||||
}
|
||||
|
||||
@Test
|
||||
public void metadataTest() {
|
||||
assertThat( getColumnNames( "attendance", metadata() ) )
|
||||
// Just check we're using @MapsId; otherwise the test wouldn't be able to reproduce HHH-13295.
|
||||
.containsExactlyInAnyOrder( "student_id", "lecture_id" );
|
||||
}
|
||||
|
||||
// The main goal of the test is to check that bootstrap doesn't throw an exception,
|
||||
// but it feels wrong to have a test class with just an empty test method,
|
||||
// so just check that persisting/loading works correctly.
|
||||
@Test
|
||||
public void smokeTest() {
|
||||
inTransaction( s -> {
|
||||
Lecture lecture = new Lecture( 1L );
|
||||
s.persist( lecture );
|
||||
Student student = new Student( 2L );
|
||||
s.persist( student );
|
||||
Attendance attendance = new Attendance( lecture, student );
|
||||
student.getAttendances().add( attendance );
|
||||
lecture.getAttendances().add( attendance );
|
||||
s.persist( attendance );
|
||||
} );
|
||||
|
||||
inTransaction( s -> {
|
||||
Attendance attendance = s.get( Attendance.class, new AttendanceId( 1L, 2L ) );
|
||||
assertThat( attendance.getId() )
|
||||
.extracting( AttendanceId::getLectureId )
|
||||
.isEqualTo( 1L );
|
||||
assertThat( attendance.getId() )
|
||||
.extracting( AttendanceId::getStudentId )
|
||||
.isEqualTo( 2L );
|
||||
assertThat( attendance.getLecture() )
|
||||
.extracting( Lecture::getId )
|
||||
.isEqualTo( 1L );
|
||||
assertThat( attendance.getStudent() )
|
||||
.extracting( Student::getId )
|
||||
.isEqualTo( 2L );
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "attendance")
|
||||
public static class Attendance {
|
||||
@EmbeddedId
|
||||
private AttendanceId id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@MapsId("lectureId")
|
||||
private Lecture lecture;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@MapsId("studentId")
|
||||
private Student student;
|
||||
|
||||
Attendance() {
|
||||
}
|
||||
|
||||
public Attendance(Lecture lecture, Student student) {
|
||||
this.id = new AttendanceId( lecture.getId(), student.getId() );
|
||||
this.lecture = lecture;
|
||||
this.student = student;
|
||||
}
|
||||
|
||||
public AttendanceId getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Lecture getLecture() {
|
||||
return lecture;
|
||||
}
|
||||
|
||||
public Student getStudent() {
|
||||
return student;
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class AttendanceId implements Serializable {
|
||||
@Column
|
||||
private Long lectureId;
|
||||
|
||||
@Column
|
||||
private Long studentId;
|
||||
|
||||
AttendanceId() {
|
||||
}
|
||||
|
||||
public AttendanceId(Long lectureId, Long studentId) {
|
||||
this.lectureId = lectureId;
|
||||
this.studentId = studentId;
|
||||
}
|
||||
|
||||
public Long getLectureId() {
|
||||
return lectureId;
|
||||
}
|
||||
|
||||
public Long getStudentId() {
|
||||
return studentId;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "users")
|
||||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
public static abstract class User {
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
User() {
|
||||
}
|
||||
|
||||
public User(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "student")
|
||||
public static class Student extends User {
|
||||
@OneToMany(mappedBy = "student", fetch = FetchType.LAZY)
|
||||
private List<Attendance> attendances = new ArrayList<>();
|
||||
|
||||
Student() {
|
||||
}
|
||||
|
||||
public Student(Long id) {
|
||||
super( id );
|
||||
}
|
||||
|
||||
public List<Attendance> getAttendances() {
|
||||
return attendances;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "lecture")
|
||||
public static class Lecture {
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
@OneToMany(mappedBy = "lecture", fetch = FetchType.LAZY)
|
||||
private List<Attendance> attendances = new ArrayList<>();
|
||||
|
||||
Lecture() {
|
||||
}
|
||||
|
||||
public Lecture(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public List<Attendance> getAttendances() {
|
||||
return attendances;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue