Skip to content

Commit ec7db94

Browse files
committed
HHH-19574 fix metamodel population for nested entity classes
1 parent f07a6f4 commit ec7db94

File tree

3 files changed

+81
-26
lines changed

3 files changed

+81
-26
lines changed

hibernate-core/src/main/java/org/hibernate/metamodel/internal/InjectionHelper.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99
import org.hibernate.boot.query.NamedQueryDefinition;
1010
import org.hibernate.internal.CoreLogging;
1111
import org.hibernate.internal.CoreMessageLogger;
12+
import org.hibernate.internal.util.ReflectHelper;
1213
import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor;
1314

1415
import java.lang.reflect.Field;
1516

1617
import static java.lang.Character.charCount;
1718
import static java.lang.Character.isJavaIdentifierPart;
19+
import static java.lang.reflect.Modifier.isPublic;
1820

1921
public class InjectionHelper {
2022
private static final CoreMessageLogger log = CoreLogging.messageLogger( MetadataContext.class );
@@ -69,14 +71,16 @@ public static void injectField(
6971
? metamodelClass.getField( name )
7072
: metamodelClass.getDeclaredField( name );
7173
try {
72-
// should be public anyway, but to be sure...
73-
// ReflectHelper.ensureAccessibility( field );
74+
if ( !isPublic( metamodelClass.getModifiers() ) ) {
75+
ReflectHelper.ensureAccessibility( field );
76+
}
7477
field.set( null, model);
7578
}
7679
catch (IllegalAccessException e) {
7780
// todo : exception type?
7881
throw new AssertionFailure(
79-
"Unable to inject static metamodel attribute : " + metamodelClass.getName() + '#' + name,
82+
"Unable to inject attribute '" + name
83+
+ "' of static metamodel class '" + metamodelClass.getName() + "'",
8084
e
8185
);
8286
}

hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,6 @@ public Map<String, IdentifiableDomainType<?>> getIdentifiableTypesByName() {
263263
Property property,
264264
IdentifiableDomainType<X> entityType,
265265
BiFunction<IdentifiableDomainType<X>, Property, PersistentAttribute<X, ?>> factoryFunction) {
266-
final PersistentAttribute<X, ?> attribute;
267266
final Component component = property.getValue() instanceof Component comp ? comp : null;
268267
if ( component != null && component.isGeneric() ) {
269268
// This is an embeddable property that uses generics, we have to retrieve the generic
@@ -273,22 +272,22 @@ public Map<String, IdentifiableDomainType<?>> getIdentifiableTypesByName() {
273272
final Property genericProperty = property.copy();
274273
genericProperty.setValue( genericComponent );
275274
genericProperty.setGeneric( true );
276-
attribute = factoryFunction.apply( entityType, genericProperty );
275+
final PersistentAttribute<X, ?> attribute = factoryFunction.apply( entityType, genericProperty );
277276
if ( !property.isGeneric() ) {
278277
final PersistentAttribute<X, ?> concreteAttribute = factoryFunction.apply( entityType, property );
279278
if ( concreteAttribute != null ) {
280-
@SuppressWarnings("unchecked") final AttributeContainer<X> attributeContainer = (AttributeContainer<X>) entityType;
279+
@SuppressWarnings("unchecked")
280+
final AttributeContainer<X> attributeContainer = (AttributeContainer<X>) entityType;
281281
attributeContainer.getInFlightAccess().addConcreteGenericAttribute( concreteAttribute );
282282
}
283283
}
284+
return attribute;
284285
}
285286
else {
286-
attribute = factoryFunction.apply( entityType, property );
287+
return factoryFunction.apply( entityType, property );
287288
}
288-
return attribute;
289289
}
290290

291-
@SuppressWarnings("unchecked")
292291
public void wrapUp() {
293292
if ( log.isTraceEnabled() ) {
294293
log.trace( "Wrapping up metadata context..." );
@@ -306,8 +305,7 @@ public void wrapUp() {
306305
log.trace( "Starting entity [" + safeMapping.getEntityName() + ']' );
307306
}
308307
try {
309-
final EntityDomainType<Object> jpaMapping = (EntityDomainType<Object>)
310-
entityTypesByPersistentClass.get( safeMapping );
308+
final EntityDomainType<?> jpaMapping = entityTypesByPersistentClass.get( safeMapping );
311309

312310
applyIdMetadata( safeMapping, jpaMapping );
313311
applyVersionAttribute( safeMapping, jpaMapping );
@@ -345,8 +343,7 @@ else if ( MappedSuperclass.class.isAssignableFrom( mapping.getClass() ) ) {
345343
log.trace( "Starting mapped superclass [" + safeMapping.getMappedClass().getName() + ']' );
346344
}
347345
try {
348-
final MappedSuperclassDomainType<Object> jpaType = (MappedSuperclassDomainType<Object>)
349-
mappedSuperclassByMappedSuperclassMapping.get( safeMapping );
346+
final var jpaType = mappedSuperclassByMappedSuperclassMapping.get( safeMapping );
350347

351348
applyIdMetadata( safeMapping, jpaType );
352349
applyVersionAttribute( safeMapping, jpaType );
@@ -446,7 +443,7 @@ private <T> void buildAttribute(Property property, IdentifiableDomainType<T> jpa
446443
final PersistentAttribute<T, ?> attribute =
447444
buildAttribute( property, jpaType, attributeFactory::buildAttribute );
448445
if ( attribute != null ) {
449-
addAttribute(jpaType, attribute );
446+
addAttribute( jpaType, attribute );
450447
if ( property.isNaturalIdentifier() ) {
451448
@SuppressWarnings("unchecked")
452449
final AttributeContainer<T> attributeContainer = (AttributeContainer<T>) jpaType;
@@ -684,8 +681,9 @@ private MappedSuperclass getMappedSuperclass(PersistentClass persistentClass) {
684681
}
685682

686683
private MappedSuperclass getMappedSuperclass(MappedSuperclass mappedSuperclass) {
687-
return mappedSuperclass.getSuperMappedSuperclass() != null
688-
? mappedSuperclass.getSuperMappedSuperclass()
684+
final MappedSuperclass superMappedSuperclass = mappedSuperclass.getSuperMappedSuperclass();
685+
return superMappedSuperclass != null
686+
? superMappedSuperclass
689687
: getMappedSuperclass( mappedSuperclass.getSuperPersistentClass() );
690688
}
691689

@@ -700,19 +698,18 @@ private Property getMappedSuperclassProperty(String propertyName, MappedSupercla
700698
}
701699
}
702700

703-
final Property property = getMappedSuperclassProperty(
704-
propertyName,
705-
mappedSuperclass.getSuperMappedSuperclass()
706-
);
701+
final Property property =
702+
getMappedSuperclassProperty( propertyName,
703+
mappedSuperclass.getSuperMappedSuperclass() );
707704
if ( property != null ) {
708705
return property;
709706
}
710-
711-
if ( mappedSuperclass.getSuperPersistentClass() != null ) {
707+
else if ( mappedSuperclass.getSuperPersistentClass() != null ) {
712708
return mappedSuperclass.getSuperPersistentClass().getProperty( propertyName );
713709
}
714-
715-
return null;
710+
else {
711+
return null;
712+
}
716713
}
717714

718715
private <X> Set<SingularPersistentAttribute<? super X, ?>> buildIdClassAttributes(
@@ -721,7 +718,7 @@ private Property getMappedSuperclassProperty(String propertyName, MappedSupercla
721718
if ( log.isTraceEnabled() ) {
722719
log.trace( "Building old-school composite identifier [" + ownerType.getJavaType().getName() + ']' );
723720
}
724-
Set<SingularPersistentAttribute<? super X, ?>> attributes = new HashSet<>();
721+
final Set<SingularPersistentAttribute<? super X, ?>> attributes = new HashSet<>();
725722
for ( Property property : properties ) {
726723
attributes.add( attributeFactory.buildIdAttribute( ownerType, property ) );
727724
}
@@ -761,7 +758,13 @@ private static <X> void injectManagedType(ManagedDomainType<X> managedType, Clas
761758
}
762759

763760
private static String metamodelClassName(ManagedDomainType<?> managedTypeClass) {
764-
return managedTypeClass.getJavaType().getName() + '_';
761+
return metamodelClassName( managedTypeClass.getJavaType() );
762+
}
763+
764+
private static String metamodelClassName(Class<?> javaType) {
765+
return javaType.isMemberClass()
766+
? metamodelClassName( javaType.getEnclosingClass() ) + "$" + javaType.getSimpleName() + "_"
767+
: javaType.getName() + '_';
765768
}
766769

767770
public Class<?> metamodelClass(ManagedDomainType<?> managedDomainType) {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.metamodel.inner;
6+
7+
import jakarta.persistence.Entity;
8+
import jakarta.persistence.Id;
9+
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
10+
import org.hibernate.testing.orm.junit.Jpa;
11+
import org.junit.jupiter.api.Test;
12+
13+
import static org.junit.jupiter.api.Assertions.assertEquals;
14+
import static org.junit.jupiter.api.Assertions.assertFalse;
15+
import static org.junit.jupiter.api.Assertions.assertNotNull;
16+
import static org.junit.jupiter.api.Assertions.assertTrue;
17+
18+
@Jpa(annotatedClasses = InnerEntityMetamodelTest.Inner.class)
19+
class InnerEntityMetamodelTest {
20+
@Test void test(EntityManagerFactoryScope scope) {
21+
scope.getEntityManagerFactory();
22+
var innerName = InnerEntityMetamodelTest_.Inner_.name;
23+
assertNotNull(innerName);
24+
assertEquals("name", innerName.getName());
25+
assertEquals(String.class, innerName.getType().getJavaType());
26+
assertTrue(innerName.isOptional());
27+
assertFalse(innerName.isId());
28+
assertFalse(innerName.isVersion());
29+
assertFalse(innerName.isAssociation());
30+
assertFalse(innerName.isCollection());
31+
var innerId = InnerEntityMetamodelTest_.Inner_.id;
32+
assertNotNull(innerId);
33+
assertEquals("id", innerId.getName());
34+
assertEquals(long.class, innerId.getType().getJavaType());
35+
assertTrue(innerId.isId());
36+
assertFalse(innerId.isOptional());
37+
var metatype = InnerEntityMetamodelTest_.Inner_.class_;
38+
assertNotNull(metatype);
39+
assertEquals("InnerEntity", metatype.getName());
40+
assertEquals( 2, metatype.getAttributes().size() );
41+
assertEquals( Inner.class, metatype.getJavaType() );
42+
}
43+
@Entity(name="InnerEntity")
44+
static class Inner {
45+
@Id long id;
46+
String name;
47+
}
48+
}

0 commit comments

Comments
 (0)