HHH-17300 detect and throw exception for @Table annotation on @MappedSuperclass (#7422)

+ very minor misc code cleanups
This commit is contained in:
Gavin King 2023-10-10 15:05:24 +02:00 committed by GitHub
parent 5bab35eb96
commit e323ec3d4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 54 deletions

View File

@ -12,7 +12,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import jakarta.persistence.FetchType;
import org.hibernate.AnnotationException;
import org.hibernate.MappingException;
import org.hibernate.annotations.CollectionTypeRegistration;
@ -74,6 +73,7 @@ import org.hibernate.usertype.UserType;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.persistence.MappedSuperclass;
@ -87,6 +87,7 @@ import jakarta.persistence.SequenceGenerator;
import jakarta.persistence.SequenceGenerators;
import jakarta.persistence.SqlResultSetMapping;
import jakarta.persistence.SqlResultSetMappings;
import jakarta.persistence.Table;
import jakarta.persistence.TableGenerator;
import jakarta.persistence.TableGenerators;
@ -433,47 +434,52 @@ public final class AnnotationBinder {
}
private static void detectMappedSuperclassProblems(XClass annotatedClass) {
if ( annotatedClass.isAnnotationPresent( MappedSuperclass.class ) ) {
//@Entity and @MappedSuperclass on the same class leads to a NPE down the road
if ( annotatedClass.isAnnotationPresent( Entity.class )
&& annotatedClass.isAnnotationPresent( MappedSuperclass.class ) ) {
throw new AnnotationException( "Type '"+ annotatedClass.getName()
if ( annotatedClass.isAnnotationPresent( Entity.class ) ) {
throw new AnnotationException( "Type '" + annotatedClass.getName()
+ "' is annotated both '@Entity' and '@MappedSuperclass'" );
}
if ( annotatedClass.isAnnotationPresent( Inheritance.class )
&& annotatedClass.isAnnotationPresent( MappedSuperclass.class ) ) {
if ( annotatedClass.isAnnotationPresent( Table.class ) ) {
throw new AnnotationException( "Mapped superclass '" + annotatedClass.getName()
+ "' may not specify a '@Table'" );
}
if ( annotatedClass.isAnnotationPresent( Inheritance.class ) ) {
LOG.unsupportedMappedSuperclassWithEntityInheritance( annotatedClass.getName() );
}
}
}
private static void bindTypeDescriptorRegistrations(XAnnotatedElement annotatedElement, MetadataBuildingContext context) {
final ManagedBeanRegistry managedBeanRegistry = context.getBootstrapContext()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class );
final JavaTypeRegistration javaTypeRegistration = annotatedElement.getAnnotation( JavaTypeRegistration.class );
final JavaTypeRegistration javaTypeRegistration =
annotatedElement.getAnnotation( JavaTypeRegistration.class );
if ( javaTypeRegistration != null ) {
handleJavaTypeRegistration( context, managedBeanRegistry, javaTypeRegistration );
}
else {
final JavaTypeRegistrations javaTypeRegistrations = annotatedElement.getAnnotation( JavaTypeRegistrations.class );
final JavaTypeRegistrations javaTypeRegistrations =
annotatedElement.getAnnotation( JavaTypeRegistrations.class );
if ( javaTypeRegistrations != null ) {
final JavaTypeRegistration[] registrations = javaTypeRegistrations.value();
for ( JavaTypeRegistration registration : registrations ) {
for ( JavaTypeRegistration registration : javaTypeRegistrations.value() ) {
handleJavaTypeRegistration( context, managedBeanRegistry, registration );
}
}
}
final JdbcTypeRegistration jdbcTypeRegistration = annotatedElement.getAnnotation( JdbcTypeRegistration.class );
final JdbcTypeRegistration jdbcTypeRegistration =
annotatedElement.getAnnotation( JdbcTypeRegistration.class );
if ( jdbcTypeRegistration != null ) {
handleJdbcTypeRegistration( context, managedBeanRegistry, jdbcTypeRegistration );
}
else {
final JdbcTypeRegistrations jdbcTypeRegistrations = annotatedElement.getAnnotation( JdbcTypeRegistrations.class );
final JdbcTypeRegistrations jdbcTypeRegistrations =
annotatedElement.getAnnotation( JdbcTypeRegistrations.class );
if ( jdbcTypeRegistrations != null ) {
final JdbcTypeRegistration[] registrations = jdbcTypeRegistrations.value();
for ( JdbcTypeRegistration registration : registrations ) {
for ( JdbcTypeRegistration registration : jdbcTypeRegistrations.value() ) {
handleJdbcTypeRegistration( context, managedBeanRegistry, registration );
}
}
@ -499,15 +505,9 @@ public final class AnnotationBinder {
ManagedBeanRegistry managedBeanRegistry,
JdbcTypeRegistration annotation) {
final Class<? extends JdbcType> jdbcTypeClass = annotation.value();
final JdbcType jdbcType;
if ( context.getBuildingOptions().disallowExtensionsInCdi() ) {
jdbcType = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( jdbcTypeClass );
}
else {
jdbcType = managedBeanRegistry.getBean( jdbcTypeClass ).getBeanInstance();
}
final JdbcType jdbcType = context.getBuildingOptions().disallowExtensionsInCdi()
? FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( jdbcTypeClass )
: managedBeanRegistry.getBean( jdbcTypeClass ).getBeanInstance();
final int typeCode = annotation.registrationCode() == Integer.MIN_VALUE
? jdbcType.getDefaultSqlTypeCode()
: annotation.registrationCode();
@ -519,14 +519,10 @@ public final class AnnotationBinder {
ManagedBeanRegistry managedBeanRegistry,
JavaTypeRegistration annotation) {
final Class<? extends BasicJavaType<?>> javaTypeClass = annotation.descriptorClass();
final BasicJavaType<?> javaType;
if ( context.getBuildingOptions().disallowExtensionsInCdi() ) {
javaType = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( javaTypeClass );
}
else {
javaType = managedBeanRegistry.getBean( javaTypeClass ).getBeanInstance();
}
final BasicJavaType<?> javaType =
context.getBuildingOptions().disallowExtensionsInCdi()
? FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( javaTypeClass )
: managedBeanRegistry.getBean( javaTypeClass ).getBeanInstance();
context.getMetadataCollector().addJavaTypeRegistration( annotation.javaType(), javaType );
}
@ -542,8 +538,7 @@ public final class AnnotationBinder {
final EmbeddableInstantiatorRegistrations embeddableInstantiatorRegistrations =
annotatedElement.getAnnotation( EmbeddableInstantiatorRegistrations.class );
if ( embeddableInstantiatorRegistrations != null ) {
final EmbeddableInstantiatorRegistration[] registrations = embeddableInstantiatorRegistrations.value();
for ( EmbeddableInstantiatorRegistration registration : registrations ) {
for ( EmbeddableInstantiatorRegistration registration : embeddableInstantiatorRegistrations.value() ) {
handleEmbeddableInstantiatorRegistration( context, registration );
}
}
@ -571,8 +566,7 @@ public final class AnnotationBinder {
final CompositeTypeRegistrations compositeTypeRegistrations =
annotatedElement.getAnnotation( CompositeTypeRegistrations.class );
if ( compositeTypeRegistrations != null ) {
final CompositeTypeRegistration[] registrations = compositeTypeRegistrations.value();
for ( CompositeTypeRegistration registration : registrations ) {
for ( CompositeTypeRegistration registration : compositeTypeRegistrations.value() ) {
handleCompositeUserTypeRegistration( context, registration );
}
}
@ -591,8 +585,7 @@ public final class AnnotationBinder {
final TypeRegistrations typeRegistrations =
annotatedElement.getAnnotation( TypeRegistrations.class );
if ( typeRegistrations != null ) {
final TypeRegistration[] registrations = typeRegistrations.value();
for ( TypeRegistration registration : registrations ) {
for ( TypeRegistration registration : typeRegistrations.value() ) {
handleUserTypeRegistration( context, registration );
}
}
@ -625,17 +618,16 @@ public final class AnnotationBinder {
final ConverterRegistration converterRegistration = container.getAnnotation( ConverterRegistration.class );
if ( converterRegistration != null ) {
handleConverterRegistration( converterRegistration, context );
return;
}
else {
final ConverterRegistrations converterRegistrations = container.getAnnotation( ConverterRegistrations.class );
if ( converterRegistrations != null ) {
final ConverterRegistration[] registrations = converterRegistrations.value();
for ( ConverterRegistration registration : registrations ) {
for ( ConverterRegistration registration : converterRegistrations.value() ) {
handleConverterRegistration( registration, context );
}
}
}
}
private static void handleConverterRegistration(ConverterRegistration registration, MetadataBuildingContext context) {
final InFlightMetadataCollector metadataCollector = context.getMetadataCollector();

View File

@ -12,6 +12,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import jakarta.persistence.MappedSuperclass;
import org.hibernate.annotations.common.reflection.MetadataProviderInjector;
import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XClass;
@ -266,7 +267,7 @@ public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProc
// order the hierarchy
List<XClass> workingCopy = new ArrayList<>( copy );
List<XClass> newList = new ArrayList<>( copy.size() );
while ( workingCopy.size() > 0 ) {
while ( !workingCopy.isEmpty() ) {
XClass clazz = workingCopy.get( 0 );
orderHierarchy( workingCopy, newList, copy, clazz );
}
@ -276,7 +277,7 @@ public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProc
private void insertMappedSuperclasses(List<XClass> original, List<XClass> copy) {
final boolean debug = log.isDebugEnabled();
for ( XClass clazz : original ) {
if ( clazz.isAnnotationPresent( jakarta.persistence.MappedSuperclass.class ) ) {
if ( clazz.isAnnotationPresent( MappedSuperclass.class ) ) {
if ( debug ) {
log.debugf(
"Skipping explicit MappedSuperclass %s, the class will be discovered analyzing the implementing class",
@ -291,7 +292,7 @@ public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProc
&& !reflectionManager.equals( superClass, Object.class )
&& !copy.contains( superClass ) ) {
if ( superClass.isAnnotationPresent( Entity.class )
|| superClass.isAnnotationPresent( jakarta.persistence.MappedSuperclass.class ) ) {
|| superClass.isAnnotationPresent( MappedSuperclass.class ) ) {
copy.add( superClass );
}
superClass = superClass.getSuperclass();

View File

@ -9,13 +9,11 @@ package org.hibernate.orm.test.jpa.criteria.idclass;
import jakarta.persistence.Id;
import jakarta.persistence.IdClass;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.Table;
/**
* @author Erich Heard
*/
@MappedSuperclass
@Table( name = "HELPER" )
@IdClass( HelperId.class )
public class Helper {
@Id