diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/Bag.java b/hibernate-core/src/main/java/org/hibernate/annotations/Bag.java index 2cfa653c50..2b86a8e330 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/Bag.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/Bag.java @@ -9,21 +9,25 @@ package org.hibernate.annotations; import java.lang.annotation.Retention; import java.lang.annotation.Target; -import org.hibernate.cfg.AvailableSettings; - import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** - * Can be used to map a {@link java.util.List}-valued attribute using - * {@link org.hibernate.metamodel.CollectionClassification#BAG} semantics. + * Specifies that an attribute of type {@link java.util.List} is semantically + * a {@linkplain org.hibernate.metamodel.CollectionClassification#BAG bag}, + * that is, that the order of the list elements is not significant, and should + * not be persistent. *

- * @apiNote Ignored if either {@link jakarta.persistence.OrderColumn} or - * {@link ListIndexBase} is used. + * This annotation is not necessary, and has no effect, unless the configuration + * property {@value org.hibernate.cfg.AvailableSettings#DEFAULT_LIST_SEMANTICS} + * is set to {@link org.hibernate.metamodel.CollectionClassification#LIST}. + * However, its use is still encouraged, since the explicit annotation serves + * as useful documentation. * - * @implSpec May also be specified SessionFactory-wide using {@value AvailableSettings#DEFAULT_LIST_SEMANTICS} + * @apiNote This annotation causes an exception if the attribute is also annotated + * {@link jakarta.persistence.OrderColumn} or {@link ListIndexBase}. * * @author Steve Ebersole */ 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 ce658fb579..294e4ec79a 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/Type.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/Type.java @@ -60,7 +60,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; @Retention(RUNTIME) public @interface Type { /** - * The implementation class which implements {@link UserType}. + * The class which implements {@link UserType}. */ Class> value(); diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java index 962ac4cb00..2d1f04b1d9 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java @@ -987,16 +987,26 @@ public abstract class CollectionBinder { return determineCollectionClassification( determineSemanticJavaType( property ), property, buildingContext ); } else { + if ( property.isAnnotationPresent( OrderColumn.class ) ) { + throw new AnnotationException( "Attribute '" + + qualify( property.getDeclaringClass().getName(), property.getName() ) + + "' is annotated '@Bag' and may not also be annotated '@OrderColumn'" ); + } + if ( property.isAnnotationPresent( ListIndexBase.class ) ) { + throw new AnnotationException( "Attribute '" + + qualify( property.getDeclaringClass().getName(), property.getName() ) + + "' is annotated '@Bag' and may not also be annotated '@ListIndexBase'" ); + } final Class collectionJavaType = property.getCollectionClass(); if ( java.util.List.class.equals( collectionJavaType ) || java.util.Collection.class.equals( collectionJavaType ) ) { return CollectionClassification.BAG; } else { - throw new MappingException( + throw new AnnotationException( String.format( Locale.ROOT, - "@Bag annotation encountered on an attribute `%s#%s` of type `%s`; only `%s` and `%s` are supported", + "Attribute '%s.%s' of type '%s' is annotated '@Bag' (bags are of type '%s' or '%s')", property.getDeclaringClass().getName(), property.getName(), collectionJavaType.getName(), diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataSourcesContributor.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataSourcesContributor.java index d3a15a4f57..e4f0ec0fdf 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataSourcesContributor.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataSourcesContributor.java @@ -17,9 +17,9 @@ import org.hibernate.boot.MetadataSources; */ public interface MetadataSourcesContributor { /** - * Perform the process of contributing to MetadataSources. + * Perform the process of contributing to the {@link MetadataSources}. * - * @param metadataSources The MetadataSources, to which to contribute. + * @param metadataSources The {@code MetadataSource}s, to which to contribute. */ void contribute(MetadataSources metadataSources); } diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java index 5018a24cdb..44cb8f44cd 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java @@ -929,8 +929,16 @@ public interface AvailableSettings { *

  • the (case insensitive) name of a {@code CollectionClassification} (list e.g.) *
  • a {@link Class} representing either {@link java.util.List} or {@link java.util.Collection} * + *

    + * By default, when this property is not set, an attribute of type {@code List} + * is taken to have the semantics of a + * {@linkplain org.hibernate.metamodel.CollectionClassification#BAG bag} unless + * it is annotated {@link jakarta.persistence.OrderColumn} or + * {@link org.hibernate.annotations.ListIndexBase}. * * @since 6.0 + * + * @see org.hibernate.annotations.Bag */ String DEFAULT_LIST_SEMANTICS = "hibernate.mapping.default_list_semantics";