Skip to content

Commit 2e1f7b5

Browse files
committed
HHH-14918 Test entity with composite ID containing an association to another entity which itself has a composite ID containing an association to another entity
1 parent ccd58ee commit 2e1f7b5

File tree

1 file changed

+196
-0
lines changed

1 file changed

+196
-0
lines changed
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
5+
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
6+
*/
7+
package org.hibernate.test.idclass;
8+
9+
import static org.assertj.core.api.Assertions.assertThat;
10+
import static org.hibernate.test.util.SchemaUtil.getColumnNames;
11+
12+
import java.io.Serializable;
13+
import javax.persistence.Entity;
14+
import javax.persistence.Id;
15+
import javax.persistence.IdClass;
16+
import javax.persistence.ManyToOne;
17+
18+
import org.hibernate.testing.TestForIssue;
19+
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
20+
import org.junit.Test;
21+
22+
/**
23+
* Test that bootstrap doesn't throw an exception
24+
* when an entity has a composite ID containing an association to another entity,
25+
* which itself has a composite ID containing an association to another entity.
26+
* <p>
27+
* This test used to fail on bootstrap with the following error:
28+
* <p>
29+
* org.hibernate.MappingException: identifier mapping has wrong number of columns: org.hibernate.test.idclass.IdClassForNestedIdWithAssociationTest$NestedIdClassEntity type: component[idClassEntity,key3]
30+
* at org.hibernate.mapping.RootClass.validate(RootClass.java:273)
31+
* at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:359)
32+
* at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:307)
33+
* at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:471)
34+
* at org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase.buildResources(BaseNonConfigCoreFunctionalTestCase.java:165)
35+
* at org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase.startUp(BaseNonConfigCoreFunctionalTestCase.java:141)
36+
* at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
37+
* at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
38+
* at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
39+
* at java.base/java.lang.reflect.Method.invoke(Method.java:566)
40+
* at org.hibernate.testing.junit4.TestClassMetadata.performCallbackInvocation(TestClassMetadata.java:205)
41+
*/
42+
@TestForIssue(jiraKey = "HHH-14918")
43+
public class IdClassForNestedIdWithAssociationTest extends BaseNonConfigCoreFunctionalTestCase {
44+
45+
@Override
46+
protected Class<?>[] getAnnotatedClasses() {
47+
return new Class[] { BasicEntity.class, IdClassEntity.class, NestedIdClassEntity.class };
48+
}
49+
50+
@Test
51+
public void metadataTest() {
52+
assertThat( getColumnNames( "NestedIdClassEntity", metadata() ) )
53+
// Just check we're using copied IDs; otherwise the test wouldn't be able to reproduce HHH-14918.
54+
.containsExactlyInAnyOrder( "idClassEntity_basicEntity_key1", "idClassEntity_key2", "key3" );
55+
}
56+
57+
// The main goal of the test is to check that bootstrap doesn't throw an exception,
58+
// but it feels wrong to have a test class with just an empty test method,
59+
// so just check that persisting/loading works correctly.
60+
@Test
61+
public void smokeTest() {
62+
inTransaction( s -> {
63+
BasicEntity basic = new BasicEntity( 1L );
64+
s.persist( basic );
65+
IdClassEntity idClass = new IdClassEntity( basic, 2L );
66+
s.persist( idClass );
67+
NestedIdClassEntity nestedIdClass = new NestedIdClassEntity( idClass, 3L );
68+
s.persist( nestedIdClass );
69+
} );
70+
71+
inTransaction( s -> {
72+
NestedIdClassEntity nestedIdClass = s.get(
73+
NestedIdClassEntity.class,
74+
new NestedIdClassEntity.NestedIdClassEntityId( 1L, 2L, 3L )
75+
);
76+
assertThat( nestedIdClass )
77+
.extracting( NestedIdClassEntity::getKey3 )
78+
.isEqualTo( 3L );
79+
IdClassEntity idClass = nestedIdClass.getIdClassEntity();
80+
assertThat( idClass )
81+
.extracting( IdClassEntity::getKey2 )
82+
.isEqualTo( 2L );
83+
BasicEntity basic = idClass.basicEntity;
84+
assertThat( basic )
85+
.extracting( BasicEntity::getKey1 )
86+
.isEqualTo( 1L );
87+
} );
88+
}
89+
90+
@Entity(name = "BasicEntity")
91+
public static class BasicEntity {
92+
@Id
93+
Long key1;
94+
95+
protected BasicEntity() {
96+
}
97+
98+
public BasicEntity(long key1) {
99+
this.key1 = key1;
100+
}
101+
102+
public Long getKey1() {
103+
return key1;
104+
}
105+
}
106+
107+
@Entity(name = "IdClassEntity")
108+
@IdClass(IdClassEntity.IdClassEntityId.class)
109+
public static class IdClassEntity {
110+
@Id
111+
@ManyToOne
112+
BasicEntity basicEntity;
113+
@Id
114+
Long key2;
115+
116+
protected IdClassEntity() {
117+
}
118+
119+
public IdClassEntity(BasicEntity basicEntity, long key2) {
120+
this.basicEntity = basicEntity;
121+
this.key2 = key2;
122+
}
123+
124+
public BasicEntity getBasicEntity() {
125+
return basicEntity;
126+
}
127+
128+
public Long getKey2() {
129+
return key2;
130+
}
131+
132+
public static class IdClassEntityId implements Serializable {
133+
long basicEntity;
134+
long key2;
135+
136+
protected IdClassEntityId() {
137+
}
138+
139+
public IdClassEntityId(long basicEntity, long key2) {
140+
this.basicEntity = basicEntity;
141+
this.key2 = key2;
142+
}
143+
144+
public long getBasicEntity() {
145+
return basicEntity;
146+
}
147+
148+
public long getKey2() {
149+
return key2;
150+
}
151+
}
152+
}
153+
154+
@Entity(name = "NestedIdClassEntity")
155+
@IdClass(NestedIdClassEntity.NestedIdClassEntityId.class)
156+
public static class NestedIdClassEntity {
157+
@Id
158+
@ManyToOne
159+
IdClassEntity idClassEntity;
160+
@Id
161+
Long key3;
162+
163+
protected NestedIdClassEntity() {
164+
}
165+
166+
public NestedIdClassEntity(IdClassEntity idClassEntity, long key3) {
167+
this.idClassEntity = idClassEntity;
168+
this.key3 = key3;
169+
}
170+
171+
public IdClassEntity getIdClassEntity() {
172+
return idClassEntity;
173+
}
174+
175+
public Long getKey3() {
176+
return key3;
177+
}
178+
179+
public static class NestedIdClassEntityId implements Serializable {
180+
IdClassEntity.IdClassEntityId idClassEntity;
181+
long key3;
182+
183+
protected NestedIdClassEntityId() {
184+
}
185+
186+
public NestedIdClassEntityId(IdClassEntity.IdClassEntityId idClassEntity, long key3) {
187+
this.idClassEntity = idClassEntity;
188+
this.key3 = key3;
189+
}
190+
191+
public NestedIdClassEntityId(long basicEntity, long key2, long key3) {
192+
this( new IdClassEntity.IdClassEntityId( basicEntity, key2 ), key3 );
193+
}
194+
}
195+
}
196+
}

0 commit comments

Comments
 (0)