* When applied to a Map-valued attribute, describes the Map value. Use
diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/ManyToAny.java b/hibernate-core/src/main/java/org/hibernate/annotations/ManyToAny.java
index 44683411c0..524133cb55 100644
--- a/hibernate-core/src/main/java/org/hibernate/annotations/ManyToAny.java
+++ b/hibernate-core/src/main/java/org/hibernate/annotations/ManyToAny.java
@@ -7,7 +7,6 @@
package org.hibernate.annotations;
import java.lang.annotation.Retention;
-import jakarta.persistence.Column;
import jakarta.persistence.FetchType;
import static java.lang.annotation.ElementType.FIELD;
@@ -15,8 +14,9 @@ import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
- * This is the collection-valued form of @Any definitions. Defines a ToMany-style association pointing
- * to one of several entity types depending on a local discriminator.
+ * Declares a many-valued association targeting one of several entity types,
+ * depending on a local discriminator column. This is the collection-valued
+ * form of {@link Any}.
*
* @see Any
*
@@ -27,10 +27,14 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
public @interface ManyToAny {
/**
- * Defines whether the value of the field or property should be lazily loaded or must be
- * eagerly fetched. The EAGER strategy is a requirement on the persistence provider runtime
- * that the value must be eagerly fetched. The LAZY strategy is applied when bytecode
- * enhancement is used. If not specified, defaults to EAGER.
+ * Specifies whether the value of the field or property should be fetched
+ * lazily or eagerly:
+ *
+ * {@link FetchType#EAGER}, the default, requires that the association
+ * be fetched immediately, but
+ * {@link FetchType#LAZY} is a hint which has no effect unless bytecode
+ * enhancement is enabled.
+ *
*/
FetchType fetch() default FetchType.EAGER;
}
diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/Type.java b/hibernate-core/src/main/java/org/hibernate/annotations/Type.java
index f13dae636c..266d0ce8c5 100644
--- a/hibernate-core/src/main/java/org/hibernate/annotations/Type.java
+++ b/hibernate-core/src/main/java/org/hibernate/annotations/Type.java
@@ -15,9 +15,9 @@ import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
- * Applies a custom {@link UserType} for the column mapping
- *
- * Generally, mutually exclusive with the compositional approach of
+ * Specifies a custom {@link UserType} for the annotated attribute mapping.
+ *
+ * This is usually mutually exclusive with the compositional approach of
* {@link JavaType}, {@link JdbcType}, etc.
*/
@java.lang.annotation.Target({METHOD, FIELD})
@@ -25,16 +25,15 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
public @interface Type {
/**
- * The custom type implementor class
+ * The implementation class which implements {@link UserType}.
*/
Class extends UserType>> value();
/**
- * Parameters to be injected into the custom type after
- * it is instantiated.
- *
- * The type should implement {@link org.hibernate.usertype.ParameterizedType}
- * to receive the parameters
+ * Parameters to be injected into the custom type after it is
+ * instantiated. The {@link UserType} implementation must implement
+ * {@link org.hibernate.usertype.ParameterizedType} to receive the
+ * parameters.
*/
Parameter[] parameters() default {};
}
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java
index c70cc4cbee..0eb29c9179 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java
@@ -114,8 +114,9 @@ import jakarta.persistence.Entity;
import jakarta.persistence.MapsId;
/**
- * The implementation of the in-flight Metadata collector contract.
- *
+ * The implementation of the {@linkplain InFlightMetadataCollector in-flight
+ * metadata collector contract}.
+ *
* The usage expectation is that this class is used until all Metadata info is
* collected and then {@link #buildMetadataInstance} is called to generate
* the complete (and immutable) Metadata object.
@@ -161,7 +162,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
private final Set defaultNamedNativeQueryNames = new HashSet<>();
private final Set defaultSqlResultSetMappingNames = new HashSet<>();
private final Set defaultNamedProcedureNames = new HashSet<>();
- private Map mappedSuperClasses;
+ private Map, MappedSuperclass> mappedSuperClasses;
private Map> propertiesAnnotatedWithMapsId;
private Map> propertiesAnnotatedWithIdAndToOne;
private Map mappedByResolver;
@@ -1845,24 +1846,21 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
Map> isADependencyOf,
String startTable,
String currentTable) {
-
Set dependencies = isADependencyOf.get( currentTable );
-
- // bottom out
- if ( dependencies == null || dependencies.size() == 0 ) {
- return;
- }
-
- for ( FkSecondPass sp : dependencies ) {
- String dependentTable = sp.getValue().getTable().getQualifiedTableName().render();
- if ( dependentTable.compareTo( startTable ) == 0 ) {
- throw new AnnotationException( "Foreign key circularity dependency involving the following tables: " + startTable + ", " + dependentTable );
- }
- buildRecursiveOrderedFkSecondPasses( orderedFkSecondPasses, isADependencyOf, startTable, dependentTable );
- if ( !orderedFkSecondPasses.contains( sp ) ) {
- orderedFkSecondPasses.add( 0, sp );
+ if ( dependencies != null ) {
+ for ( FkSecondPass sp : dependencies ) {
+ String dependentTable = sp.getValue().getTable().getQualifiedTableName().render();
+ if ( dependentTable.compareTo( startTable ) == 0 ) {
+ throw new AnnotationException( "Circular foreign key dependency involving tables '"
+ + startTable + "' and '" + dependentTable + "'" );
+ }
+ buildRecursiveOrderedFkSecondPasses( orderedFkSecondPasses, isADependencyOf, startTable, dependentTable );
+ if ( !orderedFkSecondPasses.contains( sp ) ) {
+ orderedFkSecondPasses.add( 0, sp );
+ }
}
}
+ // else bottom out
}
private void processEndOfQueue(List endOfQueueFkSecondPasses) {
@@ -2177,7 +2175,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
sb.append( columnName ).append( ", " );
}
sb.setLength( sb.length() - 2 );
- sb.append( ") on table " ).append( table.getName() ).append( ": database column " );
+ sb.append( ") on table '" ).append( table.getName() ).append( "' since the column " );
for ( Column column : unbound ) {
sb.append("'").append( column.getName() ).append( "', " );
}
@@ -2185,7 +2183,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
sb.append("'").append( column.getName() ).append( "', " );
}
sb.setLength( sb.length() - 2 );
- sb.append( " not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)" );
+ sb.append( " was not found (specify the correct column name, which depends on the naming strategy, and may not be the same as the entity property name)" );
throw new AnnotationException( sb.toString() );
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java
index a2a76e3d44..0652adfc53 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java
@@ -449,7 +449,7 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
throw new AnnotationException(
String.format(
Locale.ROOT,
- "`%s` should specify either `%s` or `%s` - %s",
+ "'%s' should specify either '%s' or '%s' (was '%s')",
AvailableSettings.DEFAULT_LIST_SEMANTICS,
java.util.List.class.getName(),
java.util.Collection.class.getName(),
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java
index f059000be9..8b443c1538 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java
@@ -79,7 +79,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
private final Map entityBindingMap;
private final List composites;
- private final Map mappedSuperclassMap;
+ private final Map, MappedSuperclass> mappedSuperclassMap;
private final Map collectionBindingMap;
private final Map typeDefinitionMap;
private final Map filterDefinitionMap;
@@ -99,7 +99,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
MetadataBuildingOptions metadataBuildingOptions,
Map entityBindingMap,
List composites,
- Map mappedSuperclassMap,
+ Map, MappedSuperclass> mappedSuperclassMap,
Map collectionBindingMap,
Map typeDefinitionMap,
Map filterDefinitionMap,
@@ -398,29 +398,40 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
final ConfigurationService cfgService = sessionFactoryServiceRegistry.getService( ConfigurationService.class );
final ClassLoaderService classLoaderService = sessionFactoryServiceRegistry.getService( ClassLoaderService.class );
- for ( Map.Entry,?> entry : ( (Map, ?>) cfgService.getSettings() ).entrySet() ) {
- if ( !(entry.getKey() instanceof String) ) {
- continue;
- }
- final String propertyName = (String) entry.getKey();
- if ( ! propertyName.startsWith( AvailableSettings.EVENT_LISTENER_PREFIX ) ) {
- continue;
- }
- final String eventTypeName = propertyName.substring( AvailableSettings.EVENT_LISTENER_PREFIX.length() + 1 );
- final EventType eventType = EventType.resolveEventTypeByName( eventTypeName );
- final EventListenerGroup eventListenerGroup = eventListenerRegistry.getEventListenerGroup( eventType );
- for ( String listenerImpl : LISTENER_SEPARATION_PATTERN.split( ( (String) entry.getValue() ) ) ) {
- eventListenerGroup.appendListener( instantiate( listenerImpl, classLoaderService ) );
+ for ( Map.Entry entry : cfgService.getSettings().entrySet() ) {
+ final String propertyName = entry.getKey();
+ if ( propertyName.startsWith( AvailableSettings.EVENT_LISTENER_PREFIX ) ) {
+ final String eventTypeName = propertyName.substring( AvailableSettings.EVENT_LISTENER_PREFIX.length() + 1 );
+ final EventType> eventType = EventType.resolveEventTypeByName( eventTypeName );
+ final String listeners = (String) entry.getValue();
+ appendListeners( eventListenerRegistry, classLoaderService, listeners, eventType );
}
}
}
- private Object instantiate(String listenerImpl, ClassLoaderService classLoaderService) {
+ private void appendListeners(
+ EventListenerRegistry eventListenerRegistry,
+ ClassLoaderService classLoaderService,
+ String listeners,
+ EventType eventType) {
+ final EventListenerGroup eventListenerGroup = eventListenerRegistry.getEventListenerGroup( eventType );
+ for ( String listenerImpl : LISTENER_SEPARATION_PATTERN.split( listeners ) ) {
+ @SuppressWarnings("unchecked")
+ T listener = (T) instantiate( listenerImpl, classLoaderService );
+ if ( !eventType.baseListenerInterface().isInstance( listener ) ) {
+ throw new HibernateException( "Event listener '" + listenerImpl + "' must implement '"
+ + eventType.baseListenerInterface().getName() + "'");
+ }
+ eventListenerGroup.appendListener( listener );
+ }
+ }
+
+ private static Object instantiate(String listenerImpl, ClassLoaderService classLoaderService) {
try {
return classLoaderService.classForName( listenerImpl ).newInstance();
}
catch (Exception e) {
- throw new HibernateException( "Could not instantiate requested listener [" + listenerImpl + "]", e );
+ throw new HibernateException( "Could not instantiate event listener '" + listenerImpl + "'", e );
}
}
@@ -484,7 +495,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
return fetchProfileMap;
}
- public Map getMappedSuperclassMap() {
+ public Map, MappedSuperclass> getMappedSuperclassMap() {
return mappedSuperclassMap;
}
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/TypeDefinition.java b/hibernate-core/src/main/java/org/hibernate/boot/model/TypeDefinition.java
index 44d3bd0edf..bf18ce4b4d 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/TypeDefinition.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/TypeDefinition.java
@@ -57,24 +57,22 @@ import static org.hibernate.mapping.MappingHelper.injectParameters;
* @author Steve Ebersole
* @author John Verhaeg
*/
-@SuppressWarnings({"rawtypes", "unchecked"})
public class TypeDefinition implements Serializable {
public static final AtomicInteger NAME_COUNTER = new AtomicInteger();
private final String name;
- private final Class typeImplementorClass;
+ private final Class> typeImplementorClass;
private final String[] registrationKeys;
- private final Properties parameters;
+ private final Map parameters;
private BasicValue.Resolution> reusableResolution;
public TypeDefinition(
String name,
- Class typeImplementorClass,
+ Class> typeImplementorClass,
String[] registrationKeys,
- Properties parameters,
- TypeConfiguration typeConfiguration) {
+ Map parameters) {
this.name = name;
this.typeImplementorClass = typeImplementorClass;
this.registrationKeys= registrationKeys;
@@ -85,7 +83,7 @@ public class TypeDefinition implements Serializable {
return name;
}
- public Class getTypeImplementorClass() {
+ public Class> getTypeImplementorClass() {
return typeImplementorClass;
}
@@ -93,13 +91,13 @@ public class TypeDefinition implements Serializable {
return registrationKeys;
}
- public Properties getParameters() {
+ public Map getParameters() {
return parameters;
}
public BasicValue.Resolution> resolve(
- Map localConfigParameters,
- MutabilityPlan explicitMutabilityPlan,
+ Map,?> localConfigParameters,
+ MutabilityPlan> explicitMutabilityPlan,
MetadataBuildingContext context,
JdbcTypeIndicators indicators) {
if ( CollectionHelper.isEmpty( localConfigParameters ) ) {
@@ -107,7 +105,6 @@ public class TypeDefinition implements Serializable {
if ( reusableResolution == null ) {
reusableResolution = createResolution( name, Collections.emptyMap(), indicators, context );
}
-
return reusableResolution;
}
else {
@@ -134,7 +131,7 @@ public class TypeDefinition implements Serializable {
private static BasicValue.Resolution> createResolution(
String name,
Class> typeImplementorClass,
- Properties parameters,
+ Map,?> parameters,
Map,?> usageSiteProperties,
JdbcTypeIndicators indicators,
MetadataBuildingContext context) {
@@ -153,34 +150,32 @@ public class TypeDefinition implements Serializable {
( (TypeConfigurationAware) typeInstance ).setTypeConfiguration( typeConfiguration );
}
- final Properties combinedTypeParameters;
-
- if ( CollectionHelper.isNotEmpty( usageSiteProperties ) ) {
- combinedTypeParameters = new Properties( parameters );
- combinedTypeParameters.putAll( usageSiteProperties );
+ final Properties combinedTypeParameters = new Properties();
+ if ( parameters!=null ) {
+ combinedTypeParameters.putAll( parameters );
}
- else {
- combinedTypeParameters = parameters;
+ if ( usageSiteProperties!=null ) {
+ combinedTypeParameters.putAll( usageSiteProperties );
}
injectParameters( typeInstance, combinedTypeParameters );
if ( typeInstance instanceof UserType ) {
- final UserType userType = (UserType) typeInstance;
- final CustomType customType = new CustomType<>( userType, typeConfiguration );
+ final UserType> userType = (UserType>) typeInstance;
+ final CustomType> customType = new CustomType<>( userType, typeConfiguration );
return new UserTypeResolution( customType, null, combinedTypeParameters );
}
if ( typeInstance instanceof BasicType ) {
- final BasicType resolvedBasicType = (BasicType) typeInstance;
- return new BasicValue.Resolution() {
+ final BasicType> resolvedBasicType = (BasicType>) typeInstance;
+ return new BasicValue.Resolution<>() {
@Override
public JdbcMapping getJdbcMapping() {
return resolvedBasicType;
}
- @Override
+ @Override @SuppressWarnings({"rawtypes", "unchecked"})
public BasicType getLegacyResolvedBasicType() {
return resolvedBasicType;
}
@@ -190,8 +185,8 @@ public class TypeDefinition implements Serializable {
return combinedTypeParameters;
}
- @Override
- public JavaType getDomainJavaType() {
+ @Override @SuppressWarnings({"rawtypes", "unchecked"})
+ public JavaType getDomainJavaType() {
return resolvedBasicType.getMappedJavaType();
}
@@ -210,8 +205,8 @@ public class TypeDefinition implements Serializable {
return resolvedBasicType.getValueConverter();
}
- @Override
- public MutabilityPlan getMutabilityPlan() {
+ @Override @SuppressWarnings({"rawtypes", "unchecked"})
+ public MutabilityPlan getMutabilityPlan() {
// a TypeDefinition does not explicitly provide a MutabilityPlan (yet?)
return resolvedBasicType.isMutable()
? getDomainJavaType().getMutabilityPlan()
@@ -229,22 +224,23 @@ public class TypeDefinition implements Serializable {
.resolveDescriptor( typeImplementorClass );
final JdbcType jdbcType = typeConfiguration.getJdbcTypeRegistry().getDescriptor( Types.VARBINARY );
final BasicType resolved = typeConfiguration.getBasicTypeRegistry().resolve( jtd, jdbcType );
+ @SuppressWarnings({"rawtypes", "unchecked"})
final SerializableType legacyType = new SerializableType( typeImplementorClass );
- return new BasicValue.Resolution() {
+ return new BasicValue.Resolution<>() {
@Override
public JdbcMapping getJdbcMapping() {
return resolved;
}
- @Override
+ @Override @SuppressWarnings({"rawtypes", "unchecked"})
public BasicType getLegacyResolvedBasicType() {
return legacyType;
}
- @Override
- public JavaType getDomainJavaType() {
- return (JavaType) resolved.getMappedJavaType();
+ @Override @SuppressWarnings({"rawtypes", "unchecked"})
+ public JavaType getDomainJavaType() {
+ return resolved.getMappedJavaType();
}
@Override
@@ -262,8 +258,8 @@ public class TypeDefinition implements Serializable {
return resolved.getValueConverter();
}
- @Override
- public MutabilityPlan getMutabilityPlan() {
+ @Override @SuppressWarnings({"rawtypes", "unchecked"})
+ public MutabilityPlan getMutabilityPlan() {
// a TypeDefinition does not explicitly provide a MutabilityPlan (yet?)
return resolved.isMutable()
? getDomainJavaType().getMutabilityPlan()
@@ -281,47 +277,31 @@ public class TypeDefinition implements Serializable {
String name, Class> typeImplementorClass,
BeanInstanceProducer instanceProducer) {
if ( Helper.INSTANCE.shouldIgnoreBeanContainer( serviceRegistry ) ) {
- if ( name != null ) {
- return instanceProducer.produceBeanInstance( name, typeImplementorClass );
- }
- else {
- return instanceProducer.produceBeanInstance( typeImplementorClass );
- }
+ return name != null
+ ? instanceProducer.produceBeanInstance( name, typeImplementorClass )
+ : instanceProducer.produceBeanInstance( typeImplementorClass );
}
else {
- final ManagedBean typeBean;
- if ( name != null ) {
- typeBean = serviceRegistry.getService( ManagedBeanRegistry.class )
- .getBean( name, typeImplementorClass, instanceProducer );
- }
- else {
- typeBean = serviceRegistry.getService( ManagedBeanRegistry.class )
- .getBean( typeImplementorClass, instanceProducer );
- }
-
+ ManagedBeanRegistry beanRegistry = serviceRegistry.getService(ManagedBeanRegistry.class);
+ final ManagedBean> typeBean = name != null
+ ? beanRegistry.getBean( name, typeImplementorClass, instanceProducer )
+ : beanRegistry.getBean( typeImplementorClass, instanceProducer );
return typeBean.getBeanInstance();
}
}
public static BasicValue.Resolution> createLocalResolution(
String name,
- Class typeImplementorClass,
- MutabilityPlan explicitMutabilityPlan,
- Map localTypeParams,
+ Class> typeImplementorClass,
+ MutabilityPlan> explicitMutabilityPlan,
+ Map,?> localTypeParams,
MetadataBuildingContext buildingContext) {
- name = name + ':' + NAME_COUNTER.getAndIncrement();
-
- final Properties properties = new Properties();
- properties.putAll( localTypeParams );
-
- final TypeConfiguration typeConfiguration = buildingContext.getBootstrapContext().getTypeConfiguration();
-
return createResolution(
- name,
+ name + ':' + NAME_COUNTER.getAndIncrement(),
typeImplementorClass,
- properties,
+ localTypeParams,
null,
- typeConfiguration.getCurrentBaseSqlTypeIndicators(),
+ buildingContext.getBootstrapContext().getTypeConfiguration().getCurrentBaseSqlTypeIndicators(),
buildingContext
);
}
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/convert/internal/AttributeConverterManager.java b/hibernate-core/src/main/java/org/hibernate/boot/model/convert/internal/AttributeConverterManager.java
index 24cbf6ffe0..000bf494de 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/convert/internal/AttributeConverterManager.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/convert/internal/AttributeConverterManager.java
@@ -30,7 +30,8 @@ import org.hibernate.internal.util.StringHelper;
import org.jboss.logging.Logger;
import com.fasterxml.classmate.ResolvedType;
-import jakarta.persistence.AttributeConverter;
+
+import static org.hibernate.boot.model.convert.internal.ConverterHelper.resolveConverterClassParamTypes;
/**
* @implNote It is important that all {@link RegisteredConversion} be registered
@@ -95,22 +96,7 @@ public class AttributeConverterManager implements ConverterAutoApplyHandler {
final Class> domainType;
if ( conversion.getExplicitDomainType().equals( void.class ) ) {
// the registration did not define an explicit domain-type, so inspect the converter
- final ClassmateContext classmateContext = context.getClassmateContext();
- final ResolvedType converterType = classmateContext.getTypeResolver().resolve( conversion.getConverterType() );
- final List converterParamTypes = converterType.typeParametersFor( AttributeConverter.class );
- if ( converterParamTypes == null ) {
- throw new AnnotationException(
- "Could not extract type parameter information from AttributeConverter implementation ["
- + conversion.getConverterType().getName() + "]"
- );
- }
- else if ( converterParamTypes.size() != 2 ) {
- throw new AnnotationException(
- "Unexpected type parameter information for AttributeConverter implementation [" +
- conversion.getConverterType().getName() + "]; expected 2 parameter types, but found " + converterParamTypes.size()
- );
- }
-
+ final List converterParamTypes = resolveConverterClassParamTypes( conversion.getConverterType(), context.getClassmateContext() );
domainType = converterParamTypes.get( 0 ).getErasedType();
}
else {
@@ -122,13 +108,13 @@ public class AttributeConverterManager implements ConverterAutoApplyHandler {
if ( existingRegistration != null ) {
if ( !conversion.equals( existingRegistration ) ) {
throw new AnnotationException(
- "Attempt to register non-matching `@ConverterRegistration` descriptors for `AttributeConverter` "
- + conversion.getConverterType().getName()
+ "Conflicting '@ConverterRegistration' descriptors for attribute converter '"
+ + conversion.getConverterType().getName() + "'"
);
}
else {
if ( log.isDebugEnabled() ) {
- log.debugf( "Skipping duplicate `@ConverterRegistration` for `%s`", conversion.getConverterType().getName() );
+ log.debugf( "Skipping duplicate '@ConverterRegistration' for '%s'", conversion.getConverterType().getName() );
}
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/convert/internal/ConverterHelper.java b/hibernate-core/src/main/java/org/hibernate/boot/model/convert/internal/ConverterHelper.java
index 575cf01065..480a220939 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/convert/internal/ConverterHelper.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/convert/internal/ConverterHelper.java
@@ -97,14 +97,15 @@ public class ConverterHelper {
final List converterParamTypes = converterType.typeParametersFor( AttributeConverter.class );
if ( converterParamTypes == null ) {
throw new AnnotationException(
- "Could not extract type parameter information from AttributeConverter implementation ["
- + converterClass.getName() + "]"
+ "Could not extract type argument from attribute converter class '"
+ + converterClass.getName() + "'"
);
}
else if ( converterParamTypes.size() != 2 ) {
throw new AnnotationException(
- "Unexpected type parameter information for AttributeConverter implementation [" +
- converterClass.getName() + "]; expected 2 parameter types, but found " + converterParamTypes.size()
+ "Unexpected type argument for attribute converter class '"
+ + converterClass.getName()
+ + "' (expected 2 type arguments, but found " + converterParamTypes.size() + ")"
);
}
return converterParamTypes;
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/convert/spi/RegisteredConversion.java b/hibernate-core/src/main/java/org/hibernate/boot/model/convert/spi/RegisteredConversion.java
index ae7188ba29..6e8ff83d90 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/convert/spi/RegisteredConversion.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/convert/spi/RegisteredConversion.java
@@ -94,7 +94,7 @@ public class RegisteredConversion {
return explicitDomainType;
}
- public Class> getConverterType() {
+ public Class extends AttributeConverter,?>> getConverterType() {
return converterType;
}
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/UserTypeResolution.java b/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/UserTypeResolution.java
index 696bf6fbec..2e650188b0 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/UserTypeResolution.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/UserTypeResolution.java
@@ -21,8 +21,8 @@ import org.hibernate.type.descriptor.jdbc.JdbcType;
* @author Steve Ebersole
*/
public class UserTypeResolution implements BasicValue.Resolution {
- private final CustomType userTypeAdapter;
- private final MutabilityPlan mutabilityPlan;
+ private final CustomType> userTypeAdapter;
+ private final MutabilityPlan> mutabilityPlan;
/**
* We need this for the way envers interprets the boot-model
@@ -31,8 +31,8 @@ public class UserTypeResolution implements BasicValue.Resolution {
private final Properties combinedTypeParameters;
public UserTypeResolution(
- CustomType userTypeAdapter,
- MutabilityPlan explicitMutabilityPlan,
+ CustomType> userTypeAdapter,
+ MutabilityPlan> explicitMutabilityPlan,
Properties combinedTypeParameters) {
this.userTypeAdapter = userTypeAdapter;
this.combinedTypeParameters = combinedTypeParameters;
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java
index 891aa18d55..9108352c84 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java
@@ -9,7 +9,6 @@ package org.hibernate.boot.model.source.internal.hbm;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -2384,7 +2383,7 @@ public class ModelBinder {
private BasicType> resolveExplicitlyNamedAnyDiscriminatorType(
String typeName,
- Properties parameters,
+ Map parameters,
Any.MetaValue discriminatorMapping) {
final BootstrapContext bootstrapContext = metadataBuildingContext.getBootstrapContext();
@@ -2432,7 +2431,9 @@ public class ModelBinder {
if ( typeInstance instanceof ParameterizedType ) {
if ( parameters != null ) {
- ( (ParameterizedType) typeInstance ).setParameterValues( parameters );
+ Properties properties = new Properties();
+ properties.putAll( parameters );
+ ( (ParameterizedType) typeInstance ).setParameterValues( properties );
}
}
@@ -2808,9 +2809,9 @@ public class ModelBinder {
private static class TypeResolution {
private final String typeName;
- private final Properties parameters;
+ private final Map parameters;
- public TypeResolution(String typeName, Properties parameters) {
+ public TypeResolution(String typeName, Map parameters) {
this.typeName = typeName;
this.parameters = parameters;
}
@@ -2824,7 +2825,7 @@ public class ModelBinder {
}
String typeName = typeSource.getName();
- Properties typeParameters = new Properties();
+ Map typeParameters = new HashMap<>();
final TypeDefinition typeDefinition = sourceDocument.getMetadataCollector().getTypeDefinition( typeName );
if ( typeDefinition != null ) {
@@ -4246,12 +4247,11 @@ public class ModelBinder {
private String columns(Value value) {
final StringBuilder builder = new StringBuilder();
- final Iterator selectableItr = value.getColumnIterator();
- while ( selectableItr.hasNext() ) {
- builder.append( selectableItr.next().getText() );
- if ( selectableItr.hasNext() ) {
+ for ( Selectable selectable : value.getSelectables() ) {
+ if ( builder.length()>0) {
builder.append( ", " );
}
+ builder.append( selectable.getText() );
}
return builder.toString();
}
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/TypeDefinitionBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/TypeDefinitionBinder.java
index c7a01d92b2..2577b0eb5d 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/TypeDefinitionBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/TypeDefinitionBinder.java
@@ -33,8 +33,7 @@ public class TypeDefinitionBinder {
typeDefinitionBinding.getName(),
cls.classForName( typeDefinitionBinding.getClazz() ),
null,
- ConfigParameterHelper.extractConfigParametersAsProperties( typeDefinitionBinding ),
- context.getMetadataCollector().getTypeConfiguration()
+ ConfigParameterHelper.extractConfigParameters( typeDefinitionBinding )
);
if ( log.isDebugEnabled() ) {
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/InFlightMetadataCollector.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/InFlightMetadataCollector.java
index 06e2f42d42..c19a6c3fad 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/spi/InFlightMetadataCollector.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/InFlightMetadataCollector.java
@@ -59,7 +59,7 @@ import org.hibernate.usertype.UserCollectionType;
import jakarta.persistence.AttributeConverter;
/**
- * An in-flight representation of Metadata while Metadata is being built.
+ * An in-flight representation of {@link org.hibernate.boot.Metadata} while it is being built.
*
* @author Steve Ebersole
*
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotatedColumn.java b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotatedColumn.java
index 7f7ede3fc9..266dc87730 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotatedColumn.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotatedColumn.java
@@ -38,6 +38,7 @@ import org.hibernate.mapping.Table;
import org.jboss.logging.Logger;
import static org.hibernate.cfg.BinderHelper.getOverridableAnnotation;
+import static org.hibernate.cfg.BinderHelper.getPath;
import static org.hibernate.cfg.BinderHelper.getRelativePath;
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
@@ -297,8 +298,9 @@ public class AnnotatedColumn {
final int numberOfJdbcParams = StringHelper.count( writeExpression, '?' );
if ( numberOfJdbcParams != 1 ) {
throw new AnnotationException(
- "@WriteExpression must contain exactly one value placeholder ('?') character: property ["
- + propertyName + "] and column [" + logicalColumnName + "]"
+ "Write expression in '@ColumnTransformer' for property '" + propertyName
+ + "' and column '" + logicalColumnName + "'"
+ + " must contain exactly one placeholder character ('?')"
);
}
}
@@ -512,8 +514,8 @@ public class AnnotatedColumn {
if ( join == null ) {
throw new AnnotationException(
- "Cannot find the expected secondary table: no "
- + explicitTableName + " available for " + propertyHolder.getClassName()
+ "Secondary table '" + explicitTableName + "' for property '" + propertyHolder.getClassName()
+ + "' is not declared (use '@SecondaryTable' to declare the secondary table)"
);
}
@@ -710,7 +712,12 @@ public class AnnotatedColumn {
if ( overriddenCols != null ) {
//check for overridden first
if ( columnAnns != null && overriddenCols.length != columnAnns.length ) {
- throw new AnnotationException( "AttributeOverride.column() should override all columns for now" );
+ //TODO: unfortunately, we never actually see this nice error message, since
+ // PersistentClass.validate() gets called first and produces a worse message
+ throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData )
+ + "' specifies " + columnAnns.length
+ + " '@AttributeOverride's but the overridden property has " + overriddenCols.length
+ + " columns (every column must have exactly one '@AttributeOverride')" );
}
LOG.debugf( "Column(s) overridden for property %s", inferredData.getPropertyName() );
return overriddenCols.length == 0 ? null : overriddenCols;
@@ -959,24 +966,24 @@ public class AnnotatedColumn {
if ( nbrOfColumns > 1 ) {
for (int currentIndex = 1; currentIndex < nbrOfColumns; currentIndex++) {
if ( !columns[currentIndex].isFormula() && !columns[currentIndex - 1].isFormula() ) {
- if ( columns[currentIndex].isInsertable() != columns[currentIndex - 1].isInsertable() ) {
- throw new AnnotationException(
- "Mixing insertable and non insertable columns in a property is not allowed: " + propertyName
- );
- }
if ( columns[currentIndex].isNullable() != columns[currentIndex - 1].isNullable() ) {
throw new AnnotationException(
- "Mixing nullable and non nullable columns in a property is not allowed: " + propertyName
+ "Column mappings for property '" + propertyName + "' mix nullable with 'not null'"
+ );
+ }
+ if ( columns[currentIndex].isInsertable() != columns[currentIndex - 1].isInsertable() ) {
+ throw new AnnotationException(
+ "Column mappings for property '" + propertyName + "' mix insertable with 'insertable=false'"
);
}
if ( columns[currentIndex].isUpdatable() != columns[currentIndex - 1].isUpdatable() ) {
throw new AnnotationException(
- "Mixing updatable and non updatable columns in a property is not allowed: " + propertyName
+ "Column mappings for property '" + propertyName + "' mix updatable with 'updatable=false'"
);
}
if ( !columns[currentIndex].getTable().equals( columns[currentIndex - 1].getTable() ) ) {
throw new AnnotationException(
- "Mixing different tables in a property is not allowed: " + propertyName
+ "Column mappings for property '" + propertyName + "' mix distinct secondary tables"
);
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotatedJoinColumn.java b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotatedJoinColumn.java
index 96c7cb24e8..a31b336b66 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotatedJoinColumn.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotatedJoinColumn.java
@@ -258,8 +258,8 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
if ( ann != null ) {
if ( !BinderHelper.isEmptyOrNullAnnotationValue( mappedBy ) ) {
throw new AnnotationException(
- "Illegal attempt to define a @JoinColumn with a mappedBy association: "
- + getRelativePath( propertyHolder, propertyName )
+ "Association '" + getRelativePath( propertyHolder, propertyName )
+ + "' is 'mappedBy' a different entity and may not explicitly specify the '@JoinColumn'"
);
}
AnnotatedJoinColumn joinColumn = new AnnotatedJoinColumn();
@@ -428,10 +428,8 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
public static void checkIfJoinColumn(Object columns, PropertyHolder holder, PropertyData property) {
if ( !( columns instanceof AnnotatedJoinColumn[] ) ) {
throw new AnnotationException(
- "@Column cannot be used on an association property: "
- + holder.getEntityName()
- + "."
- + property.getPropertyName()
+ "Property '" + getRelativePath( holder, property.getPropertyName() )
+ + "' is an association and may not use '@Column' to specify column mappings (use '@JoinColumn' instead)"
);
}
}
@@ -559,9 +557,10 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
throw new AnnotationException(
String.format(
Locale.ENGLISH,
- "mapped-by [%s] defined for attribute [%s] referenced an invalid property (no columns)",
+ "Association '%s' is 'mappedBy' a property '%s' of entity '%s' with no columns",
+ propertyHolder.getPath(),
mappedByPropertyName,
- propertyHolder.getPath()
+ mappedByEntityName
)
);
}
@@ -570,7 +569,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
throw new AnnotationException(
String.format(
Locale.ENGLISH,
- "mapped-by [%s] defined for attribute [%s] referenced an invalid property (formula)",
+ "Association '%s' is 'mappedBy' a property '%s' of entity '%s' which maps to a formula",
mappedByPropertyName,
propertyHolder.getPath()
)
@@ -580,7 +579,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
throw new AnnotationException(
String.format(
Locale.ENGLISH,
- "mapped-by [%s] defined for attribute [%s] referenced an invalid property (multiple columns)",
+ "Association '%s' is 'mappedBy' a property '%s' of entity '%s' with multiple columns",
mappedByPropertyName,
propertyHolder.getPath()
)
@@ -604,7 +603,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
else if ( ownerSide ) {
final String logicalTableName = metadataCollector.getLogicalTableName( referencedEntity.getTable() );
- columnIdentifier =implicitNamingStrategy.determineJoinColumnName(
+ columnIdentifier = implicitNamingStrategy.determineJoinColumnName(
new ImplicitJoinColumnNameSource() {
final ImplicitJoinColumnNameSource.Nature implicitNamingNature = getImplicitNature();
@@ -794,10 +793,11 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
if ( columnOwner == null ) {
try {
throw new MappingException(
- "Unable to find column with logical name: "
+ "No column with logical name '"
+ columns[0].getReferencedColumn()
- + " in " + referencedEntity.getTable()
- + " and its related supertables and secondary tables"
+ + "' in table '" + referencedEntity.getTable().getName()
+ + "' for entity '" + referencedEntity.getEntityName()
+ + "', nor in its related superclass tables and secondary tables"
);
}
catch (MappingException e) {
@@ -821,8 +821,8 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
catch (MappingException me) {
//rewrite the exception
throw new MappingException(
- "Unable to find column with logical name: "
- + logicalReferencedColumnName + " in " + matchingTable.getName()
+ "No column with logical name '" + logicalReferencedColumnName
+ + "' in table '" + matchingTable.getName() + "'"
);
}
noReferencedColumn = false;
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java
index 289f1f2d74..b63c724468 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java
@@ -560,8 +560,7 @@ public final class AnnotationBinder {
//@Entity and @MappedSuperclass on the same class leads to a NPE down the road
if ( clazzToProcess.isAnnotationPresent( Entity.class )
&& clazzToProcess.isAnnotationPresent( MappedSuperclass.class ) ) {
- throw new AnnotationException( "An entity cannot be annotated with both @Entity and @MappedSuperclass: "
- + clazzToProcess.getName() );
+ throw new AnnotationException( "Type '"+ clazzToProcess.getName() + "' is annotated both '@Entity' and '@MappedSuperclass'");
}
if ( clazzToProcess.isAnnotationPresent( Inheritance.class )
@@ -995,21 +994,17 @@ public final class AnnotationBinder {
final XAnnotatedElement element = propertyAnnotatedElement.getProperty();
if ( hasIdAnnotation(element) ) {
inFlightPropertyDataList.add( 0, propertyAnnotatedElement );
- /*
- * The property must be put in hibernate.properties as it's a system wide property. Fixable?
- * TODO support true/false/default on the property instead of present / not present
- * TODO is @Column mandatory?
- * TODO add method support
- */
+ // The property must be put in hibernate.properties as it's a system wide property. Fixable?
+ //TODO support true/false/default on the property instead of present / not present
+ //TODO is @Column mandatory?
+ //TODO add method support
if ( context.getBuildingOptions().isSpecjProprietarySyntaxEnabled() ) {
if ( element.isAnnotationPresent( Id.class ) && element.isAnnotationPresent( Column.class ) ) {
String columnName = element.getAnnotation( Column.class ).name();
for ( XProperty prop : declaringClass.getDeclaredProperties( AccessType.FIELD.getType() ) ) {
if ( !prop.isAnnotationPresent( MapsId.class ) ) {
- /*
- * The detection of a configured individual JoinColumn differs between Annotation
- * and XML configuration processing.
- */
+ //The detection of a configured individual JoinColumn differs between Annotation
+ //and XML configuration processing.
boolean isRequiredAnnotationPresent = false;
JoinColumns groupAnnotation = prop.getAnnotation( JoinColumns.class );
if ( (prop.isAnnotationPresent( JoinColumn.class )
@@ -1106,8 +1101,9 @@ public final class AnnotationBinder {
}
else {
throw new AnnotationException(
- "@Parent cannot be applied outside an embeddable object: "
- + getPath( propertyHolder, inferredData )
+ "Property '" + getPath( propertyHolder, inferredData )
+ + "' is annotated '@Parent' but is not a member of an embeddable class"
+
);
}
}
@@ -1292,19 +1288,20 @@ public final class AnnotationBinder {
PropertyBinder propertyBinder) {
if (isIdentifierMapper) {
throw new AnnotationException(
- "@IdClass class should not have @Version property"
+ "Class '" + propertyHolder.getEntityName()
+ + "' is annotated '@IdClass' and may not have a property annotated '@Version'"
);
}
if ( !( propertyHolder.getPersistentClass() instanceof RootClass ) ) {
throw new AnnotationException(
- "Unable to define/override @Version on a subclass: "
- + propertyHolder.getEntityName()
+ "Entity '" + propertyHolder.getEntityName()
+ + "' is a subclass in an entity class hierarchy and may not have a property annotated '@Version'"
);
}
if ( !propertyHolder.isEntity() ) {
throw new AnnotationException(
- "Unable to define @Version on an embedded class: "
- + propertyHolder.getEntityName()
+ "Embedded class '" + propertyHolder.getEntityName()
+ + "' may not have a property annotated '@Version'"
);
}
if ( LOG.isTraceEnabled() ) {
@@ -1387,12 +1384,19 @@ public final class AnnotationBinder {
);
if ( isComponent || compositeUserType != null ) {
- String referencedEntityName = null;
+ final String referencedEntityName;
+ final String propertyName;
if ( isOverridden ) {
+ // careful: not always a @MapsId property, sometimes it's from an @IdClass
PropertyData mapsIdProperty = getPropertyOverriddenByMapperOrMapsId(
isId, propertyHolder, property.getName(), context
);
referencedEntityName = mapsIdProperty.getClassOrElementName();
+ propertyName = mapsIdProperty.getPropertyName();
+ }
+ else {
+ referencedEntityName = null;
+ propertyName = null;
}
propertyBinder = bindComponent(
@@ -1406,6 +1410,7 @@ public final class AnnotationBinder {
isId,
inheritanceStatePerClass,
referencedEntityName,
+ propertyName,
determineCustomInstantiator( property, returnedClass, context ),
compositeUserType,
isOverridden ? (AnnotatedJoinColumn[]) columns : null
@@ -1524,9 +1529,9 @@ public final class AnnotationBinder {
throw new AnnotationException(
String.format(
Locale.ROOT,
- "@Columns not allowed on a @Any property [%s]; @Column or @Formula is used to map the discriminator" +
- "and only one is allowed",
- getPath(propertyHolder, inferredData)
+ "Property '%s' is annotated '@Any' and may not have a '@Columns' annotation "
+ + "(a single '@Column' or '@Formula' must be used to map the discriminator, and '@JoinColumn's must be used to map the foreign key) ",
+ getPath( propertyHolder, inferredData )
)
);
}
@@ -1561,8 +1566,8 @@ public final class AnnotationBinder {
if ( property.isAnnotationPresent( Column.class )
|| property.isAnnotationPresent( Columns.class ) ) {
throw new AnnotationException(
- "@Column(s) not allowed on a @OneToOne property: "
- + getPath(propertyHolder, inferredData)
+ "Property '"+ getPath( propertyHolder, inferredData )
+ + "' is a '@OneToOne' association and may not use '@Column' to specify column mappings (use '@PrimaryKeyJoinColumn' instead)"
);
}
@@ -1631,8 +1636,8 @@ public final class AnnotationBinder {
if ( property.isAnnotationPresent( Column.class )
|| property.isAnnotationPresent( Columns.class ) ) {
throw new AnnotationException(
- "@Column(s) not allowed on a @ManyToOne property: "
- + getPath(propertyHolder, inferredData)
+ "Property '"+ getPath( propertyHolder, inferredData )
+ + "' is a '@ManyToOne' association and may not use '@Column' to specify column mappings (use '@JoinColumn' instead)"
);
}
@@ -1830,8 +1835,9 @@ public final class AnnotationBinder {
MetadataBuildingContext buildingContext) {
if ( isIdentifierMapper ) {
throw new AnnotationException(
- "@IdClass class should not have @Id nor @EmbeddedId properties: "
- + getPath( propertyHolder, inferredData )
+ "Property '"+ getPath( propertyHolder, inferredData )
+ + "' belongs to an '@IdClass' and may not be annotated '@Id' or '@EmbeddedId'"
+
);
}
XClass entityXClass = inferredData.getClassOrElement();
@@ -1931,6 +1937,7 @@ public final class AnnotationBinder {
boolean isId, //is an identifier
Map inheritanceStatePerClass,
String referencedEntityName, //is a component who is overridden by a @MapsId
+ String propertyName,
Class extends EmbeddableInstantiator> customInstantiatorImpl,
Class extends CompositeUserType>> compositeUserTypeClass,
AnnotatedJoinColumn[] columns) {
@@ -1947,6 +1954,7 @@ public final class AnnotationBinder {
SecondPass sp = new CopyIdentifierComponentSecondPass(
comp,
referencedEntityName,
+ propertyName,
columns,
buildingContext
);
@@ -1972,16 +1980,18 @@ public final class AnnotationBinder {
comp.setKey( true );
if ( propertyHolder.getPersistentClass().getIdentifier() != null ) {
throw new AnnotationException(
- comp.getComponentClassName()
- + " must not have @Id properties when used as an @EmbeddedId: "
+ "Embeddable class '" + comp.getComponentClassName()
+ + "' may not have a property annotated '@Id' since it is used by '"
+ getPath( propertyHolder, inferredData )
+ + "' as an '@EmbeddedId'"
);
}
if ( referencedEntityName == null && comp.getPropertySpan() == 0 ) {
throw new AnnotationException(
- comp.getComponentClassName()
- + " has no persistent id property: "
+ "Embeddable class '" + comp.getComponentClassName()
+ + "' may not be used as an '@EmbeddedId' by '"
+ getPath( propertyHolder, inferredData )
+ + "' because it has no properties"
);
}
}
@@ -2136,9 +2146,10 @@ public final class AnnotationBinder {
if ( propertyHolder.isInIdClass() ) {
if ( entityPropertyData == null ) {
throw new AnnotationException(
- "Property of @IdClass not found in entity "
- + baseInferredData.getPropertyClass().getName() + ": "
- + idClassPropertyData.getPropertyName()
+ "Property '" + getPath( propertyHolder, idClassPropertyData )
+ + "' belongs to an '@IdClass' but has no matching property in entity class '"
+ + baseInferredData.getPropertyClass().getName()
+ + "' (every property of the '@IdClass' must have a corresponding persistent property in the '@Entity' class)"
);
}
final boolean hasXToOneAnnotation = hasToOneAnnotation( entityPropertyData.getProperty() );
@@ -2439,8 +2450,8 @@ public final class AnnotationBinder {
toOne.setFetchMode( FetchMode.SELECT );
}
else if ( fetch.value() == org.hibernate.annotations.FetchMode.SUBSELECT ) {
- throw new AnnotationException( "Use of FetchMode.SUBSELECT not allowed for to-one associations: "
- + property.getName() );
+ throw new AnnotationException( "Association '" + property.getName()
+ + "' is annotated '@Fetch(SUBSELECT)' but is not many-valued");
}
else {
throw new AssertionFailure( "Unknown FetchMode: " + fetch.value() );
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/BinderHelper.java b/hibernate-core/src/main/java/org/hibernate/cfg/BinderHelper.java
index 8274d12d31..5a3babd5dc 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/BinderHelper.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/BinderHelper.java
@@ -76,13 +76,14 @@ import jakarta.persistence.TableGenerator;
import jakarta.persistence.UniqueConstraint;
import static org.hibernate.cfg.AnnotatedColumn.buildColumnOrFormulaFromAnnotation;
+import static org.hibernate.internal.util.StringHelper.isNotEmpty;
+
import static org.hibernate.cfg.AnnotatedJoinColumn.NON_PK_REFERENCE;
import static org.hibernate.cfg.AnnotatedJoinColumn.checkReferencedColumnsType;
import static org.hibernate.internal.util.StringHelper.isEmpty;
import static org.hibernate.property.access.spi.BuiltInPropertyAccessStrategies.EMBEDDED;
import static org.hibernate.property.access.spi.BuiltInPropertyAccessStrategies.NOOP;
import static org.hibernate.property.access.spi.BuiltInPropertyAccessStrategies.interpret;
-
/**
* @author Emmanuel Bernard
*/
@@ -749,7 +750,9 @@ public class BinderHelper {
buildingContext
);
if ( gen == null ) {
- throw new AnnotationException( "Unknown named generator (@GeneratedValue#generatorName): " + generatorName );
+ throw new AnnotationException( "No id generator was declared with the name '" + generatorName
+ + "' specified by '@GeneratedValue'"
+ + " (define a named generator using '@SequenceGenerator', '@TableGenerator', or '@GenericGenerator')" );
}
//This is quite vague in the spec but a generator could override the generator choice
String identifierGeneratorStrategy = gen.getStrategy();
@@ -1000,9 +1003,7 @@ public class BinderHelper {
}
public static String getAnnotationValueStringOrNull(String value) {
- return isEmptyOrNullAnnotationValue( value )
- ? null
- : value;
+ return isEmptyOrNullAnnotationValue( value ) ? null : value;
}
public static Any buildAnyValue(
@@ -1159,7 +1160,7 @@ public class BinderHelper {
public static Map toAliasTableMap(SqlFragmentAlias[] aliases){
Map ret = new HashMap<>();
for ( SqlFragmentAlias aliase : aliases ) {
- if ( StringHelper.isNotEmpty( aliase.table() ) ) {
+ if ( isNotEmpty( aliase.table() ) ) {
ret.put( aliase.alias(), aliase.table() );
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/ColumnsBuilder.java b/hibernate-core/src/main/java/org/hibernate/cfg/ColumnsBuilder.java
index 6862f89ffd..fce30dbdf3 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/ColumnsBuilder.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/ColumnsBuilder.java
@@ -140,8 +140,8 @@ class ColumnsBuilder {
);
}
else if ( joinColumns == null && property.isAnnotationPresent( org.hibernate.annotations.Any.class ) ) {
- throw new AnnotationException( "@Any requires an explicit @JoinColumn(s): "
- + getPath( propertyHolder, inferredData ) );
+ throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData )
+ + "' is annotated '@Any' and must declare at least one '@JoinColumn'" );
}
if ( columns == null && !property.isAnnotationPresent( ManyToMany.class ) ) {
//useful for collection of embedded elements
@@ -179,21 +179,19 @@ class ColumnsBuilder {
buildingContext
);
if ( StringHelper.isEmpty( joinTableAnn.name() ) ) {
+ //TODO: I don't see why this restriction makes sense (use the same defaulting rule as for many-valued)
throw new AnnotationException(
- "JoinTable.name() on a @ToOne association has to be explicit: "
- + getPath( propertyHolder, inferredData )
+ "Single-valued association " + getPath( propertyHolder, inferredData )
+ + " has a '@JoinTable' annotation with no explicit 'name'"
);
}
}
else {
OneToOne oneToOneAnn = property.getAnnotation( OneToOne.class );
- String mappedBy = oneToOneAnn != null
- ? oneToOneAnn.mappedBy()
- : null;
joinColumns = AnnotatedJoinColumn.buildJoinColumns(
null,
comment,
- mappedBy,
+ oneToOneAnn != null ? oneToOneAnn.mappedBy() : null,
entityBinder.getSecondaryTables(),
propertyHolder,
inferredData.getPropertyName(),
@@ -215,7 +213,8 @@ class ColumnsBuilder {
joinColumnAnnotations = joinColumnAnnotation.value();
int length = joinColumnAnnotations.length;
if ( length == 0 ) {
- throw new AnnotationException( "Cannot bind an empty @JoinColumns" );
+ throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData )
+ + "' has an empty '@JoinColumns' annotation" );
}
}
@@ -243,7 +242,8 @@ class ColumnsBuilder {
joinColumnOrFormulaAnnotations = joinColumnsOrFormulasAnnotations.value();
int length = joinColumnOrFormulaAnnotations.length;
if ( length == 0 ) {
- throw new AnnotationException( "Cannot bind an empty @JoinColumnsOrFormulas" );
+ throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData )
+ + "' has an empty '@JoinColumnsOrFormulas' annotation" );
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/ComponentPropertyHolder.java b/hibernate-core/src/main/java/org/hibernate/cfg/ComponentPropertyHolder.java
index fb950dbbab..3296bd2a97 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/ComponentPropertyHolder.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/ComponentPropertyHolder.java
@@ -270,11 +270,9 @@ public class ComponentPropertyHolder extends AbstractPropertyHolder {
public void addProperty(Property prop, AnnotatedColumn[] columns, XClass declaringClass) {
//Ejb3Column.checkPropertyConsistency( ); //already called earlier
- /*
- * Check table matches between the component and the columns
- * if not, change the component table if no properties are set
- * if a property is set already the core cannot support that
- */
+ // Check table matches between the component and the columns
+ // if not, change the component table if no properties are set
+ // if a property is set already the core cannot support that
if (columns != null) {
Table table = columns[0].getTable();
if ( !table.equals( component.getTable() ) ) {
@@ -283,8 +281,9 @@ public class ComponentPropertyHolder extends AbstractPropertyHolder {
}
else {
throw new AnnotationException(
- "A component cannot hold properties split into 2 different tables: "
- + this.getPath()
+ "Embeddable class '" + component.getComponentClassName()
+ + "' has properties mapped to two different tables"
+ + " (all properties of the embeddable class must map to the same table)"
);
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/CopyIdentifierComponentSecondPass.java b/hibernate-core/src/main/java/org/hibernate/cfg/CopyIdentifierComponentSecondPass.java
index 7117bd695b..814dfc4c79 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/CopyIdentifierComponentSecondPass.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/CopyIdentifierComponentSecondPass.java
@@ -10,17 +10,16 @@ import java.util.Locale;
import java.util.Map;
import org.hibernate.AnnotationException;
-import org.hibernate.AssertionFailure;
import org.hibernate.MappingException;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.boot.model.relational.Database;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.internal.util.MutableInteger;
-import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.mapping.BasicValue;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.Component;
+import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Selectable;
@@ -38,18 +37,20 @@ public class CopyIdentifierComponentSecondPass extends FkSecondPass {
private static final Logger log = Logger.getLogger( CopyIdentifierComponentSecondPass.class );
private final String referencedEntityName;
+ private final String propertyName;
private final Component component;
private final MetadataBuildingContext buildingContext;
private final AnnotatedJoinColumn[] joinColumns;
public CopyIdentifierComponentSecondPass(
Component comp,
- String referencedEntityName,
+ String referencedEntityName, String propertyName,
AnnotatedJoinColumn[] joinColumns,
MetadataBuildingContext buildingContext) {
super( comp, joinColumns );
this.component = comp;
this.referencedEntityName = referencedEntityName;
+ this.propertyName = propertyName;
this.buildingContext = buildingContext;
this.joinColumns = joinColumns;
}
@@ -68,17 +69,26 @@ public class CopyIdentifierComponentSecondPass extends FkSecondPass {
@Override
public void doSecondPass(Map persistentClasses) throws MappingException {
PersistentClass referencedPersistentClass = persistentClasses.get( referencedEntityName );
- // TODO better error names
if ( referencedPersistentClass == null ) {
- throw new AnnotationException( "Unknown entity name: " + referencedEntityName );
+ // TODO: much better error message if this is something that can really happen!
+ throw new AnnotationException( "Unknown entity name '" + referencedEntityName + "'");
}
- if ( ! ( referencedPersistentClass.getIdentifier() instanceof Component ) ) {
- throw new AssertionFailure(
- "Unexpected identifier type on the referenced entity when mapping a @MapsId: "
- + referencedEntityName
+ KeyValue identifier = referencedPersistentClass.getIdentifier();
+ if ( !(identifier instanceof Component) ) {
+ // The entity with the @MapsId annotation has a composite
+ // id type, but the referenced entity has a basic-typed id.
+ // Therefore, the @MapsId annotation should have specified
+ // a property of the composite id that has the foreign key
+ throw new AnnotationException(
+ "Missing 'value' in '@MapsId' annotation of association '" + propertyName
+ + "' of entity '" + component.getOwner().getEntityName()
+ + "' with composite identifier type"
+ + " ('@MapsId' must specify a property of the '@EmbeddedId' class which has the foreign key of '"
+ + referencedEntityName + "')"
);
}
- Component referencedComponent = (Component) referencedPersistentClass.getIdentifier();
+
+ Component referencedComponent = (Component) identifier;
//prepare column name structure
boolean isExplicitReference = true;
@@ -184,22 +194,24 @@ public class CopyIdentifierComponentSecondPass extends FkSecondPass {
String logicalColumnName = null;
if ( isExplicitReference ) {
logicalColumnName = column.getName();
- //JPA 2 requires referencedColumnNames to be case insensitive
+ //JPA 2 requires referencedColumnNames to be case-insensitive
joinColumn = columnByReferencedName.get( logicalColumnName.toLowerCase(Locale.ROOT ) );
}
else {
joinColumn = columnByReferencedName.get( String.valueOf( index.get() ) );
index.getAndIncrement();
}
- if ( joinColumn == null && ! joinColumns[0].isNameDeferred() ) {
+ if ( joinColumn == null && !joinColumns[0].isNameDeferred() ) {
throw new AnnotationException(
- isExplicitReference ?
- "Unable to find column reference in the @MapsId mapping: " + logicalColumnName :
- "Implicit column reference in the @MapsId mapping fails, try to use explicit referenceColumnNames: " + referencedEntityName
+ "Property '" + propertyName
+ + "' of entity '" + component.getOwner().getEntityName()
+ + "' must have a '@JoinColumn' which references the foreign key column '"
+ + logicalColumnName + "'"
);
}
- final String columnName = joinColumn == null || joinColumn.isNameDeferred() ? "tata_" + column.getName() : joinColumn
- .getName();
+ final String columnName = joinColumn == null || joinColumn.isNameDeferred()
+ ? "tata_" + column.getName()
+ : joinColumn.getName();
final Database database = buildingContext.getMetadataCollector().getDatabase();
final PhysicalNamingStrategy physicalNamingStrategy = buildingContext.getBuildingOptions().getPhysicalNamingStrategy();
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/IndexOrUniqueKeySecondPass.java b/hibernate-core/src/main/java/org/hibernate/cfg/IndexOrUniqueKeySecondPass.java
index 625951f70c..01d28db798 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/IndexOrUniqueKeySecondPass.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/IndexOrUniqueKeySecondPass.java
@@ -103,7 +103,8 @@ public class IndexOrUniqueKeySecondPass implements SecondPass {
);
if ( column == null ) {
throw new AnnotationException(
- "@Index references a unknown column: " + columnName
+ "Table '" + table.getName() + "' has no column named '" + columnName
+ + "' matching the column specified in '@Index'"
);
}
if ( unique ) {
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/InheritanceState.java b/hibernate-core/src/main/java/org/hibernate/cfg/InheritanceState.java
index f3aa431b83..bb555ea55a 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/InheritanceState.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/InheritanceState.java
@@ -227,7 +227,8 @@ public class InheritanceState {
}
if ( idPropertyCount == 0 && !inheritanceState.hasParents() ) {
- throw new AnnotationException( "No identifier specified for entity: " + clazz.getName() );
+ throw new AnnotationException( "Entity '" + clazz.getName() + "' has no identifier"
+ + " (every '@Entity' class must declare or inherit at least one '@Id' or '@EmbeddedId' property)" );
}
elements.trimToSize();
elementsToProcess = new ElementsToProcess( elements, idPropertyCount );
@@ -262,7 +263,8 @@ public class InheritanceState {
}
}
}
- throw new AnnotationException( "No identifier specified for entity: " + clazz );
+ throw new AnnotationException( "Entity '" + clazz.getName() + "' has no identifier"
+ + " (every '@Entity' class must declare or inherit at least one '@Id' or '@EmbeddedId' property)" );
}
private void getMappedSuperclassesTillNextEntityOrdered() {
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java b/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java
index 467bf2b79c..cb6bc42e22 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java
@@ -18,7 +18,6 @@ import org.hibernate.annotations.NotFoundAction;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.cfg.annotations.PropertyBinder;
-import org.hibernate.internal.util.StringHelper;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.DependantValue;
@@ -31,6 +30,7 @@ import org.hibernate.mapping.SortableValue;
import org.hibernate.type.ForeignKeyDirection;
import static org.hibernate.cfg.BinderHelper.findPropertyByName;
+import static org.hibernate.cfg.BinderHelper.getPath;
import static org.hibernate.cfg.BinderHelper.isEmptyAnnotationValue;
import static org.hibernate.internal.util.StringHelper.qualify;
@@ -125,12 +125,10 @@ public class OneToOneSecondPass implements SecondPass {
Property prop = binder.makeProperty();
prop.setOptional( optional );
if ( isEmptyAnnotationValue( mappedBy ) ) {
- /*
- * we need to check if the columns are in the right order
- * if not, then we need to create a many to one and formula
- * but actually, since entities linked by a one to one need
- * to share the same composite id class, this cannot happen in hibernate
- */
+ // we need to check if the columns are in the right order
+ // if not, then we need to create a many to one and formula
+ // but actually, since entities linked by a one to one need
+ // to share the same composite id class, this cannot happen in hibernate
boolean rightOrder = true;
if ( rightOrder ) {
@@ -154,26 +152,21 @@ public class OneToOneSecondPass implements SecondPass {
else {
value.setMappedByProperty( mappedBy );
PersistentClass otherSide = persistentClasses.get( value.getReferencedEntityName() );
+ if ( otherSide == null ) {
+ throw new MappingException( "Association '" + getPath( propertyHolder, inferredData )
+ + "' targets unknown entity type '" + value.getReferencedEntityName() + "'" );
+ }
Property otherSideProperty;
try {
- if ( otherSide == null ) {
- throw new MappingException( "Unable to find entity: " + value.getReferencedEntityName() );
- }
otherSideProperty = findPropertyByName( otherSide, mappedBy );
}
catch (MappingException e) {
- throw new AnnotationException(
- "Unknown mappedBy in: " + qualify( ownerEntity, ownerProperty )
- + ", referenced property unknown: "
- + qualify( value.getReferencedEntityName(), mappedBy )
- );
+ otherSideProperty = null;
}
if ( otherSideProperty == null ) {
- throw new AnnotationException(
- "Unknown mappedBy in: " + qualify( ownerEntity, ownerProperty )
- + ", referenced property unknown: "
- + qualify( value.getReferencedEntityName(), mappedBy )
- );
+ throw new AnnotationException( "Association '" + getPath( propertyHolder, inferredData )
+ + "' is 'mappedBy' a property named '" + mappedBy
+ + "' which does not exist in the target entity type '" + value.getReferencedEntityName() + "'" );
}
if ( otherSideProperty.getValue() instanceof OneToOne ) {
propertyHolder.addProperty( prop, inferredData.getDeclaringClass() );
@@ -228,7 +221,9 @@ public class OneToOneSecondPass implements SecondPass {
// HHH-6813
// Foo: @Id long id, @OneToOne(mappedBy="foo") Bar bar
// Bar: @Id @OneToOne Foo foo
- boolean referenceToPrimaryKey = ( mappedBy == null ) || otherSide.getIdentifier() instanceof Component && ! ( (Component) otherSide.getIdentifier() ).hasProperty( mappedBy ) ;
+ boolean referenceToPrimaryKey = mappedBy == null
+ || otherSide.getIdentifier() instanceof Component
+ && ! ( (Component) otherSide.getIdentifier() ).hasProperty( mappedBy );
value.setReferenceToPrimaryKey( referenceToPrimaryKey );
String propertyRef = value.getReferencedPropertyName();
@@ -240,14 +235,10 @@ public class OneToOneSecondPass implements SecondPass {
}
}
else {
- throw new AnnotationException(
- "Referenced property not a (One|Many)ToOne: "
- + qualify(
- otherSide.getEntityName(), mappedBy
- )
- + " in mappedBy of "
- + qualify( ownerEntity, ownerProperty )
- );
+ throw new AnnotationException( "Association '" + getPath( propertyHolder, inferredData )
+ + "' is 'mappedBy' a property named '" + mappedBy
+ + "' of the target entity type '" + value.getReferencedEntityName()
+ + "' which is not a '@OneToOne' or '@ManyToOne' association" );
}
}
value.sortProperties();
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/PkDrivenByDefaultMapsIdSecondPass.java b/hibernate-core/src/main/java/org/hibernate/cfg/PkDrivenByDefaultMapsIdSecondPass.java
index 56221add63..6835d2382d 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/PkDrivenByDefaultMapsIdSecondPass.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/PkDrivenByDefaultMapsIdSecondPass.java
@@ -44,9 +44,8 @@ public class PkDrivenByDefaultMapsIdSecondPass extends FkSecondPass {
public void doSecondPass(Map persistentClasses) throws MappingException {
PersistentClass referencedEntity = persistentClasses.get( referencedEntityName );
if ( referencedEntity == null ) {
- throw new AnnotationException(
- "Unknown entity name: " + referencedEntityName
- );
+ // TODO: much better error message if this is something that can really happen!
+ throw new AnnotationException( "Unknown entity name '" + referencedEntityName + "'" );
}
TableBinder.linkJoinColumnWithValueOverridingNameIfImplicit(
referencedEntity,
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/PropertyContainer.java b/hibernate-core/src/main/java/org/hibernate/cfg/PropertyContainer.java
index 76beef015c..700a017432 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/PropertyContainer.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/PropertyContainer.java
@@ -10,8 +10,6 @@
package org.hibernate.cfg;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -241,12 +239,12 @@ class PropertyContainer {
}
private static List verifyAndInitializePersistentAttributes(XClass xClass, Map localAttributeMap) {
- ArrayList output = new ArrayList( localAttributeMap.size() );
+ ArrayList output = new ArrayList<>( localAttributeMap.size() );
for ( XProperty xProperty : localAttributeMap.values() ) {
- if ( !xProperty.isTypeResolved() && !discoverTypeWithoutReflection( xProperty ) ) {
- String msg = "Property " + StringHelper.qualify( xClass.getName(), xProperty.getName() ) +
- " has an unbound type and no explicit target entity. Resolve this Generic usage issue" +
- " or set an explicit target attribute (eg @OneToMany(target=) or use an explicit @Type";
+ if ( !xProperty.isTypeResolved() && !discoverTypeWithoutReflection( xClass, xProperty ) ) {
+ String msg = "Property '" + StringHelper.qualify( xClass.getName(), xProperty.getName() ) +
+ "' has an unbound type and no explicit target entity (resolve this generics usage issue" +
+ " or set an explicit target attribute with '@OneToMany(target=)' or use an explicit '@Type')";
throw new AnnotationException( msg );
}
output.add( xProperty );
@@ -340,46 +338,47 @@ class PropertyContainer {
return classDefinedAccessType;
}
- private static boolean discoverTypeWithoutReflection(XProperty p) {
- if ( p.isAnnotationPresent( OneToOne.class ) && !p.getAnnotation( OneToOne.class )
+ private static boolean discoverTypeWithoutReflection(XClass clazz, XProperty property) {
+ if ( property.isAnnotationPresent( OneToOne.class ) && !property.getAnnotation( OneToOne.class )
.targetEntity()
.equals( void.class ) ) {
return true;
}
- else if ( p.isAnnotationPresent( OneToMany.class ) && !p.getAnnotation( OneToMany.class )
+ else if ( property.isAnnotationPresent( OneToMany.class ) && !property.getAnnotation( OneToMany.class )
.targetEntity()
.equals( void.class ) ) {
return true;
}
- else if ( p.isAnnotationPresent( ManyToOne.class ) && !p.getAnnotation( ManyToOne.class )
+ else if ( property.isAnnotationPresent( ManyToOne.class ) && !property.getAnnotation( ManyToOne.class )
.targetEntity()
.equals( void.class ) ) {
return true;
}
- else if ( p.isAnnotationPresent( ManyToMany.class ) && !p.getAnnotation( ManyToMany.class )
+ else if ( property.isAnnotationPresent( ManyToMany.class ) && !property.getAnnotation( ManyToMany.class )
.targetEntity()
.equals( void.class ) ) {
return true;
}
- else if ( p.isAnnotationPresent( org.hibernate.annotations.Any.class ) ) {
+ else if ( property.isAnnotationPresent( org.hibernate.annotations.Any.class ) ) {
return true;
}
- else if ( p.isAnnotationPresent( ManyToAny.class ) ) {
- if ( !p.isCollection() && !p.isArray() ) {
- throw new AnnotationException( "@ManyToAny used on a non collection non array property: " + p.getName() );
+ else if ( property.isAnnotationPresent( ManyToAny.class ) ) {
+ if ( !property.isCollection() && !property.isArray() ) {
+ throw new AnnotationException( "Property '" + StringHelper.qualify( clazz.getName(), property.getName() )
+ + "' annotated '@ManyToAny' is neither a collection nor an array" );
}
return true;
}
- else if ( p.isAnnotationPresent( Basic.class ) ) {
+ else if ( property.isAnnotationPresent( Basic.class ) ) {
return true;
}
- else if ( p.isAnnotationPresent( Type.class ) ) {
+ else if ( property.isAnnotationPresent( Type.class ) ) {
return true;
}
- else if ( p.isAnnotationPresent( JavaType.class ) ) {
+ else if ( property.isAnnotationPresent( JavaType.class ) ) {
return true;
}
- else if ( p.isAnnotationPresent( Target.class ) ) {
+ else if ( property.isAnnotationPresent( Target.class ) ) {
return true;
}
return false;
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/ToOneFkSecondPass.java b/hibernate-core/src/main/java/org/hibernate/cfg/ToOneFkSecondPass.java
index 3268b9080b..6e339ee1b4 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/ToOneFkSecondPass.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/ToOneFkSecondPass.java
@@ -93,12 +93,8 @@ public class ToOneFkSecondPass extends FkSecondPass {
ManyToOne manyToOne = (ManyToOne) value;
PersistentClass ref = persistentClasses.get( manyToOne.getReferencedEntityName() );
if ( ref == null ) {
- throw new AnnotationException(
- "@OneToOne or @ManyToOne on "
- + StringHelper.qualify( entityClassName, path )
- + " references an unknown entity: "
- + manyToOne.getReferencedEntityName()
- );
+ throw new AnnotationException( "Association '" + StringHelper.qualify( entityClassName, path )
+ + "' targets an unknown entity named '" + manyToOne.getReferencedEntityName() + "'" );
}
manyToOne.setPropertyName( path );
createSyntheticPropertyReference( columns, ref, null, manyToOne, false, buildingContext );
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/BasicValueBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/BasicValueBinder.java
index 9e6bffb1b5..c6389cad65 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/BasicValueBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/BasicValueBinder.java
@@ -8,7 +8,6 @@ package org.hibernate.cfg.annotations;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -132,7 +131,7 @@ public class BasicValueBinder implements JdbcTypeIndicators {
private String explicitBasicTypeName;
private Class extends UserType>> explicitCustomType;
- private Map explicitLocalTypeParams;
+ private Map explicitLocalTypeParams;
private Function explicitJdbcTypeAccess;
private Function explicitJavaTypeAccess;
@@ -302,9 +301,9 @@ public class BasicValueBinder implements JdbcTypeIndicators {
throw new AssertionFailure( "`BasicValueBinder#setColumns` should be called before `BasicValueBinder#setType`" );
}
- if ( columns.length != 1 ) {
- throw new AssertionFailure( "Expecting just one column, but found `" + Arrays.toString( columns ) + "`" );
- }
+// if ( columns.length != 1 ) {
+// throw new AssertionFailure( "Expecting just one column, but found `" + Arrays.toString( columns ) + "`" );
+// }
final XClass modelTypeXClass = isArray
? modelXProperty.getElementClass()
@@ -377,8 +376,7 @@ public class BasicValueBinder implements JdbcTypeIndicators {
this.explicitLocalTypeParams = extractTypeParams( params );
}
- @SuppressWarnings("unchecked")
- private Map extractTypeParams(Parameter[] parameters) {
+ private Map extractTypeParams(Parameter[] parameters) {
if ( parameters == null || parameters.length == 0 ) {
return Collections.emptyMap();
}
@@ -387,7 +385,7 @@ public class BasicValueBinder implements JdbcTypeIndicators {
return Collections.singletonMap( parameters[0].name(), parameters[0].value() );
}
- final Map map = new HashMap();
+ final Map map = new HashMap<>();
for ( Parameter parameter: parameters ) {
map.put( parameter.name(), parameter.value() );
}
@@ -740,7 +738,7 @@ public class BasicValueBinder implements JdbcTypeIndicators {
else {
throw new AnnotationException(
String.format(
- "Attribute [%s.%s] was annotated as enumerated, but its java type is not an enum [%s]",
+ "Property '%s.%s' is annotated '@Enumerated' but its type '%s' is not an enum",
declaringClassName,
attributeDescriptor.getName(),
attributeType.getName()
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java
index 12b1850b84..a731290ff6 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java
@@ -199,7 +199,7 @@ public abstract class CollectionBinder {
PropertyHolder propertyHolder;
private int batchSize;
private String mappedBy;
- private XClass collectionType;
+ private XClass collectionElementType;
private XClass targetEntity;
private AnnotatedJoinColumn[] inverseJoinColumns;
private String cascadeStrategy;
@@ -261,19 +261,16 @@ public abstract class CollectionBinder {
final ElementCollection elementCollectionAnn = property.getAnnotation( ElementCollection.class );
if ( ( oneToManyAnn != null || manyToManyAnn != null || elementCollectionAnn != null )
- && isToManyAssociationWithinEmbeddableCollection(propertyHolder) ) {
- throw new AnnotationException(
- "@OneToMany, @ManyToMany or @ElementCollection cannot be used inside an @Embeddable that is also contained within an @ElementCollection: "
- + getPath(propertyHolder, inferredData)
- );
+ && isToManyAssociationWithinEmbeddableCollection( propertyHolder ) ) {
+ String ann = oneToManyAnn!=null ? "'@OneToMany'" : manyToManyAnn!=null ? "'@ManyToMany'" : "'@ElementCollection'";
+ throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData ) +
+ "' belongs to an '@Embeddable' class that is contained in an '@ElementCollection' and may not be a " + ann );
}
if ( property.isAnnotationPresent( OrderColumn.class )
&& manyToManyAnn != null && !manyToManyAnn.mappedBy().isEmpty() ) {
- throw new AnnotationException(
- "Explicit @OrderColumn on inverse side of @ManyToMany is illegal: "
- + getPath(propertyHolder, inferredData)
- );
+ throw new AnnotationException("Collection '" + getPath( propertyHolder, inferredData ) +
+ "' is the unowned side of a bidirectional '@ManyToMany' and may not have an '@OrderColumn'");
}
final IndexColumn indexColumn = IndexColumn.fromAnnotations(
@@ -305,7 +302,7 @@ public abstract class CollectionBinder {
NotFound notFound = property.getAnnotation( NotFound.class );
collectionBinder.setNotFoundAction( notFound == null ? null : notFound.action() );
- collectionBinder.setCollectionType( inferredData.getProperty().getElementClass() );
+ collectionBinder.setElementType( inferredData.getProperty().getElementClass() );
collectionBinder.setAccessType( inferredData.getDefaultAccess() );
//do not use "element" if you are a JPA 2 @ElementCollection, only for legacy Hibernate mappings
@@ -403,10 +400,8 @@ public abstract class CollectionBinder {
//TODO enhance exception with @ManyToAny and @CollectionOfElements
if ( oneToManyAnn != null && manyToManyAnn != null ) {
- throw new AnnotationException(
- "@OneToMany and @ManyToMany on the same property is not allowed: "
- + propertyHolder.getEntityName() + "." + inferredData.getPropertyName()
- );
+ throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData )
+ + "' is annotated both '@OneToMany' and '@ManyToMany'" );
}
String mappedBy = null;
ReflectionManager reflectionManager = context.getBootstrapContext().getReflectionManager();
@@ -563,10 +558,8 @@ public abstract class CollectionBinder {
index++;
}
if ( property.isAnnotationPresent( MapKeyJoinColumn.class ) ) {
- throw new AnnotationException(
- "@MapKeyJoinColumn and @MapKeyJoinColumns used on the same property: "
- + getPath(propertyHolder, inferredData)
- );
+ throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData )
+ + "' is annotated both '@MapKeyJoinColumn' and '@MapKeyJoinColumns'" );
}
return joinKeyColumns;
}
@@ -1049,7 +1042,7 @@ public abstract class CollectionBinder {
throw new AnnotationException(
String.format(
Locale.ROOT,
- "Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: %s.%s",
+ "Property '%s.%s' is not a collection and may not be a '@OneToMany', '@ManyToMany', or '@ElementCollection'",
property.getDeclaringClass().getName(),
property.getName()
)
@@ -1075,9 +1068,17 @@ public abstract class CollectionBinder {
this.tableBinder = tableBinder;
}
+ /*
+ @deprecated : Use {@link #setElementType(XClass)} instead.
+ */
+ @Deprecated(since = "6.1")
public void setCollectionType(XClass collectionType) {
// NOTE: really really badly named. This is actually NOT the collection-type, but rather the collection-element-type!
- this.collectionType = collectionType;
+ this.collectionElementType = collectionType;
+ }
+
+ public void setElementType(XClass collectionElementType) {
+ this.collectionElementType = collectionElementType;
}
public void setTargetEntity(XClass targetEntity) {
@@ -1108,12 +1109,8 @@ public abstract class CollectionBinder {
if ( property.isAnnotationPresent( MapKeyColumn.class )
&& mapKeyPropertyName != null ) {
- throw new AnnotationException(
- "Cannot mix @jakarta.persistence.MapKey and @MapKeyColumn or @org.hibernate.annotations.MapKey "
- + "on the same collection: " + qualify(
- propertyHolder.getPath(), propertyName
- )
- );
+ throw new AnnotationException( "Collection '" + qualify( propertyHolder.getPath(), propertyName )
+ + "' is annotated both '@MapKey' and '@MapKeyColumn'" );
}
bindExplicitTypes();
@@ -1154,7 +1151,7 @@ public abstract class CollectionBinder {
private void scheduleSecondPass(boolean isMappedBy, InFlightMetadataCollector metadataCollector) {
//many to many may need some second pass information
if ( !oneToMany && isMappedBy ) {
- metadataCollector.addMappedBy( getCollectionType().getName(), mappedBy, propertyName );
+ metadataCollector.addMappedBy( getElementType().getName(), mappedBy, propertyName );
}
if ( inheritanceStatePerClass == null) {
@@ -1170,7 +1167,7 @@ public abstract class CollectionBinder {
mapKeyManyToManyColumns,
isEmbedded,
property,
- getCollectionType(),
+ getElementType(),
notFoundAction,
oneToMany,
tableBinder,
@@ -1185,8 +1182,9 @@ public abstract class CollectionBinder {
Persister persisterAnn = property.getAnnotation( Persister.class );
if ( persisterAnn != null ) {
Class clazz = persisterAnn.impl();
- if ( !CollectionPersister.class.isAssignableFrom(clazz) ) {
- throw new AnnotationException( "persister class does not implement CollectionPersister: " + clazz.getName() );
+ if ( !CollectionPersister.class.isAssignableFrom( clazz ) ) {
+ throw new AnnotationException( "Persister class '" + clazz.getName()
+ + "' does not implement 'CollectionPersister'" );
}
collection.setCollectionPersisterClass( clazz );
}
@@ -1224,12 +1222,18 @@ public abstract class CollectionBinder {
private void detectMappedByProblem(boolean isMappedBy) {
if (isMappedBy
- && (property.isAnnotationPresent( JoinColumn.class )
- || property.isAnnotationPresent( JoinColumns.class )
- || propertyHolder.getJoinTable( property ) != null ) ) {
- String message = "Associations marked as mappedBy must not define database mappings like @JoinTable or @JoinColumn: ";
- message += qualify( propertyHolder.getPath(), propertyName );
- throw new AnnotationException( message );
+ && ( property.isAnnotationPresent( JoinColumn.class )
+ || property.isAnnotationPresent( JoinColumns.class ) ) ) {
+ throw new AnnotationException( "Association '"
+ + qualify( propertyHolder.getPath(), propertyName )
+ + "' is 'mappedBy' another entity and may not specify the '@JoinColumn'" );
+ }
+
+ if (isMappedBy
+ && propertyHolder.getJoinTable( property ) != null ) {
+ throw new AnnotationException( "Association '"
+ + qualify( propertyHolder.getPath(), propertyName )
+ + "' is 'mappedBy' another entity and may not specify the '@JoinTable'" );
}
if (!isMappedBy
@@ -1237,9 +1241,9 @@ public abstract class CollectionBinder {
&& property.isAnnotationPresent( OnDelete.class )
&& !property.isAnnotationPresent( JoinColumn.class )
&& !property.isAnnotationPresent( JoinColumns.class )) {
- String message = "Unidirectional one-to-many associations annotated with @OnDelete must define @JoinColumn: ";
- message += qualify( propertyHolder.getPath(), propertyName );
- throw new AnnotationException( message );
+ throw new AnnotationException( "Unidirectional '@OneToMany' association '"
+ + qualify( propertyHolder.getPath(), propertyName )
+ + "' is annotated '@OnDelete' and must explicitly specify a '@JoinColumn'" );
}
}
@@ -1358,10 +1362,11 @@ public abstract class CollectionBinder {
catch (Exception e) {
throw new AnnotationException(
String.format(
- "Could not instantiate comparator class [%s] for %s",
+ "Could not instantiate comparator class '%s' for collection '%s'",
comparatorClass.getName(),
safeCollectionRole()
- )
+ ),
+ e
);
}
}
@@ -1371,10 +1376,10 @@ public abstract class CollectionBinder {
return new AnnotationException(
String.format(
Locale.ROOT,
- "Illegal combination of ordering and sorting annotations (`%s`) - only one of `@%s` and `@%s` may be used",
+ "Collection '%s' is annotated both '@%s' and '@%s'",
+ safeCollectionRole(),
jakarta.persistence.OrderBy.class.getName(),
- OrderBy.class.getName(),
- safeCollectionRole()
+ OrderBy.class.getName()
)
);
}
@@ -1383,7 +1388,7 @@ public abstract class CollectionBinder {
throw new AnnotationException(
String.format(
Locale.ROOT,
- "Illegal combination of ordering and sorting annotations (`%s`) - only one of `@%s`, `@%s`, `@%s` and `@%s` can be used",
+ "Collection '%s' is both sorted and ordered (only one of '@%s', '@%s', '@%s', and '@%s' may be used)",
safeCollectionRole(),
jakarta.persistence.OrderBy.class.getName(),
OrderBy.class.getName(),
@@ -1396,7 +1401,7 @@ public abstract class CollectionBinder {
private AnnotationException buildIllegalSortCombination() {
return new AnnotationException(
String.format(
- "Illegal combination of sorting annotations (`%s`) - only one of `@%s` and `@%s` can be used",
+ "Collection '%s' is annotated both '@%s' and '@%s'",
safeCollectionRole(),
SortNatural.class.getName(),
SortComparator.class.getName()
@@ -1483,15 +1488,14 @@ public abstract class CollectionBinder {
}
}
- private XClass getCollectionType() {
+ private XClass getElementType() {
if ( AnnotationBinder.isDefault( targetEntity, buildingContext ) ) {
- if ( collectionType != null ) {
- return collectionType;
+ if ( collectionElementType != null ) {
+ return collectionElementType;
}
else {
- String errorMsg = "Collection has neither generic type or OneToMany.targetEntity() defined: "
- + safeCollectionRole();
- throw new AnnotationException( errorMsg );
+ throw new AnnotationException( "Collection '" + safeCollectionRole()
+ + "' is declared with a raw type and has an explicit 'targetEntity'" );
}
}
else {
@@ -1508,7 +1512,7 @@ public abstract class CollectionBinder {
final AnnotatedJoinColumn[] mapKeyManyToManyColumns,
final boolean isEmbedded,
final XProperty property,
- final XClass collType,
+ final XClass elementType,
final NotFoundAction notFoundAction,
final boolean unique,
final TableBinder assocTableBinder,
@@ -1518,7 +1522,7 @@ public abstract class CollectionBinder {
public void secondPass(Map persistentClasses) throws MappingException {
bindStarToManySecondPass(
persistentClasses,
- collType,
+ elementType,
fkJoinColumns,
keyColumns,
inverseColumns,
@@ -1539,7 +1543,7 @@ public abstract class CollectionBinder {
*/
protected boolean bindStarToManySecondPass(
Map persistentClasses,
- XClass collType,
+ XClass elementType,
AnnotatedJoinColumn[] fkJoinColumns,
AnnotatedJoinColumn[] keyColumns,
AnnotatedJoinColumn[] inverseColumns,
@@ -1550,23 +1554,17 @@ public abstract class CollectionBinder {
TableBinder associationTableBinder,
NotFoundAction notFoundAction,
MetadataBuildingContext buildingContext) {
- PersistentClass persistentClass = persistentClasses.get( collType.getName() );
+ PersistentClass persistentClass = persistentClasses.get( elementType.getName() );
boolean reversePropertyInJoin = false;
if ( persistentClass != null && isNotEmpty( mappedBy ) ) {
try {
- reversePropertyInJoin = 0 != persistentClass.getJoinNumber(
- persistentClass.getRecursiveProperty( mappedBy )
- );
+ reversePropertyInJoin =
+ 0 != persistentClass.getJoinNumber( persistentClass.getRecursiveProperty( mappedBy ) );
}
catch (MappingException e) {
- throw new AnnotationException(
- "mappedBy references an unknown target entity property: " +
- collType + "." + this.mappedBy +
- " in " +
- collection.getOwnerEntityName() +
- "." +
- property.getName()
- );
+ throw new AnnotationException( "Collection '" + safeCollectionRole()
+ + "' is 'mappedBy' a property named '" + mappedBy
+ + "' which does not exist in the target entity '" + elementType.getName() + "'" );
}
}
if ( persistentClass != null
@@ -1581,7 +1579,7 @@ public abstract class CollectionBinder {
getCollection(),
persistentClasses,
fkJoinColumns,
- collType,
+ elementType,
cascadeDeleteEnabled,
notFoundAction,
buildingContext,
@@ -1598,7 +1596,7 @@ public abstract class CollectionBinder {
inverseColumns,
elementColumns,
isEmbedded,
- collType,
+ elementType,
notFoundAction,
unique,
cascadeDeleteEnabled,
@@ -1797,8 +1795,8 @@ public abstract class CollectionBinder {
}
else {
throw new AnnotationException(
- "Illegal use of @WhereJoinTable on an association without join table: "
- + qualify( propertyHolder.getPath(), propertyName )
+ "Collection '" + qualify( propertyHolder.getPath(), propertyName )
+ + "' is an association with no join table and may not have a 'WhereJoinTable'"
);
}
}
@@ -1807,22 +1805,25 @@ public abstract class CollectionBinder {
private void addFilter(boolean hasAssociationTable, FilterJoinTable filter) {
if ( hasAssociationTable ) {
final String condition;
+ final String name = filter.name();
if ( isEmpty( filter.condition() ) ) {
- final FilterDefinition filterDefinition = buildingContext.getMetadataCollector()
- .getFilterDefinition( filter.name() );
- if ( filterDefinition == null ) {
- throw new AnnotationException(
- "@FilterJoinTable on an association without condition attribute and without an any @FilterDef with a default condition"
- + qualify( propertyHolder.getPath(), propertyName )
- );
+ final FilterDefinition definition = buildingContext.getMetadataCollector().getFilterDefinition( name );
+ if ( definition == null ) {
+ throw new AnnotationException( "Collection '" + qualify( propertyHolder.getPath(), propertyName )
+ + "' has a '@FilterJoinTable' for an undefined filter named '" + name + "'" );
+ }
+ condition = definition.getDefaultFilterCondition();
+ if ( isEmpty( condition ) ) {
+ throw new AnnotationException( "Collection '" + qualify( propertyHolder.getPath(), propertyName )
+ + "' has a '@FilterJoinTable' with no 'condition' and no default condition was given by the '@FilterDef' named '"
+ + name + "'");
}
- condition = filterDefinition.getDefaultFilterCondition();
}
else {
condition = filter.condition();
}
collection.addFilter(
- filter.name(),
+ name,
condition,
filter.deduceAliasInjectionPoints(),
toAliasTableMap( filter.aliases() ),
@@ -1830,31 +1831,32 @@ public abstract class CollectionBinder {
);
}
else {
- throw new AnnotationException(
- "Illegal use of @FilterJoinTable on an association without join table: "
- + qualify( propertyHolder.getPath(), propertyName )
- );
+ throw new AnnotationException( "Collection '" + qualify( propertyHolder.getPath(), propertyName )
+ + "' is an association with no join table and may not have a '@FilterJoinTable'" );
}
}
private String getCondition(Filter filter) {
//set filtering
- String name = filter.name();
- String cond = filter.condition();
- return getCondition( cond, name );
- }
-
- private String getCondition(String cond, String name) {
- if ( isEmptyAnnotationValue( cond ) ) {
- cond = buildingContext.getMetadataCollector().getFilterDefinition( name ).getDefaultFilterCondition();
- if ( isEmpty( cond ) ) {
- throw new AnnotationException(
- "no filter condition found for filter " + name + " in "
- + qualify( propertyHolder.getPath(), propertyName )
- );
+ final String condition = filter.condition();
+ if ( isEmptyAnnotationValue( condition ) ) {
+ final String name = filter.name();
+ final FilterDefinition definition = buildingContext.getMetadataCollector().getFilterDefinition( name );
+ if ( definition == null ) {
+ throw new AnnotationException( "Collection '" + qualify( propertyHolder.getPath(), propertyName )
+ + "' has a '@Filter' for an undefined filter named '" + name + "'" );
}
+ final String defaultCondition = definition.getDefaultFilterCondition();
+ if ( isEmpty( defaultCondition ) ) {
+ throw new AnnotationException( "Collection '" + qualify( propertyHolder.getPath(), propertyName ) +
+ "' has a '@Filter' with no 'condition' and no default condition was given by the '@FilterDef' named '"
+ + name + "'" );
+ }
+ return defaultCondition;
+ }
+ else {
+ return condition;
}
- return cond;
}
public void setCache(Cache cacheAnn) {
@@ -2070,7 +2072,7 @@ public abstract class CollectionBinder {
AnnotatedJoinColumn[] inverseJoinColumns,
AnnotatedColumn[] elementColumns,
boolean isEmbedded,
- XClass collType,
+ XClass elementType,
NotFoundAction notFoundAction,
boolean unique,
boolean cascadeDeleteEnabled,
@@ -2083,7 +2085,7 @@ public abstract class CollectionBinder {
throw new IllegalArgumentException( "null was passed for argument property" );
}
- final PersistentClass collectionEntity = persistentClasses.get( collType.getName() );
+ final PersistentClass collectionEntity = persistentClasses.get( elementType.getName() );
final String hqlOrderBy = extractHqlOrderBy( jpaOrderBy );
boolean isCollectionOfEntities = collectionEntity != null;
@@ -2094,7 +2096,7 @@ public abstract class CollectionBinder {
detectManyToManyProblems(
collValue,
joinColumns,
- collType,
+ elementType,
property,
parentPropertyHolder,
isCollectionOfEntities,
@@ -2105,7 +2107,7 @@ public abstract class CollectionBinder {
handleUnownedManyToMany(
collValue,
joinColumns,
- collType,
+ elementType,
collectionEntity,
isCollectionOfEntities
);
@@ -2138,7 +2140,7 @@ public abstract class CollectionBinder {
if ( isCollectionOfEntities ) {
element = handleCollectionOfEntities(
collValue,
- collType,
+ elementType,
notFoundAction,
property,
buildingContext,
@@ -2160,7 +2162,7 @@ public abstract class CollectionBinder {
collValue,
elementColumns,
isEmbedded,
- collType,
+ elementType,
property,
parentPropertyHolder,
buildingContext,
@@ -2177,12 +2179,19 @@ public abstract class CollectionBinder {
}
- private void handleElementCollection(Collection collValue, AnnotatedColumn[] elementColumns, boolean isEmbedded, XClass collType, XProperty property, PropertyHolder parentPropertyHolder, MetadataBuildingContext buildingContext, String hqlOrderBy) {
+ private void handleElementCollection(
+ Collection collValue,
+ AnnotatedColumn[] elementColumns,
+ boolean isEmbedded,
+ XClass elementType,
+ XProperty property,
+ PropertyHolder parentPropertyHolder,
+ MetadataBuildingContext buildingContext,
+ String hqlOrderBy) {
XClass elementClass;
AnnotatedClassType classType;
-
CollectionPropertyHolder holder;
- if ( PRIMITIVE_NAMES.contains( collType.getName() ) ) {
+ if ( PRIMITIVE_NAMES.contains( elementType.getName() ) ) {
classType = AnnotatedClassType.NONE;
elementClass = null;
@@ -2196,7 +2205,7 @@ public abstract class CollectionBinder {
);
}
else {
- elementClass = collType;
+ elementClass = elementType;
classType = buildingContext.getMetadataCollector().getClassType( elementClass );
holder = PropertyHolderBuilder.buildPropertyHolder(
@@ -2289,7 +2298,7 @@ public abstract class CollectionBinder {
final BasicValueBinder elementBinder =
new BasicValueBinder( BasicValueBinder.Kind.COLLECTION_ELEMENT, buildingContext);
- elementBinder.setReturnedClassName( collType.getName() );
+ elementBinder.setReturnedClassName( elementType.getName() );
if ( elementColumns == null || elementColumns.length == 0 ) {
elementColumns = new AnnotatedColumn[1];
AnnotatedColumn column = new AnnotatedColumn();
@@ -2326,16 +2335,15 @@ public abstract class CollectionBinder {
private ManyToOne handleCollectionOfEntities(
Collection collValue,
- XClass collType,
+ XClass elementType,
NotFoundAction notFoundAction,
XProperty property,
MetadataBuildingContext buildingContext,
PersistentClass collectionEntity,
String hqlOrderBy) {
- ManyToOne element;
- element = new ManyToOne(buildingContext, collValue.getCollectionTable() );
+ ManyToOne element = new ManyToOne( buildingContext, collValue.getCollectionTable() );
collValue.setElement( element );
- element.setReferencedEntityName( collType.getName() );
+ element.setReferencedEntityName( elementType.getName() );
//element.setFetchMode( fetchMode );
//element.setLazy( fetchMode != FetchMode.JOIN );
//make the second join non lazy
@@ -2344,9 +2352,7 @@ public abstract class CollectionBinder {
element.setNotFoundAction( notFoundAction );
// as per 11.1.38 of JPA 2.0 spec, default to primary key if no column is specified by @OrderBy.
if ( hqlOrderBy != null ) {
- collValue.setManyToManyOrdering(
- buildOrderByClauseFromHql(hqlOrderBy, collectionEntity)
- );
+ collValue.setManyToManyOrdering( buildOrderByClauseFromHql( hqlOrderBy, collectionEntity ) );
}
final ForeignKey fk = property.getAnnotation( ForeignKey.class );
@@ -2379,7 +2385,12 @@ public abstract class CollectionBinder {
return element;
}
- private void handleManyToAny(Collection collValue, AnnotatedJoinColumn[] inverseJoinColumns, boolean cascadeDeleteEnabled, XProperty property, MetadataBuildingContext buildingContext) {
+ private void handleManyToAny(
+ Collection collValue,
+ AnnotatedJoinColumn[] inverseJoinColumns,
+ boolean cascadeDeleteEnabled,
+ XProperty property,
+ MetadataBuildingContext buildingContext) {
//@ManyToAny
//Make sure that collTyp is never used during the @ManyToAny branch: it will be set to void.class
final PropertyData inferredData = new PropertyInferredData(
@@ -2486,17 +2497,13 @@ public abstract class CollectionBinder {
private void handleUnownedManyToMany(
Collection collValue,
AnnotatedJoinColumn[] joinColumns,
- XClass collType,
+ XClass elementType,
PersistentClass collectionEntity,
boolean isCollectionOfEntities) {
if ( !isCollectionOfEntities) {
- throw new AnnotationException(
- "Collection of elements must not have mappedBy or association reference an unmapped entity: " +
- collValue.getOwnerEntityName() +
- "." +
- joinColumns[0].getPropertyName()
- );
+ throw new AnnotationException( "Association '" + safeCollectionRole()
+ + "' targets the type '" + elementType.getName() + "' which is not an '@Entity' type" );
}
Property otherSideProperty;
@@ -2504,14 +2511,12 @@ public abstract class CollectionBinder {
otherSideProperty = collectionEntity.getRecursiveProperty( joinColumns[0].getMappedBy() );
}
catch (MappingException e) {
- throw new AnnotationException(
- "mappedBy references an unknown target entity property: "
- + collType + "." + joinColumns[0].getMappedBy() + " in "
- + collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName()
- );
+ throw new AnnotationException( "Association '" + safeCollectionRole() +
+ "is 'mappedBy' a property named '" + mappedBy
+ + "' which does not exist in the target entity '" + elementType.getName() + "'" );
}
Table table = otherSideProperty.getValue() instanceof Collection
- ? ((Collection) otherSideProperty.getValue()).getCollectionTable()
+ ? ( (Collection) otherSideProperty.getValue() ).getCollectionTable()
: otherSideProperty.getValue().getTable();
//this is a collection on the other side
//This is a ToOne with a @JoinTable or a regular property
@@ -2526,7 +2531,7 @@ public abstract class CollectionBinder {
private void detectManyToManyProblems(
Collection collValue,
AnnotatedJoinColumn[] joinColumns,
- XClass collType,
+ XClass elementType,
XProperty property,
PropertyHolder parentPropertyHolder,
boolean isCollectionOfEntities,
@@ -2534,26 +2539,21 @@ public abstract class CollectionBinder {
if ( !isCollectionOfEntities) {
if ( property.isAnnotationPresent( ManyToMany.class ) || property.isAnnotationPresent( OneToMany.class ) ) {
- String path = collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName();
- throw new AnnotationException(
- "Use of @OneToMany or @ManyToMany targeting an unmapped class: " + path + "[" + collType + "]"
- );
+ throw new AnnotationException( "Association '" + safeCollectionRole()
+ + "' targets the type '" + elementType.getName() + "' which is not an '@Entity' type" );
}
else if (isManyToAny) {
- if ( parentPropertyHolder.getJoinTable(property) == null ) {
- String path = collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName();
- throw new AnnotationException(
- "@JoinTable is mandatory when @ManyToAny is used: " + path
- );
+ if ( parentPropertyHolder.getJoinTable( property ) == null ) {
+ throw new AnnotationException( "Association '" + safeCollectionRole()
+ + "' is a '@ManyToAny' and must specify a '@JoinTable'" );
}
}
else {
- JoinTable joinTableAnn = parentPropertyHolder.getJoinTable(property);
+ JoinTable joinTableAnn = parentPropertyHolder.getJoinTable( property );
if ( joinTableAnn != null && joinTableAnn.inverseJoinColumns().length > 0 ) {
- String path = collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName();
- throw new AnnotationException(
- "Use of @JoinTable.inverseJoinColumns targeting an unmapped class: " + path + "[" + collType + "]"
- );
+ throw new AnnotationException( "Association '" + safeCollectionRole()
+ + " has a '@JoinTable' with 'inverseJoinColumns' and targets the type '"
+ + elementType.getName() + "' which is not an '@Entity' type" );
}
}
}
@@ -2667,7 +2667,8 @@ public abstract class CollectionBinder {
);
}
catch (AnnotationException ex) {
- throw new AnnotationException( "Unable to map collection " + collValue.getOwner().getClassName() + "." + property.getName(), ex );
+ throw new AnnotationException( "Unable to map collection "
+ + collValue.getOwner().getClassName() + "." + property.getName(), ex );
}
DependantValue key = buildCollectionKey( collValue, joinColumns, cascadeDeleteEnabled,
buildingContext.getBuildingOptions().isNoConstraintByDefault(), property, propertyHolder, buildingContext );
@@ -2682,7 +2683,7 @@ public abstract class CollectionBinder {
this.cascadeDeleteEnabled = onDeleteCascade;
}
- private String safeCollectionRole() {
+ String safeCollectionRole() {
return propertyHolder != null ? propertyHolder.getEntityName() + "." + propertyName : "";
}
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java
index 84975d4419..65dba45a88 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java
@@ -260,7 +260,7 @@ public class EntityBinder {
final InheritanceState.ElementsToProcess elementsToProcess = inheritanceState.getElementsToProcess();
inheritanceState.postProcess( persistentClass, entityBinder );
- Set idPropertiesIfIdClass = handleIdClass(
+ final Set idPropertiesIfIdClass = handleIdClass(
persistentClass,
inheritanceState,
context,
@@ -360,7 +360,7 @@ public class EntityBinder {
final XClass classWithIdClass = inheritanceState.getClassWithIdClass( false );
if ( classWithIdClass != null ) {
final IdClass idClass = classWithIdClass.getAnnotation( IdClass.class );
- //noinspection unchecked
+ @SuppressWarnings("unchecked")
final XClass compositeClass = context.getBootstrapContext().getReflectionManager().toXClass( idClass.value() );
final PropertyData inferredData = new PropertyPreloadedData(
entityBinder.getPropertyAccessType(), "id", compositeClass
@@ -501,18 +501,14 @@ public class EntityBinder {
MetadataBuildingContext buildingContext,
Map inheritanceStatePerClass) {
- /*
- * Fill simple value and property since and Id is a property
- */
- PersistentClass persistentClass = propertyHolder.getPersistentClass();
+ // Fill simple value and property since and Id is a property
+ final PersistentClass persistentClass = propertyHolder.getPersistentClass();
if ( !(persistentClass instanceof RootClass) ) {
- throw new AnnotationException(
- "Unable to define/override @Id(s) on a subclass: "
- + propertyHolder.getEntityName()
- );
+ throw new AnnotationException( "Entity '" + persistentClass.getEntityName()
+ + "' is a subclass in an entity inheritance hierarchy and may not redefine the identifier of the root entity" );
}
- RootClass rootClass = (RootClass) persistentClass;
- Component id = AnnotationBinder.fillComponent(
+ final RootClass rootClass = (RootClass) persistentClass;
+ final Component id = AnnotationBinder.fillComponent(
propertyHolder,
inferredData,
baseInferredData,
@@ -529,10 +525,13 @@ public class EntityBinder {
);
id.setKey( true );
if ( rootClass.getIdentifier() != null ) {
- throw new AnnotationException( id.getComponentClassName() + " must not have @Id properties when used as an @EmbeddedId" );
+ throw new AssertionFailure( "Entity '" + persistentClass.getEntityName()
+ + "' has an '@IdClass' and may not have an identifier property" );
}
if ( id.getPropertySpan() == 0 ) {
- throw new AnnotationException( id.getComponentClassName() + " has no persistent id property" );
+ throw new AnnotationException( "Class '" + id.getComponentClassName()
+ + " is the '@IdClass' for the entity '" + persistentClass.getEntityName()
+ + "' but has no persistent properties" );
}
rootClass.setIdentifier( id );
@@ -926,19 +925,18 @@ public class EntityBinder {
InheritanceState.ElementsToProcess elementsToProcess,
Map inheritanceStatePerClass) {
- Set missingIdProperties = new HashSet<>( idPropertiesIfIdClass );
+ final Set missingIdProperties = new HashSet<>( idPropertiesIfIdClass );
for ( PropertyData propertyAnnotatedElement : elementsToProcess.getElements() ) {
String propertyName = propertyAnnotatedElement.getPropertyName();
if ( !idPropertiesIfIdClass.contains( propertyName ) ) {
boolean subclassAndSingleTableStrategy =
inheritanceState.getType() == InheritanceType.SINGLE_TABLE
&& inheritanceState.hasParents();
- Nullability nullability = subclassAndSingleTableStrategy
- ? Nullability.FORCED_NULL
- : Nullability.NO_CONSTRAINT;
AnnotationBinder.processElementAnnotations(
propertyHolder,
- nullability,
+ subclassAndSingleTableStrategy
+ ? Nullability.FORCED_NULL
+ : Nullability.NO_CONSTRAINT,
propertyAnnotatedElement,
classGenerators,
entityBinder,
@@ -955,15 +953,16 @@ public class EntityBinder {
}
if ( missingIdProperties.size() != 0 ) {
- StringBuilder missings = new StringBuilder();
+ final StringBuilder missings = new StringBuilder();
for ( String property : missingIdProperties ) {
- missings.append( property ).append( ", " );
+ if ( missings.length() > 0 ) {
+ missings.append(", ");
+ }
+ missings.append("'").append( property ).append( "'" );
}
- throw new AnnotationException(
- "Unable to find properties ("
- + missings.substring( 0, missings.length() - 2 )
- + ") in entity annotated with @IdClass:" + persistentClass.getEntityName()
- );
+ throw new AnnotationException( "Entity '" + persistentClass.getEntityName()
+ + "' has an '@IdClass' with properties " + missings
+ + " which do not match properties of the entity class" );
}
}
@@ -1292,10 +1291,15 @@ public class EntityBinder {
String condition = filter.condition();
if ( isEmptyAnnotationValue( condition ) ) {
final FilterDefinition definition = context.getMetadataCollector().getFilterDefinition( filterName );
- condition = definition == null ? null : definition.getDefaultFilterCondition();
+ if ( definition == null ) {
+ throw new AnnotationException( "Entity '" + name
+ + "' has a '@Filter' for an undefined filter named '" + filterName + "'" );
+ }
+ condition = definition.getDefaultFilterCondition();
if ( isEmpty( condition ) ) {
- throw new AnnotationException( "no filter condition found for filter "
- + filterName + " in " + this.name );
+ throw new AnnotationException( "Entity '" + name +
+ "' has a '@Filter' with no 'condition' and no default condition was given by the '@FilterDef' named '"
+ + filterName + "'" );
}
}
persistentClass.addFilter(
@@ -1329,7 +1333,8 @@ public class EntityBinder {
if ( persisterAnn != null ) {
Class clazz = persisterAnn.impl();
if ( !EntityPersister.class.isAssignableFrom(clazz) ) {
- throw new AnnotationException( "persister class does not implement EntityPersister: " + clazz.getName() );
+ throw new AnnotationException( "Persister class '" + clazz.getName()
+ + "' does not implement EntityPersister" );
}
persistentClass.setEntityPersisterClass( clazz );
}
@@ -1365,9 +1370,8 @@ public class EntityBinder {
persistentClass.setDiscriminatorValue( name );
}
else if ( "character".equals( discriminator.getType().getName() ) ) {
- throw new AnnotationException(
- "Using default @DiscriminatorValue for a discriminator of type CHAR is not safe"
- );
+ throw new AnnotationException( "Entity '" + name
+ + "' has a discriminator of character type and must specify its '@DiscriminatorValue'" );
}
else if ( "integer".equals( discriminator.getType().getName() ) ) {
persistentClass.setDiscriminatorValue( String.valueOf( name.hashCode() ) );
@@ -1527,9 +1531,8 @@ public class EntityBinder {
case "non-lazy":
return false;
default:
- throw new AnnotationException( "Unknown @Cache.include value [" + effectiveCache.include() + "] : "
- + annotatedClass.getName()
- );
+ throw new AnnotationException( "Class '" + annotatedClass.getName()
+ + "' has a '@Cache' with undefined option 'include=\"" + effectiveCache.include() + "\"'" );
}
}
@@ -2049,7 +2052,7 @@ public class EntityBinder {
public void processComplementaryTableDefinitions(org.hibernate.annotations.Table table) {
//comment and index are processed here
if ( table == null ) return;
- String appliedTable = table.appliesTo();
+ final String appliedTable = table.appliesTo();
Table hibTable = null;
for ( Table pcTable : persistentClass.getTableClosure() ) {
if ( pcTable.getQuotedName().equals( appliedTable ) ) {
@@ -2068,9 +2071,9 @@ public class EntityBinder {
}
}
if ( hibTable == null ) {
- throw new AnnotationException(
- "@org.hibernate.annotations.Table references an unknown table: " + appliedTable
- );
+ throw new AnnotationException( "Entity '" + name
+ + "' has a '@org.hibernate.annotations.Table' annotation which 'appliesTo' an unknown table named '"
+ + appliedTable + "'" );
}
if ( !isEmptyAnnotationValue( table.comment() ) ) {
hibTable.setComment( table.comment() );
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/IdBagBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/IdBagBinder.java
index b6f0b234cc..7240d420b1 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/IdBagBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/IdBagBinder.java
@@ -16,7 +16,6 @@ import org.hibernate.annotations.NotFoundAction;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.boot.spi.MetadataBuildingContext;
-import org.hibernate.cfg.BinderHelper;
import org.hibernate.cfg.AnnotatedColumn;
import org.hibernate.cfg.AnnotatedJoinColumn;
import org.hibernate.cfg.IdGeneratorResolverSecondPass;
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/ListBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/ListBinder.java
index f8672ec87a..1e1b3e188b 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/ListBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/ListBinder.java
@@ -22,7 +22,6 @@ import org.hibernate.cfg.PropertyHolder;
import org.hibernate.cfg.PropertyHolderBuilder;
import org.hibernate.cfg.SecondPass;
import org.hibernate.internal.CoreMessageLogger;
-import org.hibernate.internal.util.StringHelper;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.IndexBackref;
import org.hibernate.mapping.List;
@@ -73,7 +72,7 @@ public class ListBinder extends CollectionBinder {
final AnnotatedJoinColumn[] mapKeyManyToManyColumns,
final boolean isEmbedded,
final XProperty property,
- final XClass collType,
+ final XClass elementType,
final NotFoundAction notFoundAction,
final boolean unique,
final TableBinder assocTableBinder,
@@ -84,7 +83,7 @@ public class ListBinder extends CollectionBinder {
throws MappingException {
bindStarToManySecondPass(
persistentClasses,
- collType,
+ elementType,
fkJoinColumns,
keyColumns,
inverseColumns,
@@ -96,12 +95,12 @@ public class ListBinder extends CollectionBinder {
notFoundAction,
buildingContext
);
- bindIndex( property, collType, buildingContext );
+ bindIndex( property, elementType, buildingContext );
}
};
}
- private void bindIndex(XProperty property, XClass collType, final MetadataBuildingContext buildingContext) {
+ private void bindIndex(XProperty property, XClass elementType, final MetadataBuildingContext buildingContext) {
final PropertyHolder valueHolder = PropertyHolderBuilder.buildPropertyHolder(
collection,
qualify( collection.getRole(), "key" ),
@@ -120,7 +119,7 @@ public class ListBinder extends CollectionBinder {
final BasicValueBinder valueBinder = new BasicValueBinder( BasicValueBinder.Kind.LIST_INDEX, buildingContext );
valueBinder.setColumns( new AnnotatedColumn[] { indexColumn } );
valueBinder.setReturnedClassName( Integer.class.getName() );
- valueBinder.setType( property, collType, null, null );
+ valueBinder.setType( property, elementType, null, null );
// valueBinder.setExplicitType( "integer" );
SimpleValue indexValue = valueBinder.make();
indexColumn.linkWithValue( indexValue );
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/MapBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/MapBinder.java
index a12876baa6..03ca645cf6 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/MapBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/MapBinder.java
@@ -24,7 +24,6 @@ import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.cfg.AccessType;
import org.hibernate.cfg.AnnotatedClassType;
import org.hibernate.cfg.AnnotationBinder;
-import org.hibernate.cfg.BinderHelper;
import org.hibernate.cfg.CollectionPropertyHolder;
import org.hibernate.cfg.CollectionSecondPass;
import org.hibernate.cfg.AnnotatedColumn;
@@ -34,7 +33,6 @@ import org.hibernate.cfg.PropertyData;
import org.hibernate.cfg.PropertyPreloadedData;
import org.hibernate.cfg.SecondPass;
import org.hibernate.engine.jdbc.Size;
-import org.hibernate.internal.util.StringHelper;
import org.hibernate.mapping.BasicValue;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Column;
@@ -165,7 +163,7 @@ public class MapBinder extends CollectionBinder {
}
private void bindKeyFromAssociationTable(
- XClass collType,
+ XClass elementType,
Map persistentClasses,
String mapKeyPropertyName,
XProperty property,
@@ -176,17 +174,19 @@ public class MapBinder extends CollectionBinder {
String targetPropertyName) {
if ( mapKeyPropertyName != null ) {
//this is an EJB3 @MapKey
- PersistentClass associatedClass = persistentClasses.get( collType.getName() );
- if ( associatedClass == null ) throw new AnnotationException( "Associated class not found: " + collType );
+ PersistentClass associatedClass = persistentClasses.get( elementType.getName() );
+ if ( associatedClass == null ) {
+ throw new AnnotationException( "Association '" + safeCollectionRole()
+ + "' targets the type '" + elementType.getName() + "' which is not an '@Entity' type" );
+ }
Property mapProperty = findPropertyByName( associatedClass, mapKeyPropertyName );
if ( mapProperty == null ) {
- throw new AnnotationException(
- "Map key property not found: " + collType + "." + mapKeyPropertyName
- );
+ throw new AnnotationException( "Map key property '" + mapKeyPropertyName
+ + "' not found in target entity '" + associatedClass.getEntityName() + "'" );
}
org.hibernate.mapping.Map map = (org.hibernate.mapping.Map) this.collection;
// HHH-11005 - if InheritanceType.JOINED then need to find class defining the column
- InheritanceState inheritanceState = inheritanceStatePerClass.get( collType );
+ InheritanceState inheritanceState = inheritanceStatePerClass.get( elementType );
PersistentClass targetPropertyPersistentClass = InheritanceType.JOINED.equals( inheritanceState.getType() ) ?
mapProperty.getPersistentClass() :
associatedClass;
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/PropertyBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/PropertyBinder.java
index fd889ea07d..84960fdf62 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/PropertyBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/PropertyBinder.java
@@ -24,13 +24,11 @@ import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.cfg.AccessType;
import org.hibernate.cfg.AnnotationBinder;
-import org.hibernate.cfg.BinderHelper;
import org.hibernate.cfg.AnnotatedColumn;
import org.hibernate.cfg.InheritanceState;
import org.hibernate.cfg.PropertyHolder;
import org.hibernate.cfg.PropertyPreloadedData;
import org.hibernate.internal.CoreMessageLogger;
-import org.hibernate.internal.util.StringHelper;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.KeyValue;
@@ -166,10 +164,9 @@ public class PropertyBinder {
private void validateBind() {
if ( property.isAnnotationPresent( Immutable.class ) ) {
- throw new AnnotationException(
- "@Immutable on property not allowed. " +
- "Only allowed on entity level or on a collection."
- );
+ throw new AnnotationException( "Property '" + qualify( holder.getPath(), name )
+ + "' may not be '@Immutable'"
+ + " ('@Immutable' may only be applied to entities and collections)" );
}
if ( !declaringClassSet ) {
throw new AssertionFailure( "declaringClass has not been set before a bind" );
@@ -292,12 +289,14 @@ public class PropertyBinder {
}
private Class extends EmbeddableInstantiator> resolveCustomInstantiator(XProperty property, XClass embeddableClass) {
- final org.hibernate.annotations.EmbeddableInstantiator propertyAnnotation = property.getAnnotation( org.hibernate.annotations.EmbeddableInstantiator.class );
+ final org.hibernate.annotations.EmbeddableInstantiator propertyAnnotation =
+ property.getAnnotation( org.hibernate.annotations.EmbeddableInstantiator.class );
if ( propertyAnnotation != null ) {
return propertyAnnotation.value();
}
- final org.hibernate.annotations.EmbeddableInstantiator classAnnotation = embeddableClass.getAnnotation( org.hibernate.annotations.EmbeddableInstantiator.class );
+ final org.hibernate.annotations.EmbeddableInstantiator classAnnotation =
+ embeddableClass.getAnnotation( org.hibernate.annotations.EmbeddableInstantiator.class );
if ( classAnnotation != null ) {
return classAnnotation.value();
}
@@ -341,7 +340,9 @@ public class PropertyBinder {
NaturalId naturalId = property.getAnnotation(NaturalId.class);
if ( naturalId != null ) {
if ( !entityBinder.isRootEntity() ) {
- throw new AnnotationException( "@NaturalId only valid on root entity (or its @MappedSuperclasses)" );
+ throw new AnnotationException( "Property '" + qualify( holder.getPath(), name )
+ + "' belongs to an entity subclass and may not be annotated '@NaturalId'" +
+ " (only a property of a root '@Entity' or a '@MappedSuperclass' may be a '@NaturalId')" );
}
if ( !naturalId.mutable() ) {
updatable = false;
@@ -368,22 +369,16 @@ public class PropertyBinder {
private void validateOptimisticLock(OptimisticLock lockAnn) {
if ( lockAnn.excluded() ) {
if ( property.isAnnotationPresent(Version.class) ) {
- throw new AnnotationException(
- "@OptimisticLock(excluded=true) incompatible with @Version: "
- + qualify( holder.getPath(), name )
- );
+ throw new AnnotationException("Property '" + qualify( holder.getPath(), name )
+ + "' is annotated '@OptimisticLock(excluded=true)' and '@Version'" );
}
if ( property.isAnnotationPresent(Id.class) ) {
- throw new AnnotationException(
- "@OptimisticLock(excluded=true) incompatible with @Id: "
- + qualify( holder.getPath(), name )
- );
+ throw new AnnotationException("Property '" + qualify( holder.getPath(), name )
+ + "' is annotated '@OptimisticLock(excluded=true)' and '@Id'" );
}
if ( property.isAnnotationPresent(EmbeddedId.class) ) {
- throw new AnnotationException(
- "@OptimisticLock(excluded=true) incompatible with @EmbeddedId: "
- + qualify( holder.getPath(), name )
- );
+ throw new AnnotationException("Property '" + qualify( holder.getPath(), name )
+ + "' is annotated '@OptimisticLock(excluded=true)' and '@EmbeddedId'" );
}
}
}
@@ -409,25 +404,18 @@ public class PropertyBinder {
*/
private ValueGeneration getValueGenerationFromAnnotations(XProperty property) {
AnnotationValueGeneration> valueGeneration = null;
-
for ( Annotation annotation : property.getAnnotations() ) {
AnnotationValueGeneration> candidate = getValueGenerationFromAnnotation( property, annotation );
-
if ( candidate != null ) {
if ( valueGeneration != null ) {
- throw new AnnotationException(
- "Only one generator annotation is allowed: " + qualify(
- holder.getPath(),
- name
- )
- );
+ throw new AnnotationException( "Property '" + qualify( holder.getPath(), name )
+ + "' has multiple 'ValueGenerationType' annotations" );
}
else {
valueGeneration = candidate;
}
}
}
-
return valueGeneration;
}
@@ -439,7 +427,6 @@ public class PropertyBinder {
XProperty property,
A annotation) {
final ValueGenerationType generatorAnnotation = annotation.annotationType().getAnnotation( ValueGenerationType.class );
-
if ( generatorAnnotation == null ) {
return null;
}
@@ -451,9 +438,9 @@ public class PropertyBinder {
&& property.isAnnotationPresent(Version.class)
&& valueGeneration.getGenerationTiming() == GenerationTiming.INSERT ) {
- throw new AnnotationException(
- "@Generated(INSERT) on a @Version property not allowed, use ALWAYS (or NEVER): "
- + qualify( holder.getPath(), name )
+ throw new AnnotationException( "Property '" + qualify( holder.getPath(), name )
+ + "' is annotated '@Generated(INSERT)' and '@Version' (use '@Generated(ALWAYS)' instead)"
+
);
}
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/QueryBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/QueryBinder.java
index e05a89550d..08da36df61 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/QueryBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/QueryBinder.java
@@ -25,10 +25,8 @@ import org.hibernate.boot.query.NamedNativeQueryDefinition;
import org.hibernate.boot.query.NamedNativeQueryDefinitionBuilder;
import org.hibernate.boot.query.NamedProcedureCallDefinition;
import org.hibernate.boot.spi.MetadataBuildingContext;
-import org.hibernate.cfg.BinderHelper;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.log.DeprecationLogger;
-import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.jpa.HibernateHints;
import org.hibernate.query.sql.internal.ParameterParser;
import org.hibernate.query.sql.spi.ParameterRecognizer;
@@ -68,7 +66,7 @@ public abstract class QueryBinder {
}
if ( isEmptyAnnotationValue( queryAnn.name() ) ) {
- throw new AnnotationException( "A named query must have a name when used in class or package level" );
+ throw new AnnotationException( "Class or package level '@NamedQuery' annotation must specify a 'name'" );
}
final String queryName = queryAnn.name();
@@ -111,7 +109,7 @@ public abstract class QueryBinder {
}
if ( isEmptyAnnotationValue( queryAnn.name() ) ) {
- throw new AnnotationException( "A named query must have a name when used in class or package level" );
+ throw new AnnotationException( "Class or package level '@NamedNativeQuery' annotation must specify a 'name'" );
}
final String registrationName = queryAnn.name();
@@ -165,7 +163,7 @@ public abstract class QueryBinder {
//ResultSetMappingDefinition mappingDefinition = mappings.getJdbcValuesMappingProducer( queryAnn.resultSetMapping() );
if ( isEmptyAnnotationValue( registrationName ) ) {
- throw new AnnotationException( "A named query must have a name when used in class or package level" );
+ throw new AnnotationException( "Class or package level '@NamedNativeQuery' annotation must specify a 'name'" );
}
final String resultSetMappingName = queryAnn.resultSetMapping();
@@ -189,16 +187,11 @@ public abstract class QueryBinder {
.setComment( getAnnotationValueStringOrNull( queryAnn.comment() ) );
if ( queryAnn.callable() ) {
- final NamedProcedureCallDefinition definition = createStoredProcedure(
- builder, context,
- () -> illegalCallSyntax(
- queryAnn,
- queryAnn.query()
- )
- );
+ final NamedProcedureCallDefinition definition =
+ createStoredProcedure( builder, context, () -> illegalCallSyntax( queryAnn ) );
context.getMetadataCollector().addNamedProcedureCallDefinition( definition );
DeprecationLogger.DEPRECATION_LOGGER.warn(
- "Marking named native queries as callable is no longer supported; use `@jakarta.persistence.NamedStoredProcedureQuery` instead. Ignoring."
+ "Marking named native queries as callable is no longer supported; use '@jakarta.persistence.NamedStoredProcedureQuery' instead. Ignoring."
);
}
else {
@@ -343,7 +336,7 @@ public abstract class QueryBinder {
//ResultSetMappingDefinition mappingDefinition = mappings.getJdbcValuesMappingProducer( queryAnn.resultSetMapping() );
if ( isEmptyAnnotationValue( registrationName ) ) {
- throw new AnnotationException( "A named query must have a name when used in class or package level" );
+ throw new AnnotationException( "Class or package level '@NamedQuery' annotation must specify a 'name'" );
}
@@ -432,7 +425,7 @@ public abstract class QueryBinder {
final String registrationName = annotation.name();
if ( isEmptyAnnotationValue( registrationName ) ) {
- throw new AnnotationException( "A named query must have a name when used in class or package level" );
+ throw new AnnotationException( "Class or package level '@NamedStoredProcedureQuery' annotation must specify a 'name'" );
}
final NamedProcedureCallDefinitionImpl def = new NamedProcedureCallDefinitionImpl( annotation );
@@ -537,15 +530,8 @@ public abstract class QueryBinder {
return i;
}
- private static AnnotationException illegalCallSyntax(
- org.hibernate.annotations.NamedNativeQuery queryAnn,
- String sqlString) {
- return new AnnotationException(
- String.format(
- "Callable named native query [%s] doesn't use the JDBC call syntax: %s",
- queryAnn.name(),
- sqlString
- )
- );
+ private static AnnotationException illegalCallSyntax(org.hibernate.annotations.NamedNativeQuery queryAnn) {
+ return new AnnotationException( "Callable 'NamedNativeQuery' named '" + queryAnn.name()
+ + "' does not use the JDBC call syntax" );
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/TableBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/TableBinder.java
index 531591d66f..9a4f090c9d 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/TableBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/TableBinder.java
@@ -22,7 +22,6 @@ import org.hibernate.boot.model.naming.NamingStrategyHelper;
import org.hibernate.boot.model.source.spi.AttributePath;
import org.hibernate.boot.spi.InFlightMetadataCollector;
import org.hibernate.boot.spi.MetadataBuildingContext;
-import org.hibernate.cfg.BinderHelper;
import org.hibernate.cfg.AnnotatedJoinColumn;
import org.hibernate.cfg.IndexOrUniqueKeySecondPass;
import org.hibernate.cfg.JPAIndexHolder;
@@ -30,7 +29,6 @@ import org.hibernate.cfg.ObjectNameSource;
import org.hibernate.cfg.UniqueConstraintHolder;
import org.hibernate.dialect.Dialect;
import org.hibernate.internal.CoreMessageLogger;
-import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Column;
@@ -546,10 +544,8 @@ public class TableBinder {
}
final String mappedByProperty = columns[0].getMappedBy();
if ( isNotEmpty( mappedByProperty ) ) {
- /*
- * Get the columns of the mapped-by property
- * copy them and link the copy to the actual value
- */
+ // Get the columns of the mapped-by property
+ // copy them and link the copy to the actual value
LOG.debugf( "Retrieving property %s.%s", associatedClass.getEntityName(), mappedByProperty );
final Property property = associatedClass.getRecursiveProperty( columns[0].getMappedBy() );
@@ -559,8 +555,9 @@ public class TableBinder {
Value element = collection.getElement();
if ( element == null ) {
throw new AnnotationException(
- "Illegal use of mappedBy on both sides of the relationship: "
+ "Both sides of the bidirectional association '"
+ associatedClass.getEntityName() + "." + mappedByProperty
+ + "' specify 'mappedBy'"
);
}
mappedByColumns = element.getColumns();
@@ -574,10 +571,8 @@ public class TableBinder {
}
}
else if ( columns[0].isImplicit() ) {
- /*
- * if columns are implicit, then create the columns based on the
- * referenced entity id columns
- */
+ // if columns are implicit, then create the columns based on the
+ // referenced entity id columns
List idColumns = referencedEntity instanceof JoinedSubclass
? referencedEntity.getKey().getColumns()
: referencedEntity.getIdentifier().getColumns();
@@ -602,7 +597,7 @@ public class TableBinder {
referencedPropertyName = collection.getReferencedPropertyName();
}
else {
- throw new AnnotationException( "SecondaryTable JoinColumn cannot reference a non primary key" );
+ throw new AnnotationException( "The '@JoinColumn' for a secondary table must reference the primary key" );
}
}
@@ -623,9 +618,7 @@ public class TableBinder {
"Cannot find synthProp: " + referencedEntity.getEntityName() + "." + referencedPropertyName
);
}
- linkJoinColumnWithValueOverridingNameIfImplicit(
- referencedEntity, synthProp.getValue(), columns, value
- );
+ linkJoinColumnWithValueOverridingNameIfImplicit( referencedEntity, synthProp.getValue(), columns, value );
if ( value instanceof SortableValue ) {
( (SortableValue) value ).sortProperties();
}
@@ -635,10 +628,10 @@ public class TableBinder {
//implicit case, we hope PK and FK columns are in the same order
if ( columns.length != referencedEntity.getIdentifier().getColumnSpan() ) {
throw new AnnotationException(
- "A Foreign key referring " + referencedEntity.getEntityName()
- + " from " + associatedClass.getEntityName()
- + " has the wrong number of column. should be " + referencedEntity.getIdentifier()
- .getColumnSpan()
+ "A foreign key that references '" + referencedEntity.getEntityName()
+ + "' from entity '" + associatedClass.getEntityName()
+ + "' has " + columns.length + " columns but the primary key has "
+ + referencedEntity.getIdentifier().getColumnSpan() + " columns"
);
}
linkJoinColumnWithValueOverridingNameIfImplicit(
@@ -669,7 +662,7 @@ public class TableBinder {
Dialect dialect = buildingContext.getMetadataCollector().getDatabase()
.getJdbcEnvironment().getDialect();
final String colName = col.getQuotedName(dialect);
- for (AnnotatedJoinColumn joinCol : columns) {
+ for ( AnnotatedJoinColumn joinCol : columns ) {
String referencedColumn = joinCol.getReferencedColumn();
referencedColumn = buildingContext.getMetadataCollector().getPhysicalColumnName(
table,
diff --git a/hibernate-core/src/main/java/org/hibernate/event/spi/EventType.java b/hibernate-core/src/main/java/org/hibernate/event/spi/EventType.java
index 9bb4ac97c3..d847ec835c 100644
--- a/hibernate-core/src/main/java/org/hibernate/event/spi/EventType.java
+++ b/hibernate-core/src/main/java/org/hibernate/event/spi/EventType.java
@@ -119,12 +119,11 @@ public final class EventType {
*
* @throws HibernateException If eventName is null, or if eventName does not correlate to any known event type.
*/
- @SuppressWarnings("rawtypes")
- public static EventType resolveEventTypeByName(final String eventName) {
+ public static EventType> resolveEventTypeByName(final String eventName) {
if ( eventName == null ) {
throw new HibernateException( "event name to resolve cannot be null" );
}
- final EventType eventType = STANDARD_TYPE_BY_NAME_MAP.get( eventName );
+ final EventType> eventType = STANDARD_TYPE_BY_NAME_MAP.get( eventName );
if ( eventType == null ) {
throw new HibernateException( "Unable to locate proper event type for event name [" + eventName + "]" );
}
diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java b/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java
index dfc606ddb4..78b4df83eb 100644
--- a/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java
+++ b/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java
@@ -78,7 +78,7 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol
// incoming "configuration" values
private String explicitTypeName;
- private Map explicitLocalTypeParams;
+ private Map explicitLocalTypeParams;
private Function explicitJavaTypeAccess;
private Function explicitJdbcTypeAccess;
@@ -117,7 +117,7 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol
this.explicitTypeName = original.explicitTypeName;
this.explicitLocalTypeParams = original.explicitLocalTypeParams == null
? null
- : new HashMap(original.explicitLocalTypeParams);
+ : new HashMap<>(original.explicitLocalTypeParams);
this.explicitJavaTypeAccess = original.explicitJavaTypeAccess;
this.explicitJdbcTypeAccess = original.explicitJdbcTypeAccess;
this.explicitMutabilityPlanAccess = original.explicitMutabilityPlanAccess;
@@ -264,11 +264,11 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol
return;
}
- throw new IllegalStateException(
- "BasicValue [" + ownerName + "." + propertyName +
- "] already had column associated: `" + column.getText() +
- "` -> `" + incomingColumn.getText() + "`"
- );
+// throw new IllegalStateException(
+// "BasicValue [" + ownerName + "." + propertyName +
+// "] already had column associated: `" + column.getText() +
+// "` -> `" + incomingColumn.getText() + "`"
+// );
}
@Override
@@ -665,8 +665,7 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol
name,
typeNamedClass,
null,
- null,
- typeConfiguration
+ null
);
context.getTypeDefinitionRegistry().register( implicitDefinition );
return implicitDefinition.resolve(
@@ -754,7 +753,7 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol
return typeConfiguration;
}
- public void setExplicitTypeParams(Map explicitLocalTypeParams) {
+ public void setExplicitTypeParams(Map explicitLocalTypeParams) {
this.explicitLocalTypeParams = explicitLocalTypeParams;
}
@@ -772,7 +771,6 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol
.getServiceRegistry()
.getService( ClassLoaderService.class );
try {
- //noinspection rawtypes
final Class> converterClass = cls.classForName( converterClassName );
setAttributeConverterDescriptor( new ClassBasedConverterDescriptor(
converterClass,
diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Column.java b/hibernate-core/src/main/java/org/hibernate/mapping/Column.java
index f1cb5e0852..9149b5e70c 100644
--- a/hibernate-core/src/main/java/org/hibernate/mapping/Column.java
+++ b/hibernate-core/src/main/java/org/hibernate/mapping/Column.java
@@ -196,18 +196,10 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
return object instanceof Column && equals( (Column) object );
}
- @SuppressWarnings("SimplifiableIfStatement")
public boolean equals(Column column) {
- if ( null == column ) {
- return false;
- }
- if ( this == column ) {
- return true;
- }
-
- return isQuoted() ?
- name.equals( column.name ) :
- name.equalsIgnoreCase( column.name );
+ return column != null && (
+ this == column || isQuoted() ? name.equals( column.name ) : name.equalsIgnoreCase( column.name )
+ );
}
public int getSqlTypeCode(Mapping mapping) throws MappingException {
diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java b/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java
index 5e4e176cec..4b91167456 100644
--- a/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java
+++ b/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java
@@ -33,6 +33,7 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.jpa.event.spi.CallbackDefinition;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.sql.Alias;
+import org.hibernate.type.Type;
/**
* Mapping for an entity.
@@ -704,11 +705,14 @@ public abstract class PersistentClass implements AttributeContainer, Serializabl
public void validate(Mapping mapping) throws MappingException {
for ( Property prop : getProperties() ) {
if ( !prop.isValid( mapping ) ) {
+ Type type = prop.getType();
+ int actualColumns = prop.getColumnSpan();
+ int requiredColumns = type.getColumnSpan(mapping);
throw new MappingException(
- "property mapping has wrong number of columns: " +
- StringHelper.qualify( getEntityName(), prop.getName() ) +
- " type: " +
- prop.getType().getName()
+ "Property '" + StringHelper.qualify( getEntityName(), prop.getName() )
+ + "' maps to " + actualColumns + " columns but " + requiredColumns
+ + " columns are required (type '" + type.getName()
+ + "' spans " + requiredColumns + " columns)"
);
}
}
@@ -1001,11 +1005,9 @@ public abstract class PersistentClass implements AttributeContainer, Serializabl
Column col = (Column) columnOrFormula;
if ( !distinctColumns.add( col.getName() ) ) {
throw new MappingException(
- "Repeated column in mapping for entity: " +
- getEntityName() +
- " column: " +
- col.getName() +
- " (should be mapped with insert=\"false\" update=\"false\")"
+ "Column '" + col.getName()
+ + "' is duplicated in mapping for entity '" + getEntityName()
+ + "' (use '@Column(insertable=false, updatable=false)' when mapping multiple properties to the same column)"
);
}
}
@@ -1014,14 +1016,15 @@ public abstract class PersistentClass implements AttributeContainer, Serializabl
protected void checkPropertyColumnDuplication(Set distinctColumns, List properties)
throws MappingException {
- for (Property prop : properties) {
- if ( prop.getValue() instanceof Component ) { //TODO: remove use of instanceof!
- Component component = (Component) prop.getValue();
+ for ( Property prop : properties ) {
+ Value value = prop.getValue();
+ if ( value instanceof Component ) {
+ Component component = (Component) value;
checkPropertyColumnDuplication( distinctColumns, component.getProperties() );
}
else {
if ( prop.isUpdateable() || prop.isInsertable() ) {
- checkColumnDuplication( distinctColumns, prop.getValue() );
+ checkColumnDuplication( distinctColumns, value);
}
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/property/access/spi/BuiltInPropertyAccessStrategies.java b/hibernate-core/src/main/java/org/hibernate/property/access/spi/BuiltInPropertyAccessStrategies.java
index aa6dc073f7..168053e496 100644
--- a/hibernate-core/src/main/java/org/hibernate/property/access/spi/BuiltInPropertyAccessStrategies.java
+++ b/hibernate-core/src/main/java/org/hibernate/property/access/spi/BuiltInPropertyAccessStrategies.java
@@ -14,7 +14,7 @@ import org.hibernate.property.access.internal.PropertyAccessStrategyMixedImpl;
import org.hibernate.property.access.internal.PropertyAccessStrategyNoopImpl;
/**
- * Describes the built-in externally-nameable PropertyAccessStrategy implementations.
+ * Describes the built-in externally-nameable {@link PropertyAccessStrategy} implementations.
*
* @author Steve Ebersole
*/
@@ -24,8 +24,7 @@ public enum BuiltInPropertyAccessStrategies {
MIXED( "mixed", PropertyAccessStrategyMixedImpl.INSTANCE ),
MAP( "map", PropertyAccessStrategyMapImpl.INSTANCE ),
EMBEDDED( "embedded", PropertyAccessStrategyEmbeddedImpl.INSTANCE ),
- NOOP( "noop", PropertyAccessStrategyNoopImpl.INSTANCE )
- ;
+ NOOP( "noop", PropertyAccessStrategyNoopImpl.INSTANCE );
private final String externalName;
private final PropertyAccessStrategy strategy;
@@ -44,22 +43,11 @@ public enum BuiltInPropertyAccessStrategies {
}
public static BuiltInPropertyAccessStrategies interpret(String name) {
- if ( BASIC.externalName.equals( name ) ) {
- return BASIC;
+ for ( BuiltInPropertyAccessStrategies strategy : values() ) {
+ if ( strategy.externalName.equals( name ) ) {
+ return strategy;
+ }
}
- else if ( FIELD.externalName.equals( name ) ) {
- return FIELD;
- }
- else if ( MAP.externalName.equals( name ) ) {
- return MAP;
- }
- else if ( EMBEDDED.externalName.equals( name ) ) {
- return EMBEDDED;
- }
- else if ( NOOP.externalName.equals( name ) ) {
- return NOOP;
- }
-
return null;
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/AttributeAccessorBinder.java b/hibernate-core/src/main/java/org/hibernate/tuple/AttributeAccessorBinder.java
index 898d8d7736..1fc56a33db 100644
--- a/hibernate-core/src/main/java/org/hibernate/tuple/AttributeAccessorBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/tuple/AttributeAccessorBinder.java
@@ -34,7 +34,7 @@ public class AttributeAccessorBinder implements AttributeBinder@Type
+ * annotation which was based on the {@code hbm.xml} mapping's string-based type support.
*
* @see Type
*/
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/e3/b3/Dependent.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/e3/b3/Dependent.java
index 7e1af01f33..72bff2f2dc 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/e3/b3/Dependent.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/e3/b3/Dependent.java
@@ -9,10 +9,8 @@ public class Dependent {
@EmbeddedId
DependentId id;
- @JoinColumns({
- @JoinColumn(name = "FIRSTNAME", referencedColumnName = "FIRSTNAME"),
- @JoinColumn(name = "LASTNAME", referencedColumnName = "lastName")
- })
+ @JoinColumn(name = "FIRSTNAME", referencedColumnName = "FIRSTNAME")
+ @JoinColumn(name = "LASTNAME", referencedColumnName = "lastName")
@MapsId("empPK")
@ManyToOne
Employee emp;
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/e3/b3/EmployeeId.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/e3/b3/EmployeeId.java
index aa534006f7..8408625e17 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/e3/b3/EmployeeId.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/e3/b3/EmployeeId.java
@@ -6,8 +6,8 @@ import java.io.Serializable;
@Embeddable
public class EmployeeId implements Serializable {
- @Column(length = 32)
+ @Column(name="firstname", length = 32)
String firstName;
- @Column(length = 32)
+ @Column(name="lastname", length = 32)
String lastName;
}
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embeddables/collection/AbstractEmbeddableWithManyToManyTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embeddables/collection/AbstractEmbeddableWithManyToManyTest.java
index 149495d36f..2c5df2f17c 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embeddables/collection/AbstractEmbeddableWithManyToManyTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embeddables/collection/AbstractEmbeddableWithManyToManyTest.java
@@ -28,8 +28,8 @@ public abstract class AbstractEmbeddableWithManyToManyTest {
fail( "Should throw AnnotationException!" );
}
catch (AnnotationException expected) {
- assertTrue( expected.getMessage().startsWith(
- "@OneToMany, @ManyToMany or @ElementCollection cannot be used inside an @Embeddable that is also contained within an @ElementCollection"
+ assertTrue( expected.getMessage().contains(
+ "belongs to an '@Embeddable' class that is contained in an '@ElementCollection' and may not be"
) );
}
}
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idmanytoone/BasketItems.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idmanytoone/BasketItems.java
index 0b5a7e3b99..67f748e362 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idmanytoone/BasketItems.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idmanytoone/BasketItems.java
@@ -16,7 +16,6 @@ import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.IdClass;
import jakarta.persistence.JoinColumn;
-import jakarta.persistence.JoinColumns;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
@@ -30,7 +29,8 @@ public class BasketItems implements Serializable {
@Id
@ManyToOne(cascade={ CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
- @JoinColumns({ @JoinColumn(name="basketDatetime", referencedColumnName="basketDatetime"), @JoinColumn(name="customerID", referencedColumnName="customerID") })
+ @JoinColumn(name="basketDatetime", referencedColumnName="basketDatetime")
+ @JoinColumn(name="customerID", referencedColumnName="customerID")
@Basic(fetch= FetchType.LAZY)
private ShoppingBaskets shoppingBaskets;
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idmanytoone/BasketItemsPK.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idmanytoone/BasketItemsPK.java
index 1cb9f8314d..f294c20aa3 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idmanytoone/BasketItemsPK.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idmanytoone/BasketItemsPK.java
@@ -15,7 +15,6 @@ import jakarta.persistence.Embeddable;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
-import jakarta.persistence.JoinColumns;
import jakarta.persistence.ManyToOne;
@Embeddable
@@ -50,7 +49,8 @@ public class BasketItemsPK implements Serializable {
@Id
@ManyToOne(cascade={ CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
- @JoinColumns({ @JoinColumn(name="basketDatetime", referencedColumnName="basketDatetime"), @JoinColumn(name="customerID", referencedColumnName="customerID") })
+ @JoinColumn(name="basketDatetime", referencedColumnName="basketDatetime")
+ @JoinColumn(name="customerID", referencedColumnName="customerID")
@Basic(fetch= FetchType.LAZY)
private ShoppingBaskets shoppingBaskets;
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idmanytoone/ShoppingBaskets.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idmanytoone/ShoppingBaskets.java
index f678991d7d..9fd7ac17ae 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idmanytoone/ShoppingBaskets.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idmanytoone/ShoppingBaskets.java
@@ -16,7 +16,6 @@ import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.IdClass;
import jakarta.persistence.JoinColumn;
-import jakarta.persistence.JoinColumns;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
@@ -31,7 +30,7 @@ public class ShoppingBaskets implements Serializable {
@Id
@ManyToOne(cascade={ CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
- @JoinColumns({ @JoinColumn(name="customerID", referencedColumnName="customerID") })
+ @JoinColumn(name="customerID", referencedColumnName="customerID")
@Basic(fetch=FetchType.LAZY)
private Customers owner;
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idmanytoone/ShoppingBasketsPK.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idmanytoone/ShoppingBasketsPK.java
index c9a45a8cbf..6f642278a7 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idmanytoone/ShoppingBasketsPK.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idmanytoone/ShoppingBasketsPK.java
@@ -15,7 +15,6 @@ import jakarta.persistence.Embeddable;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
-import jakarta.persistence.JoinColumns;
import jakarta.persistence.ManyToOne;
@Embeddable
@@ -48,7 +47,7 @@ public class ShoppingBasketsPK implements Serializable {
@Id
@ManyToOne(cascade={ CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
- @JoinColumns({ @JoinColumn(name="customerID", referencedColumnName="customerID") })
+ @JoinColumn(name="customerID", referencedColumnName="customerID")
@Basic(fetch= FetchType.LAZY)
private Customers owner;
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/index/jpa/Car.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/index/jpa/Car.java
index cb54fcd38b..067191eb21 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/index/jpa/Car.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/index/jpa/Car.java
@@ -9,7 +9,6 @@ package org.hibernate.orm.test.annotations.index.jpa;
import java.util.List;
import java.util.Set;
import jakarta.persistence.AttributeOverride;
-import jakarta.persistence.AttributeOverrides;
import jakarta.persistence.CascadeType;
import jakarta.persistence.CollectionTable;
import jakarta.persistence.Column;
@@ -28,8 +27,8 @@ import jakarta.persistence.Table;
*/
@Entity
@Table(indexes = {
- @Index(unique = true, columnList = "brand, producer")
- , @Index(name = "Car_idx", columnList = "since DESC")
+ @Index(unique = true, columnList = "brand, producer"),
+ @Index(name = "Car_idx", columnList = "since DESC")
})
@SecondaryTable(name = "T_DEALER", indexes = @Index(columnList = "dealer_name ASC, rate DESC"))
public class Car {
@@ -38,10 +37,8 @@ public class Car {
private String brand;
private String producer;
private long since;
- @AttributeOverrides({
- @AttributeOverride(name = "name", column = @Column(name = "dealer_name", table = "T_DEALER")),
- @AttributeOverride(name = "rate", column = @Column(table = "T_DEALER"))
- })
+ @AttributeOverride(name = "name", column = @Column(name = "dealer_name", table = "T_DEALER"))
+ @AttributeOverride(name = "rate", column = @Column(table = "T_DEALER"))
@Embedded
private Dealer dealer;
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/onetomany/OneToManyTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/onetomany/OneToManyTest.java
index 9a151b149b..76638b7753 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/onetomany/OneToManyTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/onetomany/OneToManyTest.java
@@ -397,7 +397,7 @@ public class OneToManyTest extends BaseNonConfigCoreFunctionalTestCase {
.build();
}
catch ( AnnotationException e ) {
- assertTrue(e.getMessage().contains( "Unidirectional one-to-many associations annotated with @OnDelete must define @JoinColumn" ));
+ assertTrue(e.getMessage().contains( "is annotated '@OnDelete' and must explicitly specify a '@JoinColumn'" ));
}
finally {
StandardServiceRegistryBuilder.destroy( serviceRegistry );
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/onetoone/OverrideOneToOneJoinColumnTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/onetoone/OverrideOneToOneJoinColumnTest.java
index 36003c0482..c92a812ed9 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/onetoone/OverrideOneToOneJoinColumnTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/onetoone/OverrideOneToOneJoinColumnTest.java
@@ -73,7 +73,7 @@ public class OverrideOneToOneJoinColumnTest {
);
assertTrue(
- ex.getMessage().startsWith( "Illegal attempt to define a @JoinColumn with a mappedBy association:" ),
+ ex.getMessage().contains( "is 'mappedBy' a different entity and may not explicitly specify the '@JoinColumn'" ),
"Should disallow exactly because of @JoinColumn override on side with mappedBy"
);
}
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/collections/SortAndOrderTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/collections/SortAndOrderTests.java
index f5871b64eb..3c174af9ff 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/collections/SortAndOrderTests.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/collections/SortAndOrderTests.java
@@ -23,7 +23,6 @@ import jakarta.persistence.Basic;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
-import jakarta.persistence.OneToMany;
import jakarta.persistence.OrderBy;
import jakarta.persistence.Table;
@@ -47,7 +46,7 @@ public class SortAndOrderTests {
fail( "Expecting to fail" );
}
catch (AnnotationException expected) {
- assertThat( expected ).hasMessageStartingWith( "Illegal combination of ordering and sorting annotations" );
+ assertThat( expected ).hasMessageContaining( "both sorted and ordered" );
}
}
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/collections/custom/declaredtype/UserWithUnimplementedCollectionTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/collections/custom/declaredtype/UserWithUnimplementedCollectionTest.java
index 5024abbe1e..4fb6d9f4ce 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/collections/custom/declaredtype/UserWithUnimplementedCollectionTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/collections/custom/declaredtype/UserWithUnimplementedCollectionTest.java
@@ -63,8 +63,8 @@ public class UserWithUnimplementedCollectionTest extends BaseCoreFunctionalTestC
}
catch (Exception e) {
assertThat( e ).isInstanceOf( AnnotationException.class );
- assertThat( e ).hasMessageStartingWith( "Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements:" );
- assertThat( e ).hasMessageEndingWith( ".emailAddresses" );
+ assertThat( e ).hasMessageEndingWith( "is not a collection and may not be a '@OneToMany', '@ManyToMany', or '@ElementCollection'" );
+ assertThat( e ).hasMessageContaining( ".emailAddresses" );
}
}
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/schemaupdate/derivedid/ColumnLengthTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/schemaupdate/derivedid/ColumnLengthTest.java
index 7eddc63a4a..f4133b237c 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/schemaupdate/derivedid/ColumnLengthTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/schemaupdate/derivedid/ColumnLengthTest.java
@@ -16,7 +16,6 @@ import jakarta.persistence.Embeddable;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import jakarta.persistence.JoinColumn;
-import jakarta.persistence.JoinColumns;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.MapsId;
import jakarta.persistence.Table;
@@ -122,10 +121,8 @@ public class ColumnLengthTest extends BaseUnitTestCase {
@EmbeddedId
DependentId id;
@MapsId("empPK")
- @JoinColumns({
- @JoinColumn(name = "FK1", referencedColumnName = "first_name"),
- @JoinColumn(name = "FK2", referencedColumnName = "last_name")
- })
+ @JoinColumn(name = "FK1", referencedColumnName = "first_name")
+ @JoinColumn(name = "FK2", referencedColumnName = "last_name")
@ManyToOne
Employee emp;
}