Skip to content

Commit 851c0fd

Browse files
committed
HHH-18839 Validate property type of @IdClass at bind time
1 parent d5e829d commit 851c0fd

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

hibernate-core/src/main/java/org/hibernate/boot/model/internal/EmbeddableBinder.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -835,8 +835,9 @@ private static void processIdClassElements(
835835

836836
for ( int i = 0; i < classElements.size(); i++ ) {
837837
final PropertyData idClassPropertyData = classElements.get( i );
838+
final String propertyName = idClassPropertyData.getPropertyName();
838839
final PropertyData entityPropertyData =
839-
baseClassElementsByName.get( idClassPropertyData.getPropertyName() );
840+
baseClassElementsByName.get( propertyName );
840841
if ( propertyHolder.isInIdClass() ) {
841842
if ( entityPropertyData == null ) {
842843
throw new AnnotationException(
@@ -852,6 +853,13 @@ private static void processIdClassElements(
852853
//the annotation overriding will be dealt with by a mechanism similar to @MapsId
853854
continue;
854855
}
856+
if ( !idClassPropertyData.getTypeName().equals( entityPropertyData.getTypeName() ) ) {
857+
throw new AnnotationException(
858+
"Property '" + propertyName + "' in @IdClass '" + idClassPropertyData.getDeclaringClass()
859+
+ "' doesn't match type in entity class '" + baseInferredData.getPropertyType().getName()
860+
+ "' (expected '" + entityPropertyData.getTypeName() + "' but was '" + idClassPropertyData.getTypeName() + "')"
861+
);
862+
}
855863
}
856864
classElements.set( i, entityPropertyData ); //this works since they are in the same order
857865
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* SPDX-License-Identifier: LGPL-2.1-or-later
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.annotations.cid;
6+
7+
import jakarta.persistence.Entity;
8+
import jakarta.persistence.Id;
9+
import jakarta.persistence.IdClass;
10+
import org.hibernate.AnnotationException;
11+
import org.hibernate.boot.MetadataSources;
12+
import org.hibernate.boot.registry.StandardServiceRegistry;
13+
import org.hibernate.testing.util.ServiceRegistryUtil;
14+
import org.junit.jupiter.api.Test;
15+
16+
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
17+
18+
19+
/**
20+
* @author Yanming Zhou
21+
*/
22+
public class CompositeIdTypeMismatchTest {
23+
24+
@Test
25+
public void test() {
26+
try ( StandardServiceRegistry ssr = ServiceRegistryUtil.serviceRegistryBuilder().build() ) {
27+
final MetadataSources metadataSources = new MetadataSources( ssr );
28+
metadataSources.addAnnotatedClass( TestEntity.class );
29+
assertThatExceptionOfType( AnnotationException.class).isThrownBy( metadataSources::buildMetadata ).withMessageContaining( "doesn't match type" );
30+
}
31+
}
32+
33+
@IdClass(TestEntity.ID.class)
34+
@Entity
35+
static class TestEntity {
36+
37+
@Id
38+
String code;
39+
40+
41+
@Id
42+
Integer type;
43+
44+
record ID(String code, String type) {
45+
46+
}
47+
}
48+
}

0 commit comments

Comments
 (0)