Drop `@CollectionClassificationType`;

Drop `@CollectionSemantics`;
Drop `@CollectionSemanticsRegistration(s)`;
Add `@CollectionTypeRegistration(s)`;
Rename `@CustomType` to `@Type`;
User Guide and Migration Guide changes
This commit is contained in:
Steve Ebersole 2022-01-06 21:45:14 -06:00
parent b8d26f829e
commit 448d678fb5
135 changed files with 1078 additions and 1260 deletions

View File

@ -32,6 +32,8 @@ Hibernate supports using the following integrations as managed beans:
* `org.hibernate.type.descriptor.jdbc.JdbcType`
* `org.hibernate.type.descriptor.java.BasicJavaType`
* `org.hibernate.type.descriptor.java.MutabilityPlan`
* `org.hibernate.usertype.UserType`
* `org.hibernate.usertype.UserCollectionType`
* `org.hibernate.metamodel.EmbeddableInstantiator`
* `org.hibernate.envers.RevisionListener`
* `org.hibernate.id.IdentifierGenerator`{fn-cdi-availability}

View File

@ -1532,17 +1532,17 @@ See <<basic-type-contributor>> for an alternative to `@JavaTypeRegistration` and
[[basic-mapping-custom]]
==== Custom type mapping
Another approach is to supply the implementation of the `org.hibernate.usertype.UserType` contract using `@CustomType`.
Another approach is to supply the implementation of the `org.hibernate.usertype.UserType` contract using `@Type`.
There are also corresponding, specialized forms of `@CustomType` for specific model parts:
There are also corresponding, specialized forms of `@Type` for specific model parts:
* When mapping a Map, `@CustomType` describes the Map value while `@MapKeyCustomType` describe the Map key
* When mapping a List or array, `@CustomType` describes the elements while `@ListIndexCustomType` describes the index
* When mapping an id-bag, `@CustomType` describes the elements while `@CollectionIdCustomType` describes the collection-id
* For other collection mappings, `@CustomType` describes the elements
* For discriminated association mappings (`@Any` and `@ManyToAny`), `@CustomType` describes the discriminator value
* When mapping a Map, `@Type` describes the Map value while `@MapKeyCustomType` describe the Map key
* When mapping a List or array, `@Type` describes the elements while `@ListIndexCustomType` describes the index
* When mapping an id-bag, `@Type` describes the elements while `@CollectionIdCustomType` describes the collection-id
* For other collection mappings, `@Type` describes the elements
* For discriminated association mappings (`@Any` and `@ManyToAny`), `@Type` describes the discriminator value
`@UserType` allows for more complex mapping concerns; but, <<basic-jpa-convert,AttributeConverter> and
`@Type` allows for more complex mapping concerns; but, <<basic-jpa-convert,AttributeConverter> and
<<basic-mapping-composition>> should generally be preferred as simpler solutions
[[basic-nationalized]]

View File

@ -237,7 +237,7 @@ Some apps map BAG collections using `java.util.List` instead. Hibernate provide
lists as bags. First an explicit annotation
[[collection-bag-list-ex]]
.List as BAG
.@Bag
====
[source, JAVA, indent=0]
----
@ -245,11 +245,11 @@ include::{classificationTestsDir}/bag/EntityWithBagAsList.java[tags=collections-
----
====
Specifically, the usage of `@CollectionClassificationType(BAG)` forces the interpretation to
BAG. See <<collection-classification-ann>> for details on using `@CollectionClassificationType`.
Specifically, the usage of `@Bag` forces the classification as BAG. Even though the `names` attribute is defined
as `List`, Hibernate will treat it using the BAG semantics.
Additionally, as discussed in <<collection-list>>, the `hibernate.mapping.default_list_semantics` setting
is available to have Hibernate interpret a `List` with no `@OrderColumn` as a BAG.
is available to have Hibernate interpret a `List` with no `@OrderColumn` and no `@ListIndexBase` as a BAG.
An ID_BAG is similar to a BAG, except that it maps a generated, per-row identifier into the collection
@ -380,118 +380,16 @@ Id:: the identifier for an ID_BAG
// todo (6.0) - finish
[[collection-semantics-influence]]
==== Influencing CollectionSemantics
Hibernate provides multiple ways to influence the `CollectionSemantics used to
map any particular plural attribute:
1. <<collection-classification-ann, @CollectionClassificationType>>
2. <<collection-semantics-ann, @CollectionSemantics>>
3. <<collection-type-ann>>
[[collection-classification-ann]]
===== @CollectionClassificationType
`@CollectionClassificationType` allows directly telling Hibernate which semantics to use
through its classification.
For example, as discussed in <<collection-bag>>, Hibernate will map a `java.util.Collection`
using BAG semantics by default.
As seen in <<collection-bag-list-ex>>, we can use the `@CollectionClassificationType`
annotation to request it handled using a different semantic - there LIST.
In fact, we can use this technique with any of the classifications as long
as the attribute's declared type on the domain model is assignable from the type
implied by the semantic associated with the classification. The most common case where
this would be useful is when exposing a plural attribute using `java.util.Collection` but
telling Hibernate to use a semantic other than BAG. E.g., to use SET semantics for a
`java.util.Collection`
[[collection-bag-set-ex]]
.Collection as SET
====
[source, JAVA, indent=0]
----
include::{classificationTestsDir}/explicit/EntityWithExplicitSetClassification.java[tags=collections-bag-set-ex]
----
====
[[collection-semantics-ann]]
===== @CollectionSemantics
Applications can also use the `@CollectionSemantics` annotation to specify a custom
link:{javadoc-base}/org/hibernate/collection/spi/CollectionSemantics.html[`org.hibernate.collection.spi.CollectionSemantics`]
implementation to use for the plural attribute.
As an example, consider a requirement for a collection with the semantics of a "unique list" - a
cross between the ordered-ness of a `List` and the uniqueness of a `Set`. First the entity:
[[collection-semantics-ann-ex]]
.@CollectionSemantics
====
[source, JAVA, indent=0]
----
include::{coreCollectionTestsDir}/semantics/TheEntityWithUniqueList.java[tags=collections-custom-semantics-ex]
----
====
The mapping specifies that a custom `UniqueListSemantic` should be used as the `CollectionSemantics` for the
`strings` attribute.
[[collection-semantics-ann-impl-ex]]
.@CollectionSemantics
====
[source, JAVA, indent=0]
----
include::{coreCollectionTestsDir}/semantics/UniqueListSemantic.java[tags=collections-custom-semantics-ex]
----
====
`UniqueListSemantic` defines the actual semantics of what a unique list is and how Hibernate should handle it.
See the `CollectionSemantics` link:{javadoc-base}/org/hibernate/collection/spi/CollectionSemantics.html[javadoc] for
details.
[[collection-semantics-ann-wrapper-ex]]
.PersistentCollection
====
[source, JAVA, indent=0]
----
include::{coreCollectionTestsDir}/semantics/UniqueListWrapper.java[tags=collections-custom-semantics-ex]
----
====
Most custom `CollectionSemantics` will need their own `PersistentCollection` implementation.
`UniqueListWrapper` is the `PersistentCollection` implementation for the "unique list" semantic.
See <<collection-wrapper>> for more details.
For cases where an application wants to apply the same custom semantic to all
plural attributes of a given classification, Hibernate also provides the
`@CollectionSemanticsRegistration`:
// todo (6.0) - example of using `@CollectionSemanticsRegistration`
[[collection-type-ann]]
===== @CollectionType
==== @CollectionType
The `@CollectionType` annotation provides the ability to use a custom
link:{javadoc-base}/org/hibernate/usertype/UserCollectionType.html[`UserCollectionType`]
implementation.
implementation to influence how the collection for a plural attribute behaves.
Let's revisit the requirement of needing a unique list that was used
in <<collection-semantics-ann>> and see how to implement the same behavior using
`UserCollectionType`.
As an example, consider a requirement for a collection with the semantics of a "unique list" - a
cross between the ordered-ness of a `List` and the uniqueness of a `Set`. First the entity:
[[collection-type-ann-ex]]
@ -499,7 +397,7 @@ in <<collection-semantics-ann>> and see how to implement the same behavior using
====
[source, JAVA, indent=0]
----
include::{coreCollectionTestsDir}/semantics/AnotherEntityWithUniqueList.java[tags=collections-custom-type-ex]
include::{coreCollectionTestsDir}/semantics/TheEntityWithUniqueList.java[tags=ex-collections-custom-type-model]
----
====
@ -514,6 +412,30 @@ include::{coreCollectionTestsDir}/semantics/UniqueListType.java[tags=collections
----
====
Most custom `UserCollectionType` implementations will want their own `PersistentCollection` implementation.
[[collection-type-usertype-wrapper-ex]]
.UniqueListWrapper
====
[source, JAVA, indent=0]
----
include::{coreCollectionTestsDir}/semantics/UniqueListWrapper.java[tags=collections-custom-semantics-ex]
----
====
`UniqueListWrapper` is the `PersistentCollection` implementation for the "unique list" semantic. See <<collection-wrapper>> for more details.
For cases where an application wants to apply the same custom type to all
plural attributes of a given classification, Hibernate also provides the
`@CollectionTypeRegistration`:
// todo (6.0) - example of using `@CollectionTypeRegistration`
[[collection-type-reg-ann]]
==== @CollectionTypeRegistration
[[collection-wrapper]]

View File

@ -15,11 +15,21 @@ import java.util.Queue;
import org.hibernate.HibernateException;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.usertype.UserCollectionType;
//tag::collections-custom-collection-mapping-example[]
public class QueueType implements UserCollectionType {
@Override
public CollectionClassification getClassification() {
return CollectionClassification.BAG;
}
@Override
public Class<?> getCollectionClass() {
return Queue.class;
}
@Override
public PersistentCollection instantiate(

View File

@ -6,7 +6,7 @@
*/
package org.hibernate.userguide.mapping.basic;
import org.hibernate.annotations.CustomType;
import org.hibernate.annotations.Type;
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
import org.junit.Test;
@ -48,7 +48,7 @@ public class EnumerationCustomTypeTest extends BaseEntityManagerFunctionalTestCa
private String name;
@CustomType(org.hibernate.userguide.mapping.basic.GenderType.class)
@Type(org.hibernate.userguide.mapping.basic.GenderType.class)
public Gender gender;
//Getters and setters are omitted for brevity

View File

@ -9,7 +9,7 @@ package org.hibernate.userguide.mapping.basic;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import org.hibernate.annotations.CustomType;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.Parameter;
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
import org.hibernate.usertype.UserTypeLegacyBridge;
@ -46,13 +46,13 @@ public class ExplicitTypeTest extends BaseEntityManagerFunctionalTestCase {
private String sku;
@CustomType(
@Type(
value = UserTypeLegacyBridge.class,
parameters = @Parameter(name = UserTypeLegacyBridge.TYPE_NAME_PARAM_KEY, value = "nstring")
)
private String name;
@CustomType(
@Type(
value = UserTypeLegacyBridge.class,
parameters = @Parameter(name = UserTypeLegacyBridge.TYPE_NAME_PARAM_KEY, value = "materialized_nclob")
)

View File

@ -8,7 +8,7 @@ package org.hibernate.userguide.mapping.basic.bitset;
import java.util.BitSet;
import org.hibernate.annotations.CustomType;
import org.hibernate.annotations.Type;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
@ -107,7 +107,7 @@ public class BitSetUserTypeTest extends BaseCoreFunctionalTestCase {
@Id
private Integer id;
@CustomType(BitSetUserType.class)
@Type(BitSetUserType.class)
@Column(name = "bitset_col")
private BitSet bitSet;

View File

@ -14,14 +14,15 @@ import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Specifies a custom {@link org.hibernate.collection.spi.CollectionSemantics}
* Can be used to map a {@link java.util.List}-valued attribute using
* {@link org.hibernate.metamodel.CollectionClassification#BAG} semantics.
*
* @since 6.0
* @apiNote Ignored if either {@link jakarta.persistence.OrderColumn} or
* {@link ListIndexBase} is used.
*
* @author Steve Ebersole
*/
@java.lang.annotation.Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
public @interface CollectionSemantics {
Class<? extends org.hibernate.collection.spi.CollectionSemantics> value();
public @interface Bag {
}

View File

@ -1,27 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.annotations;
import java.lang.annotation.Retention;
import org.hibernate.metamodel.CollectionClassification;
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;
/**
* @since 6.0
*
* @author Steve Ebersole
*/
@java.lang.annotation.Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
public @interface CollectionClassificationType {
CollectionClassification value();
}

View File

@ -15,7 +15,7 @@ import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Form of {@link CustomType} for describing the id of an id-bag mapping
* Form of {@link Type} for describing the id of an id-bag mapping
*
* @since 6.0
*/
@ -26,7 +26,7 @@ public @interface CollectionIdCustomType {
/**
* The custom type implementor class
*
* @see CustomType#value
* @see Type#value
*/
Class<? extends UserType<?>> value();
@ -37,7 +37,7 @@ public @interface CollectionIdCustomType {
* The type should implement {@link org.hibernate.usertype.ParameterizedType}
* to receive the parameters
*
* @see CustomType#parameters
* @see Type#parameters
*/
Parameter[] parameters() default {};
}

View File

@ -1,45 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.annotations;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import org.hibernate.metamodel.CollectionClassification;
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;
/**
* Allows to register a {@link org.hibernate.collection.spi.CollectionSemantics}
* to use as the default for the specified classification of collection.
*
* @see CollectionClassificationType
* @see CollectionSemantics
* @see org.hibernate.collection.spi.CollectionSemantics
*
* @since 6.0
*
* @author Steve Ebersole
*/
@java.lang.annotation.Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Repeatable( CollectionSemanticsRegistrations.class )
public @interface CollectionSemanticsRegistration {
/**
* The collection classification for which the supplied semantic applies
*/
CollectionClassification classification();
/**
* The semantic to apply. Will be applied to all collections of the given
* classification which do not define an explicit {@link org.hibernate.collection.spi.CollectionSemantics}
*/
Class<? extends org.hibernate.collection.spi.CollectionSemantics<?,?>> semantics();
}

View File

@ -29,18 +29,6 @@ public @interface CollectionType {
*/
Class<? extends UserCollectionType> type();
/**
* Specifies the class to use the semantics of.
*
* For example, specifying {@link java.util.Set} will use Set semantics.
*
* When not specified, will be inferred from the interfaces on the property
* as long as it extends a standard {@link java.util.Collection} or {@link java.util.Map}.
*
* @return the class to use the semantics of.
*/
Class<?> semantics() default void.class;
/**
* Specifies configuration information for the type. Note that if the named type is a
* {@link org.hibernate.usertype.UserCollectionType}, it must also implement

View File

@ -0,0 +1,53 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.annotations;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.usertype.UserCollectionType;
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.ElementType.PACKAGE;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Allows to register a {@link org.hibernate.usertype.UserCollectionType}
* to use as the default for the specified classification of collection.
*
* @see CollectionType
*
* @since 6.0
*
* @author Steve Ebersole
*/
@java.lang.annotation.Target({TYPE, PACKAGE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Repeatable( CollectionTypeRegistrations.class )
public @interface CollectionTypeRegistration {
/**
* The collection classification for which the supplied type applies
*/
CollectionClassification classification();
/**
* Specifies the UserCollectionType to use when we encounter
* a plural attribute classified as {@link #classification()}
*/
Class<? extends UserCollectionType> type();
/**
* Specifies configuration information for the type. Note that if the named type is a
* {@link org.hibernate.usertype.UserCollectionType}, it must also implement
* {@link org.hibernate.usertype.ParameterizedType} in order to receive these values.
*/
Parameter[] parameters() default {};
}

View File

@ -11,20 +11,21 @@ import java.lang.annotation.Retention;
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.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Repeatable container for {@link CollectionSemanticsRegistration}
* Repeatable container for {@link CollectionTypeRegistration}
*
* @since 6.0
*
* @author Steve Ebersole
*/
@java.lang.annotation.Target({METHOD, FIELD, ANNOTATION_TYPE})
@java.lang.annotation.Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
public @interface CollectionSemanticsRegistrations {
public @interface CollectionTypeRegistrations {
/**
* The individual CollectionSemanticsRegistrations
* The individual CollectionTypeRegistration
*/
CollectionSemanticsRegistration[] value();
CollectionTypeRegistration[] value();
}

View File

@ -9,7 +9,7 @@ package org.hibernate.annotations;
import org.hibernate.usertype.UserType;
/**
* Form of {@link CustomType} for use with map-keys
* Form of {@link Type} for use with map-keys
*
* @since 6.0
*/
@ -17,14 +17,14 @@ public @interface MapKeyCustomType {
/**
* The custom type implementor class
*
* @see CustomType#value
* @see Type#value
*/
Class<? extends UserType<?>> value();
/**
* Parameters for the custom type
*
* @see CustomType#parameters
* @see Type#parameters
*/
Parameter[] parameters() default {};
}

View File

@ -22,7 +22,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
*/
@java.lang.annotation.Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface CustomType {
public @interface Type {
/**
* The custom type implementor class

View File

@ -31,7 +31,7 @@
* </li>
* <li>
* Contracted via the {@link org.hibernate.usertype.UserType} interface and specified using
* {@link org.hibernate.annotations.CustomType}.
* {@link org.hibernate.annotations.Type}.
* As with the compositional approach, there are model-part specific annotations for specifying
* custom-types as well.
* </li>

View File

@ -15,6 +15,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@ -27,6 +28,8 @@ import org.hibernate.DuplicateMappingException;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.SessionFactory;
import org.hibernate.annotations.CollectionTypeRegistration;
import org.hibernate.annotations.Parameter;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.boot.CacheRegionDefinition;
import org.hibernate.boot.SessionFactoryBuilder;
@ -54,6 +57,7 @@ import org.hibernate.boot.query.NamedProcedureCallDefinition;
import org.hibernate.boot.query.NamedResultSetMappingDescriptor;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.InFlightMetadataCollector;
import org.hibernate.boot.spi.InFlightMetadataCollector.CollectionTypeRegistrationDescriptor;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.boot.spi.MetadataBuildingOptions;
import org.hibernate.boot.spi.NaturalIdUniqueKeyBinder;
@ -95,12 +99,14 @@ import org.hibernate.mapping.RootClass;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.Table;
import org.hibernate.mapping.UniqueKey;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.metamodel.EmbeddableInstantiator;
import org.hibernate.query.named.NamedObjectRepository;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.spi.TypeConfiguration;
import org.hibernate.usertype.UserCollectionType;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Embeddable;
@ -407,6 +413,48 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
return registeredInstantiators.get( embeddableType );
}
private Map<CollectionClassification, CollectionTypeRegistrationDescriptor> collectionTypeRegistrations;
@Override
public void addCollectionTypeRegistration(CollectionTypeRegistration registrationAnnotation) {
addCollectionTypeRegistration(
registrationAnnotation.classification(),
toDescriptor( registrationAnnotation )
);
}
@Override
public void addCollectionTypeRegistration(CollectionClassification classification, CollectionTypeRegistrationDescriptor descriptor) {
if ( collectionTypeRegistrations == null ) {
collectionTypeRegistrations = new HashMap<>();
}
collectionTypeRegistrations.put( classification, descriptor );
}
@Override
public CollectionTypeRegistrationDescriptor findCollectionTypeRegistration(CollectionClassification classification) {
if ( collectionTypeRegistrations == null ) {
return null;
}
return collectionTypeRegistrations.get( classification );
}
private CollectionTypeRegistrationDescriptor toDescriptor(CollectionTypeRegistration registrationAnnotation) {
final Properties parameters;
if ( registrationAnnotation.parameters().length > 0 ) {
parameters = new Properties();
for ( Parameter parameter : registrationAnnotation.parameters() ) {
parameters.put( parameter.name(), parameter.value() );
}
}
else {
parameters = null;
}
return new CollectionTypeRegistrationDescriptor( registrationAnnotation.type(), parameters );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// attribute converters

View File

@ -10,11 +10,13 @@ import java.io.Serializable;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.function.Function;
import org.hibernate.DuplicateMappingException;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.annotations.CollectionTypeRegistration;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.boot.internal.ClassmateContext;
import org.hibernate.boot.internal.NamedProcedureCallDefinitionImpl;
@ -49,9 +51,11 @@ import org.hibernate.mapping.Join;
import org.hibernate.mapping.MappedSuperclass;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Table;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.metamodel.EmbeddableInstantiator;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.usertype.UserCollectionType;
import jakarta.persistence.AttributeConverter;
@ -323,6 +327,10 @@ public interface InFlightMetadataCollector extends Mapping, MetadataImplementor
void registerEmbeddableInstantiator(Class<?> embeddableType, Class<? extends EmbeddableInstantiator> instantiator);
Class<? extends EmbeddableInstantiator> findRegisteredEmbeddableInstantiator(Class<?> embeddableType);
void addCollectionTypeRegistration(CollectionTypeRegistration registrationAnnotation);
void addCollectionTypeRegistration(CollectionClassification classification, CollectionTypeRegistrationDescriptor descriptor);
CollectionTypeRegistrationDescriptor findCollectionTypeRegistration(CollectionClassification classification);
interface DelayedPropertyReferenceHandler extends Serializable {
void process(InFlightMetadataCollector metadataCollector);
}
@ -371,4 +379,23 @@ public interface InFlightMetadataCollector extends Mapping, MetadataImplementor
Table primaryTable,
EntityTableXref superEntityTableXref);
Map<String,Join> getJoins(String entityName);
class CollectionTypeRegistrationDescriptor {
private final Class<? extends UserCollectionType> implementation;
private final Properties parameters;
public CollectionTypeRegistrationDescriptor(Class<? extends UserCollectionType> implementation, Properties parameters) {
this.implementation = implementation;
this.parameters = parameters;
}
public Class<? extends UserCollectionType> getImplementation() {
return implementation;
}
public Properties getParameters() {
return parameters;
}
}
}

View File

@ -19,7 +19,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.hibernate.AnnotationException;
@ -33,6 +32,8 @@ import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.Check;
import org.hibernate.annotations.CollectionId;
import org.hibernate.annotations.CollectionTypeRegistration;
import org.hibernate.annotations.CollectionTypeRegistrations;
import org.hibernate.annotations.Columns;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.DiscriminatorFormula;
@ -873,16 +874,18 @@ public final class AnnotationBinder {
}
}
}
final CollectionTypeRegistration singleRegistration = annotatedElement.getAnnotation( CollectionTypeRegistration.class );
if ( singleRegistration != null ) {
context.getMetadataCollector().addCollectionTypeRegistration( singleRegistration );
}
private static Properties extractProperties(Parameter[] parameters) {
final Properties properties = new Properties();
if ( parameters.length > 0 ) {
for ( int i = 0; i < parameters.length; i++ ) {
properties.setProperty( parameters[i].name(), parameters[i].value() );
final CollectionTypeRegistrations multiRegistration = annotatedElement.getAnnotation( CollectionTypeRegistrations.class );
if ( multiRegistration != null ) {
for ( CollectionTypeRegistration registration : multiRegistration.value() ) {
context.getMetadataCollector().addCollectionTypeRegistration( registration );
}
}
return properties;
}
private static void handleSqlTypeDescriptorRegistration(

View File

@ -19,7 +19,7 @@ import java.util.Map;
import java.util.TreeMap;
import org.hibernate.AnnotationException;
import org.hibernate.annotations.CustomType;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.JavaType;
import org.hibernate.annotations.ManyToAny;
import org.hibernate.annotations.Target;
@ -385,7 +385,7 @@ class PropertyContainer {
else if ( p.isAnnotationPresent( Basic.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( CustomType.class ) ) {
else if ( p.isAnnotationPresent( Type.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( JavaType.class ) ) {

View File

@ -6,11 +6,15 @@
*/
package org.hibernate.cfg.annotations;
import java.util.function.Supplier;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.mapping.Array;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.SemanticsResolver;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.usertype.UserCollectionType;
/**
* Bind an Array
@ -18,11 +22,11 @@ import org.hibernate.mapping.SemanticsResolver;
* @author Anthony Patricio
*/
public class ArrayBinder extends ListBinder {
public ArrayBinder(SemanticsResolver semanticsResolver, MetadataBuildingContext buildingContext) {
super( semanticsResolver, buildingContext );
public ArrayBinder(Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver, MetadataBuildingContext buildingContext) {
super( customTypeBeanResolver, buildingContext );
}
protected Collection createCollection(PersistentClass owner) {
return new Array( getSemanticsResolver(), owner, getBuildingContext() );
return new Array( getCustomTypeBeanResolver(), owner, getBuildingContext() );
}
}

View File

@ -6,10 +6,14 @@
*/
package org.hibernate.cfg.annotations;
import java.util.function.Supplier;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.SemanticsResolver;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.usertype.UserCollectionType;
/**
* Bind a bag.
@ -17,11 +21,11 @@ import org.hibernate.mapping.SemanticsResolver;
* @author Matthew Inger
*/
public class BagBinder extends CollectionBinder {
public BagBinder(SemanticsResolver semanticsResolver, MetadataBuildingContext context) {
super( semanticsResolver, false, context );
public BagBinder(Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver, MetadataBuildingContext context) {
super( customTypeBeanResolver, false, context );
}
protected Collection createCollection(PersistentClass owner) {
return new org.hibernate.mapping.Bag( getSemanticsResolver(), owner, getBuildingContext() );
return new org.hibernate.mapping.Bag( getCustomTypeBeanResolver(), owner, getBuildingContext() );
}
}

View File

@ -31,7 +31,7 @@ import org.hibernate.annotations.CollectionIdJavaType;
import org.hibernate.annotations.CollectionIdJdbcType;
import org.hibernate.annotations.CollectionIdJdbcTypeCode;
import org.hibernate.annotations.CollectionIdMutability;
import org.hibernate.annotations.CustomType;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.Immutable;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.annotations.ListIndexJavaType;
@ -1434,7 +1434,7 @@ public class BasicValueBinder<T> implements JdbcTypeDescriptorIndicators {
@Override
public Class<? extends UserType<?>> customType(XProperty xProperty) {
final CustomType customType = findAnnotation( xProperty, CustomType.class );
final Type customType = findAnnotation( xProperty, Type.class );
if ( customType == null ) {
return null;
}
@ -1444,7 +1444,7 @@ public class BasicValueBinder<T> implements JdbcTypeDescriptorIndicators {
@Override
public Parameter[] customTypeParameters(XProperty xProperty) {
final CustomType customType = findAnnotation( xProperty, CustomType.class );
final Type customType = findAnnotation( xProperty, Type.class );
if ( customType == null ) {
return null;
}

View File

@ -13,19 +13,19 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.function.Supplier;
import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.FetchMode;
import org.hibernate.MappingException;
import org.hibernate.annotations.Bag;
import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CollectionClassificationType;
import org.hibernate.annotations.CollectionId;
import org.hibernate.annotations.CollectionIdJavaType;
import org.hibernate.annotations.CollectionIdJdbcType;
import org.hibernate.annotations.CollectionIdJdbcTypeCode;
import org.hibernate.annotations.CollectionSemantics;
import org.hibernate.annotations.CollectionType;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.Filter;
@ -60,19 +60,22 @@ import org.hibernate.annotations.Where;
import org.hibernate.annotations.WhereJoinTable;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.boot.BootLogging;
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
import org.hibernate.boot.model.TypeDefinition;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.spi.InFlightMetadataCollector;
import org.hibernate.boot.spi.InFlightMetadataCollector.CollectionTypeRegistrationDescriptor;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.cfg.AccessType;
import org.hibernate.cfg.AnnotatedClassType;
import org.hibernate.cfg.AnnotatedColumn;
import org.hibernate.cfg.AnnotatedJoinColumn;
import org.hibernate.cfg.AnnotationBinder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.BinderHelper;
import org.hibernate.cfg.CollectionPropertyHolder;
import org.hibernate.cfg.CollectionSecondPass;
import org.hibernate.cfg.AnnotatedColumn;
import org.hibernate.cfg.AnnotatedJoinColumn;
import org.hibernate.cfg.IndexColumn;
import org.hibernate.cfg.InheritanceState;
import org.hibernate.cfg.PropertyData;
@ -81,11 +84,11 @@ import org.hibernate.cfg.PropertyHolderBuilder;
import org.hibernate.cfg.PropertyInferredData;
import org.hibernate.cfg.PropertyPreloadedData;
import org.hibernate.cfg.SecondPass;
import org.hibernate.collection.internal.CustomCollectionTypeSemantics;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.mapping.Any;
import org.hibernate.mapping.Backref;
@ -99,13 +102,14 @@ import org.hibernate.mapping.ManyToOne;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Selectable;
import org.hibernate.mapping.SemanticsResolver;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.Table;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.metamodel.EmbeddableInstantiator;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.usertype.ParameterizedType;
import org.hibernate.usertype.UserCollectionType;
import org.jboss.logging.Logger;
@ -150,7 +154,7 @@ public abstract class CollectionBinder {
);
private final MetadataBuildingContext buildingContext;
private final SemanticsResolver semanticsResolver;
private final Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver;
private final boolean isSortedCollection;
protected Collection collection;
@ -194,8 +198,11 @@ public abstract class CollectionBinder {
private String explicitType;
private final Properties explicitTypeParameters = new Properties();
protected CollectionBinder(SemanticsResolver semanticsResolver, boolean isSortedCollection, MetadataBuildingContext buildingContext) {
this.semanticsResolver = semanticsResolver;
protected CollectionBinder(
Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver,
boolean isSortedCollection,
MetadataBuildingContext buildingContext) {
this.customTypeBeanResolver = customTypeBeanResolver;
this.isSortedCollection = isSortedCollection;
this.buildingContext = buildingContext;
}
@ -204,8 +211,8 @@ public abstract class CollectionBinder {
return buildingContext;
}
protected SemanticsResolver getSemanticsResolver() {
return semanticsResolver;
public Supplier<ManagedBean<? extends UserCollectionType>> getCustomTypeBeanResolver() {
return customTypeBeanResolver;
}
public boolean isMap() {
@ -286,15 +293,20 @@ public abstract class CollectionBinder {
final CollectionBinder binder;
if ( typeAnnotation != null ) {
binder = createBinderFromCustomTypeAnnotation( property, typeAnnotation, buildingContext );
// todo (6.0) - technically, these should no longer be needed
binder.explicitType = typeAnnotation.type().getName();
for ( Parameter param : typeAnnotation.parameters() ) {
binder.explicitTypeParameters.setProperty( param.name(), param.value() );
}
}
else {
final CollectionSemantics customSemantics = property.getAnnotation( CollectionSemantics.class );
if ( customSemantics != null ) {
binder = createBinderFromCustomSemantics( customSemantics, property, buildingContext );
final CollectionClassification classification = determineCollectionClassification( property, buildingContext );
final CollectionTypeRegistrationDescriptor typeRegistration = buildingContext
.getMetadataCollector()
.findCollectionTypeRegistration( classification );
if ( typeRegistration != null ) {
binder = createBinderFromTypeRegistration( property, classification, typeRegistration, buildingContext );
}
else {
binder = createBinderFromProperty( property, buildingContext );
@ -306,74 +318,164 @@ public abstract class CollectionBinder {
return binder;
}
private static CollectionBinder createBinderFromCustomSemantics(
CollectionSemantics customSemantics,
private static CollectionBinder createBinderFromTypeRegistration(
XProperty property,
CollectionClassification classification,
CollectionTypeRegistrationDescriptor typeRegistration,
MetadataBuildingContext buildingContext) {
final ManagedBeanRegistry beanRegistry = buildingContext.getBootstrapContext()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class );
final ManagedBean<? extends org.hibernate.collection.spi.CollectionSemantics> semanticsBean = beanRegistry.getBean( customSemantics.value() );
final org.hibernate.collection.spi.CollectionSemantics semantics = semanticsBean.getBeanInstance();
return createBinder(
property,
semantics.getCollectionClassification(),
(type) -> semantics,
() -> createCustomType(
property.getDeclaringClass().getName() + "#" + property.getName(),
typeRegistration.getImplementation(),
typeRegistration.getParameters(),
buildingContext
),
classification,
buildingContext
);
}
private static ManagedBean<? extends UserCollectionType> createCustomType(
String role,
Class<? extends UserCollectionType> implementation,
Properties parameters,
MetadataBuildingContext buildingContext) {
final StandardServiceRegistry serviceRegistry = buildingContext.getBuildingOptions().getServiceRegistry();
final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
if ( CollectionHelper.isNotEmpty( parameters ) ) {
return beanRegistry.getBean( implementation );
}
else {
// defined parameters...
if ( ParameterizedType.class.isAssignableFrom( implementation ) ) {
// because there are config parameters and the type is configurable, we need
// a separate bean instance which means uniquely naming it
final ManagedBean<? extends UserCollectionType> typeBean = beanRegistry.getBean( role, implementation );
final UserCollectionType type = typeBean.getBeanInstance();
( (ParameterizedType) type ).setParameterValues( parameters );
return typeBean;
}
else {
// log a "warning"
BootLogging.LOGGER.debugf(
"Custom collection-type (`%s`) assigned to attribute (`%s`) does not implement `%s`, but its `@CollectionType` defined parameters",
implementation.getName(),
role,
ParameterizedType.class.getName()
);
// but still return the bean - we can again use the no-config bean instance
return beanRegistry.getBean( implementation );
}
}
}
private static CollectionBinder createBinderFromProperty(
XProperty property,
MetadataBuildingContext buildingContext) {
final CollectionClassification classification = determineCollectionClassification( property, null, buildingContext );
return createBinder( property, classification, null, buildingContext );
final CollectionClassification classification = determineCollectionClassification( property, buildingContext );
return createBinder( property, null, classification, buildingContext );
}
private static CollectionBinder createBinderFromCustomTypeAnnotation(
XProperty property,
CollectionType typeAnnotation,
MetadataBuildingContext buildingContext) {
final CollectionClassification classification = determineCollectionClassification( property, typeAnnotation, buildingContext );
final SemanticsResolver semanticsResolver = (collectionType) -> new CustomCollectionTypeSemantics<>( collectionType, classification );
return createBinder( property, classification, semanticsResolver, buildingContext );
determineSemanticJavaType( property );
final ManagedBean<? extends UserCollectionType> customTypeBean = resolveCustomType( property, typeAnnotation, buildingContext );
return createBinder(
property,
() -> customTypeBean,
customTypeBean.getBeanInstance().getClassification(),
buildingContext
);
}
public static ManagedBean<? extends UserCollectionType> resolveCustomType(
XProperty property,
CollectionType typeAnnotation,
MetadataBuildingContext buildingContext) {
final ManagedBeanRegistry beanRegistry = buildingContext.getBootstrapContext()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class );
final Class<? extends UserCollectionType> typeImpl = typeAnnotation.type();
if ( typeAnnotation.parameters().length == 0 ) {
// no parameters - we can re-use a no-config bean instance
return beanRegistry.getBean( typeImpl );
}
else {
// defined parameters...
final String attributeKey = property.getDeclaringClass().getName() + "#" + property.getName();
if ( ParameterizedType.class.isAssignableFrom( typeImpl ) ) {
// because there are config parameters and the type is configurable, we need
// a separate bean instance which means uniquely naming it
final ManagedBean<? extends UserCollectionType> typeBean = beanRegistry.getBean( attributeKey, typeImpl );
final UserCollectionType type = typeBean.getBeanInstance();
( (ParameterizedType) type ).setParameterValues( extractParameters( typeAnnotation ) );
return typeBean;
}
else {
// log a "warning"
BootLogging.LOGGER.debugf(
"Custom collection-type (`%s`) assigned to attribute (`%s`) does not implement `%s`, but its `@CollectionType` defined parameters",
typeImpl.getName(),
attributeKey,
ParameterizedType.class.getName()
);
// but still return the bean - we can again use the no-config bean instance
return beanRegistry.getBean( typeImpl );
}
}
}
private static Properties extractParameters(CollectionType typeAnnotation) {
final Parameter[] parameterAnnotations = typeAnnotation.parameters();
final Properties configParams = new Properties( parameterAnnotations.length );
for ( Parameter parameterAnnotation : parameterAnnotations ) {
configParams.put( parameterAnnotation.name(), parameterAnnotation.value() );
}
return configParams;
}
private static CollectionBinder createBinder(
XProperty property,
Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanAccess,
CollectionClassification classification,
SemanticsResolver semanticsResolver,
MetadataBuildingContext buildingContext) {
switch ( classification ) {
case ARRAY: {
if ( property.getElementClass().isPrimitive() ) {
return new PrimitiveArrayBinder( semanticsResolver, buildingContext );
return new PrimitiveArrayBinder( customTypeBeanAccess, buildingContext );
}
return new ArrayBinder( semanticsResolver, buildingContext );
return new ArrayBinder( customTypeBeanAccess, buildingContext );
}
case BAG: {
return new BagBinder( semanticsResolver, buildingContext );
return new BagBinder( customTypeBeanAccess, buildingContext );
}
case ID_BAG: {
return new IdBagBinder( semanticsResolver, buildingContext );
return new IdBagBinder( customTypeBeanAccess, buildingContext );
}
case LIST: {
return new ListBinder( semanticsResolver, buildingContext );
return new ListBinder( customTypeBeanAccess, buildingContext );
}
case MAP:
case ORDERED_MAP: {
return new MapBinder( semanticsResolver, false, buildingContext );
return new MapBinder( customTypeBeanAccess, false, buildingContext );
}
case SORTED_MAP: {
return new MapBinder( semanticsResolver, true, buildingContext );
return new MapBinder( customTypeBeanAccess, true, buildingContext );
}
case SET:
case ORDERED_SET: {
return new SetBinder( semanticsResolver, false, buildingContext );
return new SetBinder( customTypeBeanAccess, false, buildingContext );
}
case SORTED_SET: {
return new SetBinder( semanticsResolver, true, buildingContext );
return new SetBinder( customTypeBeanAccess, true, buildingContext );
}
}
@ -392,23 +494,32 @@ public abstract class CollectionBinder {
private static CollectionClassification determineCollectionClassification(
XProperty property,
CollectionType typeAnnotation,
MetadataBuildingContext buildingContext) {
final CollectionClassificationType classificationTypeAnnotation = property.getAnnotation( CollectionClassificationType.class );
if ( property.isArray() ) {
if ( classificationTypeAnnotation != null ) {
throw new AnnotationException( "Arrays should not be annotated with `@" + CollectionClassificationType.class.getName() + "`" );
}
return CollectionClassification.ARRAY;
}
if ( classificationTypeAnnotation != null ) {
return classificationTypeAnnotation.value();
final Bag bagAnnotation = HCANNHelper.findAnnotation( property, Bag.class );
if ( bagAnnotation != null ) {
final Class<?> collectionJavaType = property.getCollectionClass();
if ( java.util.List.class.equals( collectionJavaType ) || java.util.Collection.class.equals( collectionJavaType ) ) {
return CollectionClassification.BAG;
}
throw new MappingException(
String.format(
Locale.ROOT,
"@Bag annotation encountered on an attribute `%s#%s` of type `%s`; only `%s` and `%s` are supported",
property.getDeclaringClass().getName(),
property.getName(),
collectionJavaType.getName(),
java.util.List.class.getName(),
java.util.Collection.class.getName()
)
);
}
return determineCollectionClassification(
determineSemanticJavaType( property, typeAnnotation ),
determineSemanticJavaType( property ),
property,
buildingContext
);
@ -466,14 +577,7 @@ public abstract class CollectionBinder {
}
}
private static Class<?> determineSemanticJavaType(XProperty property, CollectionType typeAnnotation) {
if ( typeAnnotation != null ) {
final Class<?> requestedSemanticsJavaType = typeAnnotation.semantics();
if ( requestedSemanticsJavaType != null && requestedSemanticsJavaType != void.class ) {
return inferCollectionClassFromSubclass( requestedSemanticsJavaType );
}
}
private static Class<?> determineSemanticJavaType(XProperty property) {
final Class<?> returnedJavaType = property.getCollectionClass();
if ( returnedJavaType == null ) {
throw new AnnotationException(

View File

@ -8,6 +8,7 @@ package org.hibernate.cfg.annotations;
import java.util.Collections;
import java.util.Map;
import java.util.function.Supplier;
import org.hibernate.MappingException;
import org.hibernate.annotations.CollectionId;
@ -24,10 +25,13 @@ import org.hibernate.cfg.SecondPass;
import org.hibernate.cfg.WrappedInferredData;
import org.hibernate.mapping.BasicValue;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.IdentifierBag;
import org.hibernate.mapping.IdentifierCollection;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.SemanticsResolver;
import org.hibernate.mapping.Table;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.usertype.UserCollectionType;
import jakarta.persistence.Column;
@ -35,12 +39,12 @@ import jakarta.persistence.Column;
* @author Emmanuel Bernard
*/
public class IdBagBinder extends BagBinder {
public IdBagBinder(SemanticsResolver semanticsResolver, MetadataBuildingContext buildingContext) {
super( semanticsResolver, buildingContext );
public IdBagBinder(Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver, MetadataBuildingContext buildingContext) {
super( customTypeBeanResolver, buildingContext );
}
protected Collection createCollection(PersistentClass owner) {
return new org.hibernate.mapping.IdentifierBag( getSemanticsResolver(), owner, getBuildingContext() );
return new IdentifierBag( getCustomTypeBeanResolver(), owner, getBuildingContext() );
}
@Override

View File

@ -7,6 +7,7 @@
package org.hibernate.cfg.annotations;
import java.util.Map;
import java.util.function.Supplier;
import org.hibernate.MappingException;
import org.hibernate.annotations.OrderBy;
@ -28,6 +29,8 @@ import org.hibernate.mapping.OneToMany;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.SemanticsResolver;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.usertype.UserCollectionType;
import org.jboss.logging.Logger;
@ -41,13 +44,13 @@ import org.jboss.logging.Logger;
public class ListBinder extends CollectionBinder {
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, ListBinder.class.getName() );
public ListBinder(SemanticsResolver semanticsResolver, MetadataBuildingContext buildingContext) {
super( semanticsResolver, false, buildingContext );
public ListBinder(Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver, MetadataBuildingContext buildingContext) {
super( customTypeBeanResolver, false, buildingContext );
}
@Override
protected Collection createCollection(PersistentClass owner) {
return new List( getSemanticsResolver(), owner, getBuildingContext() );
return new List( getCustomTypeBeanResolver(), owner, getBuildingContext() );
}
@Override

View File

@ -9,6 +9,7 @@ package org.hibernate.cfg.annotations;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.function.Supplier;
import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
@ -48,6 +49,8 @@ import org.hibernate.mapping.SemanticsResolver;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.Table;
import org.hibernate.mapping.Value;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.usertype.UserCollectionType;
import jakarta.persistence.AttributeOverride;
import jakarta.persistence.AttributeOverrides;
@ -64,8 +67,8 @@ import jakarta.persistence.MapKeyJoinColumns;
* @author Emmanuel Bernard
*/
public class MapBinder extends CollectionBinder {
public MapBinder(SemanticsResolver semanticsResolver, boolean sorted, MetadataBuildingContext buildingContext) {
super( semanticsResolver, sorted, buildingContext );
public MapBinder(Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver, boolean sorted, MetadataBuildingContext buildingContext) {
super( customTypeBeanResolver, sorted, buildingContext );
}
public boolean isMap() {
@ -73,7 +76,7 @@ public class MapBinder extends CollectionBinder {
}
protected Collection createCollection(PersistentClass owner) {
return new org.hibernate.mapping.Map( getSemanticsResolver(), owner, getBuildingContext() );
return new org.hibernate.mapping.Map( getCustomTypeBeanResolver(), owner, getBuildingContext() );
}
@Override

View File

@ -6,22 +6,25 @@
*/
package org.hibernate.cfg.annotations;
import java.util.function.Supplier;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.PrimitiveArray;
import org.hibernate.mapping.SemanticsResolver;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.usertype.UserCollectionType;
/**
* @author Emmanuel Bernard
*/
public class PrimitiveArrayBinder extends ArrayBinder {
public PrimitiveArrayBinder(SemanticsResolver semanticsResolver, MetadataBuildingContext buildingContext) {
super( semanticsResolver, buildingContext );
public PrimitiveArrayBinder(Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver, MetadataBuildingContext buildingContext) {
super( customTypeBeanResolver, buildingContext );
}
@Override
protected Collection createCollection(PersistentClass owner) {
return new PrimitiveArray( getSemanticsResolver(), owner, getBuildingContext() );
return new PrimitiveArray( getCustomTypeBeanResolver(), owner, getBuildingContext() );
}
}

View File

@ -6,11 +6,15 @@
*/
package org.hibernate.cfg.annotations;
import java.util.function.Supplier;
import org.hibernate.annotations.OrderBy;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.SemanticsResolver;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.usertype.UserCollectionType;
/**
* Bind a set.
@ -18,13 +22,13 @@ import org.hibernate.mapping.SemanticsResolver;
* @author Matthew Inger
*/
public class SetBinder extends CollectionBinder {
public SetBinder(SemanticsResolver semanticsResolver, boolean sorted, MetadataBuildingContext buildingContext) {
super( semanticsResolver, sorted, buildingContext );
public SetBinder(Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver, boolean sorted, MetadataBuildingContext buildingContext) {
super( customTypeBeanResolver, sorted, buildingContext );
}
@Override
protected Collection createCollection(PersistentClass persistentClass) {
return new org.hibernate.mapping.Set( getSemanticsResolver(), persistentClass, getBuildingContext() );
return new org.hibernate.mapping.Set( getCustomTypeBeanResolver(), persistentClass, getBuildingContext() );
}
@Override

View File

@ -30,16 +30,18 @@ import org.hibernate.type.CollectionType;
*/
public class CustomCollectionTypeSemantics<CE, E> implements CollectionSemantics<CE, E> {
private final CollectionType collectionType;
private final CollectionClassification classification;
public CustomCollectionTypeSemantics(CollectionType collectionType, CollectionClassification classification) {
public CustomCollectionTypeSemantics(CollectionType collectionType) {
this.collectionType = collectionType;
this.classification = classification;
}
public CollectionType getCollectionType() {
return collectionType;
}
@Override
public CollectionClassification getCollectionClassification() {
return classification;
return collectionType.getCollectionClassification();
}
@Override
@ -77,7 +79,7 @@ public class CustomCollectionTypeSemantics<CE, E> implements CollectionSemantics
return InitializerProducerBuilder.createCollectionTypeWrapperInitializerProducer(
navigablePath,
attributeMapping,
classification,
getCollectionClassification(),
fetchParent,
selected,
indexFetch,

View File

@ -6,33 +6,39 @@
*/
package org.hibernate.collection.spi;
import java.util.function.Consumer;
import org.hibernate.Incubating;
import org.hibernate.LockMode;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.AssemblerCreationState;
import org.hibernate.sql.results.graph.collection.CollectionInitializer;
import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.FetchParentAccess;
import org.hibernate.sql.results.graph.Initializer;
import org.hibernate.sql.results.graph.collection.CollectionInitializer;
/**
* Functional contract to create a CollectionInitializer
*
* @author Steve Ebersole
*
* @since 6.0
*/
@Incubating
@FunctionalInterface
public interface CollectionInitializerProducer {
/**
* todo (6.0) : clean this contract up!
* Create an initializer for `attribute` relative to `navigablePath`.
*
* `parentAccess` may be null to indicate that the initializer is for
* a {@link org.hibernate.sql.results.graph.DomainResult} rather than
* a {@link org.hibernate.sql.results.graph.Fetch}
*
* `collectionKeyAssembler` and `collectionValueKeyAssembler` allow
* creating {@link org.hibernate.sql.results.graph.DomainResult} for
* either side of the collection foreign-key
*/
CollectionInitializer produceInitializer(
NavigablePath navigablePath,
PluralAttributeMapping attributeMapping,
PluralAttributeMapping attribute,
FetchParentAccess parentAccess,
LockMode lockMode,
DomainResultAssembler<?> collectionKeyAssembler,

View File

@ -27,6 +27,8 @@ import org.hibernate.sql.results.graph.FetchParent;
*
* @author Steve Ebersole
* @author Gavin King
*
* @since 6.0
*/
@Incubating
public interface CollectionSemantics<CE, E> {

View File

@ -500,7 +500,7 @@ public class PersistentBag<E> extends AbstractPersistentCollection<E> implements
@Override
public Object getIndex(Object entry, int i, CollectionPersister persister) {
throw new UnsupportedOperationException( "Bags don't have indexes" );
throw new UnsupportedOperationException( "Bags don't have indexes : " + persister.getRole() );
}
@Override

View File

@ -6,7 +6,7 @@
*/
package org.hibernate.mapping;
import java.util.function.Function;
import java.util.function.Supplier;
import org.hibernate.MappingException;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
@ -14,10 +14,12 @@ import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.collection.internal.StandardArraySemantics;
import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.type.ArrayType;
import org.hibernate.type.BasicType;
import org.hibernate.type.CollectionType;
import org.hibernate.type.descriptor.java.spi.PrimitiveJavaType;
import org.hibernate.usertype.UserCollectionType;
/**
* An array mapping has a primary key consisting of the key columns + index column.
@ -31,8 +33,8 @@ public class Array extends List {
super( buildingContext, owner );
}
public Array(SemanticsResolver semanticsResolver, PersistentClass owner, MetadataBuildingContext buildingContext) {
super( semanticsResolver, owner, buildingContext );
public Array(Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver, PersistentClass owner, MetadataBuildingContext buildingContext) {
super( customTypeBeanResolver, owner, buildingContext );
}
public Class<?> getElementClass() throws MappingException {

View File

@ -7,12 +7,15 @@
package org.hibernate.mapping;
import java.util.function.Function;
import java.util.function.Supplier;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.collection.internal.StandardBagSemantics;
import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.type.BagType;
import org.hibernate.type.CollectionType;
import org.hibernate.usertype.UserCollectionType;
/**
* A bag permits duplicates, so it has no primary key
@ -30,8 +33,8 @@ public class Bag extends Collection {
/**
* Annotation binding
*/
public Bag(SemanticsResolver semanticsResolver, PersistentClass owner, MetadataBuildingContext buildingContext) {
super( semanticsResolver, owner, buildingContext );
public Bag(Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver, PersistentClass owner, MetadataBuildingContext buildingContext) {
super( customTypeBeanResolver, owner, buildingContext );
}
public CollectionType getDefaultCollectionType() {

View File

@ -14,8 +14,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.function.Supplier;
import org.hibernate.FetchMode;
import org.hibernate.MappingException;
@ -29,12 +28,14 @@ import org.hibernate.engine.spi.Mapping;
import org.hibernate.internal.FilterConfiguration;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.CollectionType;
import org.hibernate.type.CustomCollectionType;
import org.hibernate.type.Type;
import org.hibernate.type.spi.TypeConfiguration;
import org.hibernate.usertype.UserCollectionType;
/**
* Mapping for a collection. Subclasses specialize to particular collection styles.
@ -77,7 +78,10 @@ public abstract class Collection implements Fetchable, Value, Filterable {
private String typeName;
private Properties typeParameters;
private SemanticsResolver customSemanticsResolver;
private Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver;
private CollectionType cachedCollectionType;
private CollectionSemantics<?,?> cachedCollectionSemantics;
private Class<? extends CollectionPersister> collectionPersisterClass;
private final List<FilterConfiguration> filters = new ArrayList<>();
@ -110,8 +114,11 @@ public abstract class Collection implements Fetchable, Value, Filterable {
/**
* Annotation binding
*/
protected Collection(SemanticsResolver customSemanticsResolver, PersistentClass owner, MetadataBuildingContext buildingContext) {
this.customSemanticsResolver = customSemanticsResolver;
protected Collection(
Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver,
PersistentClass owner,
MetadataBuildingContext buildingContext) {
this.customTypeBeanResolver = customTypeBeanResolver;
this.owner = owner;
this.buildingContext = buildingContext;
}
@ -409,8 +416,6 @@ public abstract class Collection implements Fetchable, Value, Filterable {
return getCollectionType();
}
private CollectionSemantics<?,?> cachedCollectionSemantics;
@SuppressWarnings("rawtypes")
public CollectionSemantics getCollectionSemantics() {
if ( cachedCollectionSemantics == null ) {
@ -422,8 +427,32 @@ public abstract class Collection implements Fetchable, Value, Filterable {
private CollectionSemantics<?, ?> resolveCollectionSemantics() {
final CollectionType collectionType;
if ( typeName == null ) {
collectionType = null;
if ( cachedCollectionType == null ) {
collectionType = resolveCollectionType();
cachedCollectionType = collectionType;
}
else {
collectionType = cachedCollectionType;
}
return new CustomCollectionTypeSemantics<>( collectionType );
}
private CollectionType resolveCollectionType() {
final CollectionType collectionType;
if ( cachedCollectionType != null ) {
collectionType = cachedCollectionType;
}
else if ( customTypeBeanResolver != null ) {
collectionType = new CustomCollectionType(
customTypeBeanResolver.get(),
role,
referencedPropertyName,
getMetadata().getTypeConfiguration()
);
}
else if ( typeName == null ) {
collectionType = getDefaultCollectionType();
}
else {
collectionType = MappingHelper.customCollection(
@ -434,50 +463,7 @@ public abstract class Collection implements Fetchable, Value, Filterable {
getMetadata()
);
}
if ( customSemanticsResolver != null ) {
return customSemanticsResolver.resolve( collectionType );
}
if ( collectionType == null ) {
return getDefaultCollectionSemantics();
}
final Class<?> semanticJavaType = collectionType.getReturnedClass();
final CollectionClassification classification;
if ( semanticJavaType.isArray() ) {
classification = CollectionClassification.ARRAY;
}
else if ( List.class.isAssignableFrom( semanticJavaType ) ) {
classification = CollectionClassification.LIST;
}
else if ( SortedSet.class.isAssignableFrom( semanticJavaType ) ) {
classification = CollectionClassification.SORTED_SET;
}
else if ( Set.class.isAssignableFrom( semanticJavaType ) ) {
classification = CollectionClassification.SET;
}
else if ( SortedMap.class.isAssignableFrom( semanticJavaType ) ) {
classification = CollectionClassification.SORTED_MAP;
}
else if ( Map.class.isAssignableFrom( semanticJavaType ) ) {
classification = CollectionClassification.MAP;
}
else if ( Collection.class.isAssignableFrom( semanticJavaType ) ) {
if ( isIdentified() ) {
classification = CollectionClassification.ID_BAG;
}
else {
classification = CollectionClassification.BAG;
}
}
else {
throw new IllegalArgumentException( "Unexpected collection-semantics Java type : " + semanticJavaType );
}
return new CustomCollectionTypeSemantics<>( collectionType, classification );
return collectionType;
}
public CollectionSemantics<?,?> getDefaultCollectionSemantics() {
@ -488,13 +474,10 @@ public abstract class Collection implements Fetchable, Value, Filterable {
}
public CollectionType getCollectionType() {
// todo (6.0) : hook in CollectionSemantics
if ( typeName == null ) {
return getDefaultCollectionType();
}
else {
return MappingHelper.customCollection( typeName, typeParameters, role, referencedPropertyName, getMetadata() );
if ( cachedCollectionType == null ) {
cachedCollectionType = resolveCollectionType();
}
return cachedCollectionType;
}
public boolean isNullable() {

View File

@ -6,11 +6,15 @@
*/
package org.hibernate.mapping;
import java.util.function.Supplier;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.collection.internal.StandardIdentifierBagSemantics;
import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.type.CollectionType;
import org.hibernate.type.IdentifierBagType;
import org.hibernate.usertype.UserCollectionType;
/**
* An {@code IdentifierBag} has a primary key consisting of
@ -28,8 +32,8 @@ public class IdentifierBag extends IdentifierCollection {
/**
* annotation binding
*/
public IdentifierBag(SemanticsResolver semanticsResolver, PersistentClass owner, MetadataBuildingContext buildingContext) {
super( semanticsResolver, owner, buildingContext );
public IdentifierBag(Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver, PersistentClass owner, MetadataBuildingContext buildingContext) {
super( customTypeBeanResolver, owner, buildingContext );
}
public CollectionType getDefaultCollectionType() {

View File

@ -6,10 +6,13 @@
*/
package org.hibernate.mapping;
import java.util.function.Supplier;
import org.hibernate.MappingException;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.engine.spi.Mapping;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.usertype.UserCollectionType;
/**
* A collection with a synthetic "identifier" column
@ -24,8 +27,8 @@ public abstract class IdentifierCollection extends Collection {
super( buildingContext, owner );
}
public IdentifierCollection(SemanticsResolver semanticsResolver, PersistentClass owner, MetadataBuildingContext buildingContext) {
super( semanticsResolver, owner, buildingContext );
public IdentifierCollection(Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver, PersistentClass owner, MetadataBuildingContext buildingContext) {
super( customTypeBeanResolver, owner, buildingContext );
}
public KeyValue getIdentifier() {

View File

@ -7,13 +7,13 @@
package org.hibernate.mapping;
import java.util.Iterator;
import java.util.function.Function;
import java.util.function.Supplier;
import org.hibernate.MappingException;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.engine.spi.Mapping;
import org.hibernate.type.CollectionType;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.usertype.UserCollectionType;
/**
* Indexed collections include Lists, Maps, arrays and
@ -30,8 +30,8 @@ public abstract class IndexedCollection extends Collection {
super( buildingContext, owner );
}
public IndexedCollection(SemanticsResolver semanticsResolver, PersistentClass owner, MetadataBuildingContext buildingContext) {
super( semanticsResolver, owner, buildingContext );
public IndexedCollection(Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver, PersistentClass owner, MetadataBuildingContext buildingContext) {
super( customTypeBeanResolver, owner, buildingContext );
}
public Value getIndex() {

View File

@ -6,14 +6,16 @@
*/
package org.hibernate.mapping;
import java.util.function.Function;
import java.util.function.Supplier;
import org.hibernate.MappingException;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.collection.internal.StandardListSemantics;
import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.type.CollectionType;
import org.hibernate.type.ListType;
import org.hibernate.usertype.UserCollectionType;
/**
* A list mapping has a primary key consisting of the key columns + index column.
@ -34,8 +36,8 @@ public class List extends IndexedCollection {
/**
* annotation binding
*/
public List(SemanticsResolver semanticsResolver, PersistentClass owner, MetadataBuildingContext buildingContext) {
super( semanticsResolver, owner, buildingContext );
public List(Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver, PersistentClass owner, MetadataBuildingContext buildingContext) {
super( customTypeBeanResolver, owner, buildingContext );
}
public boolean isList() {

View File

@ -6,16 +6,20 @@
*/
package org.hibernate.mapping;
import java.util.function.Supplier;
import org.hibernate.MappingException;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.collection.internal.StandardMapSemantics;
import org.hibernate.collection.internal.StandardOrderedMapSemantics;
import org.hibernate.collection.internal.StandardSortedMapSemantics;
import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.type.CollectionType;
import org.hibernate.type.MapType;
import org.hibernate.type.OrderedMapType;
import org.hibernate.type.SortedMapType;
import org.hibernate.usertype.UserCollectionType;
/**
* A map has a primary key consisting of
@ -29,8 +33,8 @@ public class Map extends IndexedCollection {
super( buildingContext, owner );
}
public Map(SemanticsResolver semanticsResolver, PersistentClass owner, MetadataBuildingContext buildingContext) {
super( semanticsResolver, owner, buildingContext );
public Map(Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver, PersistentClass owner, MetadataBuildingContext buildingContext) {
super( customTypeBeanResolver, owner, buildingContext );
}
public boolean isMap() {

View File

@ -6,18 +6,17 @@
*/
package org.hibernate.mapping;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.function.Supplier;
import org.hibernate.Internal;
import org.hibernate.MappingException;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.metamodel.mapping.MappingModelCreationLogger;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.type.AnyType;
import org.hibernate.type.CollectionType;
import org.hibernate.type.CustomCollectionType;
@ -47,20 +46,23 @@ public final class MappingHelper {
String propertyRef,
MetadataImplementor metadata) {
final ClassLoaderService cls = metadata.getMetadataBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class );
final Class<? extends UserCollectionType> typeImpl = cls.classForName( typeName );
try {
final Class<? extends UserCollectionType> typeClass = cls.classForName( typeName );
final ManagedBeanRegistry beanRegistry = metadata
.getMetadataBuildingOptions()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class );
CustomCollectionType result = new CustomCollectionType( typeClass, role, propertyRef, metadata.getTypeConfiguration() );
if ( typeParameters != null ) {
injectParameters( result.getUserType(), typeParameters );
final ManagedBean<? extends UserCollectionType> customTypeBean;
if ( typeParameters == null ) {
customTypeBean = beanRegistry.getBean( typeImpl );
}
else {
customTypeBean = beanRegistry.getBean( role, typeImpl );
injectParameters( customTypeBean.getBeanInstance(), typeParameters );
}
return result;
}
catch (ClassLoadingException e) {
throw new MappingException( "user collection type class not found: " + typeName, e );
}
return new CustomCollectionType( customTypeBean, role, propertyRef, metadata.getTypeConfiguration() );
}
public static void injectParameters(Object type, Properties parameters) {

View File

@ -6,9 +6,13 @@
*/
package org.hibernate.mapping;
import java.util.function.Supplier;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.collection.internal.StandardArraySemantics;
import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.usertype.UserCollectionType;
/**
* A primitive array has a primary key consisting of the key columns + index column.
@ -18,8 +22,8 @@ public class PrimitiveArray extends Array {
super( buildingContext, owner );
}
public PrimitiveArray(SemanticsResolver semanticsResolver, PersistentClass owner, MetadataBuildingContext buildingContext) {
super( semanticsResolver, owner, buildingContext );
public PrimitiveArray(Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver, PersistentClass owner, MetadataBuildingContext buildingContext) {
super( customTypeBeanResolver, owner, buildingContext );
}
public boolean isPrimitiveArray() {

View File

@ -7,6 +7,7 @@
package org.hibernate.mapping;
import java.util.Iterator;
import java.util.function.Supplier;
import org.hibernate.MappingException;
import org.hibernate.boot.spi.MetadataBuildingContext;
@ -15,10 +16,12 @@ import org.hibernate.collection.internal.StandardSetSemantics;
import org.hibernate.collection.internal.StandardSortedSetSemantics;
import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.engine.spi.Mapping;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.type.CollectionType;
import org.hibernate.type.OrderedSetType;
import org.hibernate.type.SetType;
import org.hibernate.type.SortedSetType;
import org.hibernate.usertype.UserCollectionType;
/**
* A set with no nullable element columns. It will have a primary key
@ -36,8 +39,8 @@ public class Set extends Collection {
/**
* Used by annotation binding
*/
public Set(SemanticsResolver semanticsResolver, PersistentClass persistentClass, MetadataBuildingContext buildingContext) {
super( semanticsResolver, persistentClass, buildingContext );
public Set(Supplier<ManagedBean<? extends UserCollectionType>> customTypeBeanResolver, PersistentClass persistentClass, MetadataBuildingContext buildingContext) {
super( customTypeBeanResolver, persistentClass, buildingContext );
}
public void validate(Mapping mapping) throws MappingException {

View File

@ -56,6 +56,9 @@ public enum CollectionClassification {
* A sorted {@link #SET} using either natural sorting of the elements or a
* specified {@link java.util.Comparator}. Represented
* as {@link java.util.SortedSet} or {@link java.util.Set}
*
* @see org.hibernate.annotations.SortNatural
* @see org.hibernate.annotations.SortComparator
*/
SORTED_SET( PluralAttribute.CollectionType.SET ),
@ -64,6 +67,9 @@ public enum CollectionClassification {
* as the collection is loaded. Does not maintain ordering
* while in memory if the contents change. Represented
* as {@link java.util.Set}.
*
* @see jakarta.persistence.OrderBy
* @see org.hibernate.annotations.OrderBy
*/
ORDERED_SET( PluralAttribute.CollectionType.SET ),
@ -76,6 +82,9 @@ public enum CollectionClassification {
* A sorted {@link #MAP} using either natural sorting of the keys or a
* specified {@link java.util.Comparator}. Represented
* as {@link java.util.SortedMap} or {@link java.util.Map}
*
* @see org.hibernate.annotations.SortNatural
* @see org.hibernate.annotations.SortComparator
*/
SORTED_MAP( PluralAttribute.CollectionType.MAP ),
@ -84,6 +93,9 @@ public enum CollectionClassification {
* as the collection is loaded. Does not maintain ordering
* while in memory if the contents change. Represented
* as {@link java.util.Map}.
*
* @see jakarta.persistence.OrderBy
* @see org.hibernate.annotations.OrderBy
*/
ORDERED_MAP( PluralAttribute.CollectionType.MAP );

View File

@ -7,7 +7,6 @@
package org.hibernate.query.internal;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.function.Consumer;
import org.hibernate.boot.model.convert.internal.ConverterHelper;
@ -118,7 +117,7 @@ public class ResultMementoBasicStandard implements ResultMementoBasic {
}
else if ( UserType.class.isAssignableFrom( registeredJtd.getJavaTypeClass() ) ) {
final ManagedBean<UserType<?>> userTypeBean = (ManagedBean) beanRegistry.getBean( registeredJtd.getJavaTypeClass() );
// todo (6.0) : is this the best approach? or should we keep a Class<? extends UserType> -> CustomType mapping somewhere?
// todo (6.0) : is this the best approach? or should we keep a Class<? extends UserType> -> @Type mapping somewhere?
explicitType = new CustomType<>( (UserType<Object>) userTypeBean.getBeanInstance(), typeConfiguration );
explicitJavaTypeDescriptor = explicitType.getJavaTypeDescriptor();
}
@ -135,8 +134,8 @@ public class ResultMementoBasicStandard implements ResultMementoBasic {
private BasicJavaType<?> determineDomainJavaType(
ParameterizedType parameterizedType,
JavaTypeRegistry jtdRegistry) {
final Type[] typeParameters = parameterizedType.getActualTypeArguments();
final Type domainTypeType = typeParameters[ 0 ];
final java.lang.reflect.Type[] typeParameters = parameterizedType.getActualTypeArguments();
final java.lang.reflect.Type domainTypeType = typeParameters[ 0 ];
final Class<?> domainClass = (Class<?>) domainTypeType;
return (BasicJavaType<?>) jtdRegistry.getDescriptor( domainClass );
@ -145,7 +144,7 @@ public class ResultMementoBasicStandard implements ResultMementoBasic {
private BasicValuedMapping resolveUnderlyingMapping(
ParameterizedType parameterizedType,
TypeConfiguration typeConfiguration) {
final Type[] typeParameters = parameterizedType.getActualTypeArguments();
final java.lang.reflect.Type[] typeParameters = parameterizedType.getActualTypeArguments();
return typeConfiguration.standardBasicTypeForJavaType( (Class) typeParameters[ 1 ] );
}

View File

@ -20,6 +20,7 @@ import org.hibernate.collection.spi.PersistentArrayHolder;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.type.spi.TypeConfiguration;
@ -43,6 +44,11 @@ public class ArrayType extends CollectionType {
return arrayClass;
}
@Override
public CollectionClassification getCollectionClassification() {
return CollectionClassification.ARRAY;
}
@Override
public PersistentCollection instantiate(SharedSessionContractImplementor session, CollectionPersister persister, Object key)
throws HibernateException {

View File

@ -13,6 +13,7 @@ import org.hibernate.HibernateException;
import org.hibernate.collection.spi.PersistentBag;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.type.spi.TypeConfiguration;
@ -23,9 +24,8 @@ public class BagType extends CollectionType {
}
@Override
public PersistentCollection instantiate(SharedSessionContractImplementor session, CollectionPersister persister, Object key)
throws HibernateException {
return new PersistentBag( session );
public CollectionClassification getCollectionClassification() {
return CollectionClassification.BAG;
}
@Override
@ -33,6 +33,12 @@ public class BagType extends CollectionType {
return Collection.class;
}
@Override
public PersistentCollection instantiate(SharedSessionContractImplementor session, CollectionPersister persister, Object key)
throws HibernateException {
return new PersistentBag( session );
}
@Override
public PersistentCollection wrap(SharedSessionContractImplementor session, Object collection) {
return new PersistentBag( session, (Collection) collection );

View File

@ -37,6 +37,7 @@ import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.MarkerObject;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.EntityPersister;
@ -74,6 +75,8 @@ public abstract class CollectionType extends AbstractType implements Association
this.foreignKeyPropertyName = foreignKeyPropertyName;
}
public abstract CollectionClassification getCollectionClassification();
public String getRole() {
return role;
}

View File

@ -10,11 +10,12 @@ import java.util.Iterator;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.type.spi.TypeConfiguration;
import org.hibernate.usertype.LoggableUserType;
import org.hibernate.usertype.UserCollectionType;
@ -32,30 +33,24 @@ public class CustomCollectionType extends CollectionType {
private final boolean customLogging;
public CustomCollectionType(
Class<? extends UserCollectionType> userTypeClass,
ManagedBean<? extends UserCollectionType> userTypeBean,
String role,
String foreignKeyPropertyName,
TypeConfiguration typeConfiguration) {
super( typeConfiguration, role, foreignKeyPropertyName );
if ( !UserCollectionType.class.isAssignableFrom( userTypeClass ) ) {
throw new MappingException( "Custom type does not implement UserCollectionType: " + userTypeClass.getName() );
}
userType = createUserCollectionType( userTypeClass );
userType = userTypeBean.getBeanInstance();
customLogging = userType instanceof LoggableUserType;
}
private static UserCollectionType createUserCollectionType(Class<? extends UserCollectionType> userTypeClass) {
try {
return userTypeClass.newInstance();
}
catch (InstantiationException ie) {
throw new MappingException( "Cannot instantiate custom type: " + userTypeClass.getName() );
}
catch (IllegalAccessException iae) {
throw new MappingException( "IllegalAccessException trying to instantiate custom type: " + userTypeClass.getName() );
@Override
public Class getReturnedClass() {
return userType.instantiate( -1 ).getClass();
}
@Override
public CollectionClassification getCollectionClassification() {
return userType.getClassification();
}
@Override
@ -69,11 +64,6 @@ public class CustomCollectionType extends CollectionType {
return userType.wrap( session, collection );
}
@Override
public Class getReturnedClass() {
return userType.instantiate( -1 ).getClass();
}
@Override
public Object instantiate(int anticipatedType) {
return userType.instantiate( anticipatedType );

View File

@ -12,6 +12,7 @@ import org.hibernate.HibernateException;
import org.hibernate.collection.spi.PersistentIdentifierBag;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.type.spi.TypeConfiguration;
@ -21,6 +22,11 @@ public class IdentifierBagType extends CollectionType {
super( typeConfiguration, role, propertyRef );
}
@Override
public CollectionClassification getCollectionClassification() {
return CollectionClassification.ID_BAG;
}
@Override
public PersistentCollection instantiate(
SharedSessionContractImplementor session,

View File

@ -12,15 +12,23 @@ import java.util.List;
import org.hibernate.collection.spi.PersistentList;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.type.spi.TypeConfiguration;
import static org.hibernate.metamodel.CollectionClassification.LIST;
public class ListType extends CollectionType {
public ListType(TypeConfiguration typeConfiguration, String role, String propertyRef) {
super( typeConfiguration, role, propertyRef );
}
@Override
public CollectionClassification getCollectionClassification() {
return LIST;
}
@Override
public PersistentCollection instantiate(SharedSessionContractImplementor session, CollectionPersister persister, Object key) {
return new PersistentList( session );

View File

@ -14,6 +14,7 @@ import org.hibernate.HibernateException;
import org.hibernate.collection.spi.PersistentMap;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.type.spi.TypeConfiguration;
@ -24,6 +25,11 @@ public class MapType extends CollectionType {
super( typeConfiguration, role, propertyRef );
}
@Override
public CollectionClassification getCollectionClassification() {
return CollectionClassification.MAP;
}
@Override
public PersistentCollection instantiate(
SharedSessionContractImplementor session,

View File

@ -7,6 +7,7 @@
package org.hibernate.type;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.type.spi.TypeConfiguration;
/**
@ -18,6 +19,11 @@ public class OrderedMapType extends MapType {
super( typeConfiguration, role, propertyRef );
}
@Override
public CollectionClassification getCollectionClassification() {
return CollectionClassification.ORDERED_MAP;
}
@Override
public Object instantiate(int anticipatedSize) {
return anticipatedSize > 0

View File

@ -7,6 +7,7 @@
package org.hibernate.type;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.type.spi.TypeConfiguration;
/**
@ -18,6 +19,11 @@ public class OrderedSetType extends SetType {
super( typeConfiguration, role, propertyRef );
}
@Override
public CollectionClassification getCollectionClassification() {
return CollectionClassification.ORDERED_SET;
}
@Override
public Object instantiate(int anticipatedSize) {
return anticipatedSize > 0

View File

@ -10,6 +10,7 @@ import org.hibernate.collection.spi.PersistentSet;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.type.spi.TypeConfiguration;
@ -20,8 +21,8 @@ public class SetType extends CollectionType {
}
@Override
public PersistentCollection instantiate(SharedSessionContractImplementor session, CollectionPersister persister, Object key) {
return new PersistentSet( session );
public CollectionClassification getCollectionClassification() {
return CollectionClassification.SET;
}
@Override
@ -29,6 +30,11 @@ public class SetType extends CollectionType {
return java.util.Set.class;
}
@Override
public PersistentCollection instantiate(SharedSessionContractImplementor session, CollectionPersister persister, Object key) {
return new PersistentSet( session );
}
@Override
public PersistentCollection wrap(SharedSessionContractImplementor session, Object collection) {
return new PersistentSet( session, (java.util.Set) collection );

View File

@ -12,6 +12,7 @@ import java.util.TreeMap;
import org.hibernate.collection.spi.PersistentSortedMap;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.type.spi.TypeConfiguration;
@ -26,14 +27,19 @@ public class SortedMapType extends MapType {
}
@Override
public PersistentCollection instantiate(SharedSessionContractImplementor session, CollectionPersister persister, Object key) {
return new PersistentSortedMap( session, comparator );
public CollectionClassification getCollectionClassification() {
return CollectionClassification.SORTED_MAP;
}
public Class getReturnedClass() {
return java.util.SortedMap.class;
}
@Override
public PersistentCollection instantiate(SharedSessionContractImplementor session, CollectionPersister persister, Object key) {
return new PersistentSortedMap( session, comparator );
}
@SuppressWarnings( {"unchecked"})
public Object instantiate(int anticipatedSize) {
return new TreeMap(comparator);

View File

@ -12,6 +12,7 @@ import java.util.TreeSet;
import org.hibernate.collection.spi.PersistentSortedSet;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.type.spi.TypeConfiguration;
@ -25,14 +26,19 @@ public class SortedSetType extends SetType {
}
@Override
public PersistentCollection instantiate(SharedSessionContractImplementor session, CollectionPersister persister, Object key) {
return new PersistentSortedSet( session, comparator );
public CollectionClassification getCollectionClassification() {
return CollectionClassification.SORTED_SET;
}
public Class getReturnedClass() {
return java.util.SortedSet.class;
}
@Override
public PersistentCollection instantiate(SharedSessionContractImplementor session, CollectionPersister persister, Object key) {
return new PersistentSortedSet( session, comparator );
}
@SuppressWarnings( {"unchecked"})
public Object instantiate(int anticipatedSize) {
return new TreeSet(comparator);

View File

@ -12,15 +12,27 @@ import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.persister.collection.CollectionPersister;
/**
* A custom type for mapping user-written classes that implement {@code PersistentCollection}
*
* @author Gavin King
* @see PersistentCollection
*
* @author Gavin King
* @author Steve Ebersole
*/
public interface UserCollectionType {
/**
* The classification mapped by this custom type
*/
CollectionClassification getClassification();
/**
* The Java type that this type maps.
*/
Class<?> getCollectionClass();
/**
* Instantiate an uninitialized instance of the collection wrapper

View File

@ -10,6 +10,7 @@ import java.util.Properties;
import java.util.function.BiConsumer;
import org.hibernate.MappingException;
import org.hibernate.annotations.Type;
import org.hibernate.type.BasicType;
import org.hibernate.type.spi.TypeConfiguration;
import org.hibernate.type.spi.TypeConfigurationAware;
@ -18,7 +19,7 @@ import org.hibernate.type.spi.TypeConfigurationAware;
* Convenience UserType implementation to mimic the legacy `@Type` annotation
* which based on the {@code hbm.xml} mapping's String-based type support
*
* @see org.hibernate.annotations.CustomType
* @see Type
*/
public class UserTypeLegacyBridge extends BaseUserTypeSupport<Object> implements ParameterizedType, TypeConfigurationAware {
public static final String TYPE_NAME_PARAM_KEY = "hbm-type-name";

View File

@ -9,7 +9,7 @@ package org.hibernate.orm.test.annotations.basic;
import java.sql.Types;
import java.util.Set;
import org.hibernate.annotations.CustomType;
import org.hibernate.annotations.Type;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
@ -49,7 +49,7 @@ public class CollectionAsBasicTest {
public Integer id;
public String name;
@Basic
@CustomType( DelimitedStringsJavaTypeDescriptor.class )
@Type( DelimitedStringsJavaTypeDescriptor.class )
Set<String> tags;
}

View File

@ -6,7 +6,7 @@
*/
package org.hibernate.orm.test.annotations.generics;
import org.hibernate.annotations.CustomType;
import org.hibernate.annotations.Type;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
@ -22,7 +22,7 @@ public class Gene<T, STE extends Enum> {
private Integer id;
private STE state;
@CustomType( StateType.class )
@Type( StateType.class )
public STE getState() {
return state;
}

View File

@ -23,7 +23,7 @@
*/
package org.hibernate.orm.test.annotations.type.dynamicparameterized;
import org.hibernate.annotations.CustomType;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.Parameter;
import jakarta.persistence.Access;
@ -41,26 +41,26 @@ import jakarta.persistence.Table;
public class Entity1 extends AbstractEntity {
@Column(name = "PROP1")
@CustomType( MyStringType.class )
@Type( MyStringType.class )
String entity1_Prop1;
@Column(name = "PROP2")
@CustomType( MyStringType.class )
@Type( MyStringType.class )
String entity1_Prop2;
@Column(name = "PROP3")
@CustomType( value = MyStringType.class, parameters = @Parameter(name = "suffix", value = "foo"))
@Type( value = MyStringType.class, parameters = @Parameter(name = "suffix", value = "foo"))
String entity1_Prop3;
@Column(name = "PROP4")
@CustomType( value = MyStringType.class, parameters = @Parameter(name = "suffix", value = "bar"))
@Type( value = MyStringType.class, parameters = @Parameter(name = "suffix", value = "bar"))
String entity1_Prop4;
@Column(name = "PROP5")
@CustomType( MyStringType.class )
@Type( MyStringType.class )
String entity1_Prop5;
@Column(name = "PROP6")
@CustomType( MyStringType.class )
@Type( MyStringType.class )
String entity1_Prop6;
}

View File

@ -23,7 +23,7 @@
*/
package org.hibernate.orm.test.annotations.type.dynamicparameterized;
import org.hibernate.annotations.CustomType;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.Parameter;
import jakarta.persistence.Access;
@ -41,26 +41,26 @@ import jakarta.persistence.Table;
public class Entity2 extends AbstractEntity {
@Column(name = "PROP1")
@CustomType( MyStringType.class )
@Type( MyStringType.class )
String entity2_Prop1;
@Column(name = "PROP2")
@CustomType( MyStringType.class )
@Type( MyStringType.class )
String entity2_Prop2;
@Column(name = "PROP3")
@CustomType( MyStringType.class )
@Type( MyStringType.class )
String entity2_Prop3;
@Column(name = "PROP4")
@CustomType( MyStringType.class )
@Type( MyStringType.class )
String entity2_Prop4;
@Column(name = "PROP5")
@CustomType( value = MyStringType.class, parameters = @Parameter(name = "suffix", value = "blah"))
@Type( value = MyStringType.class, parameters = @Parameter(name = "suffix", value = "blah"))
String entity2_Prop5;
@Column(name = "PROP6")
@CustomType( value = MyStringType.class, parameters = @Parameter(name = "suffix", value = "yeah"))
@Type( value = MyStringType.class, parameters = @Parameter(name = "suffix", value = "yeah"))
String entity2_Prop6;
}

View File

@ -7,14 +7,12 @@
package org.hibernate.orm.test.bytecode.enhancement.lazy.cache;
import java.nio.charset.Charset;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.CustomType;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.annotations.Type;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.usertype.UserTypeLegacyBridge;
@ -97,7 +95,7 @@ public class LazyInCacheTest extends BaseCoreFunctionalTestCase {
List<Tag> tags = new ArrayList<>();
@Basic( fetch = FetchType.LAZY )
@CustomType( BinaryCustomType.class )
@Type( BinaryCustomType.class )
// @JdbcTypeCode(Types.LONGVARBINARY)
byte[] data;
}

View File

@ -6,10 +6,6 @@
*/
package org.hibernate.orm.test.cfg.annotations;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
@ -22,15 +18,20 @@ import org.hibernate.cfg.AnnotatedJoinColumn;
import org.hibernate.cfg.InheritanceState;
import org.hibernate.cfg.PropertyHolder;
import org.hibernate.cfg.annotations.CollectionBinder;
import org.hibernate.collection.internal.StandardBagSemantics;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Table;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.junit.Test;
import org.mockito.Mockito;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* Test for HHH-10106
*
@ -56,7 +57,7 @@ public class CollectionBinderTest extends BaseUnitTestCase {
String expectMessage = "Association [abc] for entity [CollectionBinderTest] references unmapped class [List]";
try {
new CollectionBinder( (t) -> StandardBagSemantics.INSTANCE, false, buildingContext ) {
new CollectionBinder( null, false, buildingContext ) {
{
final PropertyHolder propertyHolder = Mockito.mock(PropertyHolder.class);

View File

@ -14,7 +14,7 @@ import java.sql.Types;
import java.util.Comparator;
import org.hibernate.HibernateException;
import org.hibernate.annotations.CustomType;
import org.hibernate.annotations.Type;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.usertype.UserType;
@ -71,7 +71,7 @@ public class UserTypeComparableIdTest {
public static class SomeEntity {
@Id
@CustomType( CustomIdType.class )
@Type( CustomIdType.class )
@Column(name = "id")
private CustomId customId;

View File

@ -18,7 +18,7 @@ import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.hibernate.HibernateException;
import org.hibernate.annotations.CustomType;
import org.hibernate.annotations.Type;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.usertype.UserType;
@ -63,7 +63,7 @@ public class UserTypeNonComparableIdTest {
public static class SomeEntity {
@Id
@CustomType( CustomIdType.class )
@Type( CustomIdType.class )
@Column(name = "id")
private CustomId customId;

View File

@ -17,7 +17,7 @@ import java.util.Objects;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.annotations.CustomType;
import org.hibernate.annotations.Type;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
@ -122,7 +122,7 @@ public class QueryParametersValidationTest extends BaseEntityManagerFunctionalTe
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@CustomType( QueryParametersValidationTest.BooleanUserType.class )
@Type( QueryParametersValidationTest.BooleanUserType.class )
private boolean active;
}

View File

@ -15,6 +15,7 @@ import java.util.Arrays;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.annotations.Type;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.query.TypedParameterValue;
@ -114,7 +115,7 @@ public class TypedValueParametersTest {
@Id
private int id;
@org.hibernate.annotations.CustomType( TagUserType.class )
@Type( TagUserType.class )
@Column(name = "tags")
private List<String> tags = new ArrayList<>();

View File

@ -9,11 +9,9 @@ package org.hibernate.orm.test.mapping.collections;
import java.util.Collection;
import java.util.List;
import org.hibernate.annotations.CollectionClassificationType;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.mapping.Bag;
import org.hibernate.mapping.Property;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.DomainModelScope;
@ -26,6 +24,7 @@ import jakarta.persistence.Basic;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.OrderColumn;
import jakarta.persistence.Table;
import static org.assertj.core.api.Assertions.assertThat;
@ -82,11 +81,11 @@ public class ImplicitListAsBagSemanticsTests {
private Collection<String> implicitBag;
@ElementCollection
@CollectionClassificationType( CollectionClassification.BAG )
@org.hibernate.annotations.Bag
private List<String> explicitBag;
@ElementCollection
@CollectionClassificationType( CollectionClassification.LIST )
@OrderColumn( name = "explicit_list_position" )
private List<String> explicitList;
private AnEntity() {

View File

@ -6,12 +6,9 @@
*/
package org.hibernate.orm.test.mapping.collections;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.List;
import org.hibernate.annotations.CollectionClassificationType;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.mapping.Bag;
import org.hibernate.mapping.Property;
import org.hibernate.metamodel.CollectionClassification;
@ -19,7 +16,6 @@ import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.DomainModelScope;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.Setting;
import org.hibernate.testing.orm.junit.SettingProvider;
import org.junit.jupiter.api.Test;
@ -27,6 +23,7 @@ import jakarta.persistence.Basic;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.OrderColumn;
import jakarta.persistence.Table;
import static org.assertj.core.api.Assertions.assertThat;
@ -75,11 +72,11 @@ public class ImplicitListAsListSemanticsTests {
private Collection<String> implicitBag;
@ElementCollection
@CollectionClassificationType( CollectionClassification.BAG )
@org.hibernate.annotations.Bag
private List<String> explicitBag;
@ElementCollection
@CollectionClassificationType( CollectionClassification.LIST )
@OrderColumn( name = "explicit_list_position" )
private List<String> explicitList;
private AnEntity() {

View File

@ -9,11 +9,9 @@ package org.hibernate.orm.test.mapping.collections;
import java.util.Collection;
import java.util.List;
import org.hibernate.annotations.CollectionClassificationType;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.mapping.Bag;
import org.hibernate.mapping.Property;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.DomainModelScope;
@ -23,6 +21,7 @@ import jakarta.persistence.Basic;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.OrderColumn;
import jakarta.persistence.Table;
import static org.assertj.core.api.Assertions.assertThat;
@ -69,11 +68,11 @@ public class ImplicitListDefaultSemanticsTests {
private Collection<String> implicitBag;
@ElementCollection
@CollectionClassificationType( CollectionClassification.BAG )
@org.hibernate.annotations.Bag
private List<String> explicitBag;
@ElementCollection
@CollectionClassificationType( CollectionClassification.LIST )
@OrderColumn( name = "explicit_list_position" )
private List<String> explicitList;
private AnEntity() {

View File

@ -20,7 +20,8 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Steve Ebersole
*/
@DomainModel( annotatedClasses = {
EntityWithBagAsCollection.class
EntityWithBagAsCollection.class,
EntityWithBagAsList.class
} )
public class BagTests {
@Test
@ -32,4 +33,14 @@ public class BagTests {
assertThat( namesMapping.getCollectionSemantics().getCollectionClassification() ).isEqualTo( CollectionClassification.BAG );
} );
}
@Test
public void verifyListMarkedAsBag(DomainModelScope scope) {
scope.withHierarchy( EntityWithBagAsList.class, (entityDescriptor) -> {
final Property names = entityDescriptor.getProperty( "names" );
final Collection namesMapping = (Collection) names.getValue();
assertThat( namesMapping.getCollectionSemantics().getCollectionClassification() ).isEqualTo( CollectionClassification.BAG );
} );
}
}

View File

@ -6,11 +6,9 @@
*/
package org.hibernate.orm.test.mapping.collections.classification.bag;
import java.util.Collection;
import java.util.List;
import org.hibernate.annotations.CollectionClassificationType;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.annotations.Bag;
import org.hibernate.orm.test.mapping.collections.classification.Name;
import jakarta.persistence.Basic;
@ -18,8 +16,6 @@ import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import static org.hibernate.metamodel.CollectionClassification.BAG;
/**
* @author Steve Ebersole
*/
@ -36,7 +32,7 @@ public class EntityWithBagAsList {
//tag::collections-bag-list-ex[]
@ElementCollection
@CollectionClassificationType( BAG )
@Bag
private List<Name> names;
//end::collections-bag-list-ex[]

View File

@ -1,63 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.mapping.collections.classification.explicit;
import java.util.Collection;
import org.hibernate.annotations.CollectionClassificationType;
import org.hibernate.orm.test.mapping.collections.classification.Name;
import jakarta.persistence.Basic;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import static org.hibernate.metamodel.CollectionClassification.SET;
/**
* @author Steve Ebersole
*/
//tag::collections-bag-set-ex[]
@Entity
public class EntityWithExplicitSetClassification {
// ...
//end::collections-bag-set-ex[]
@Id
private Integer id;
@Basic
private String name;
//tag::collections-bag-set-ex[]
@ElementCollection
@CollectionClassificationType(SET)
private Collection<Name> names;
//end::collections-bag-set-ex[]
private EntityWithExplicitSetClassification() {
// for Hibernate use
}
public EntityWithExplicitSetClassification(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//tag::collections-bag-set-ex[]
}
//end::collections-bag-set-ex[]

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.mapping.type.collection.custom.basic;
package org.hibernate.orm.test.mapping.collections.custom.basic;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.mapping.type.collection.custom.basic;
package org.hibernate.orm.test.mapping.collections.custom.basic;
import java.util.List;

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.mapping.type.collection.custom.basic;
package org.hibernate.orm.test.mapping.collections.custom.basic;
import java.util.ArrayList;

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.mapping.type.collection.custom.basic;
package org.hibernate.orm.test.mapping.collections.custom.basic;
import java.util.Iterator;
import java.util.Map;
@ -12,6 +12,7 @@ import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.usertype.UserCollectionType;
@ -19,6 +20,16 @@ public class MyListType implements UserCollectionType {
static int lastInstantiationRequest = -2;
@Override
public CollectionClassification getClassification() {
return CollectionClassification.LIST;
}
@Override
public Class<?> getCollectionClass() {
return IMyList.class;
}
@Override
public PersistentCollection instantiate(SharedSessionContractImplementor session, CollectionPersister persister) throws HibernateException {
return new PersistentMyList( session );

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.mapping.type.collection.custom.basic;
package org.hibernate.orm.test.mapping.collections.custom.basic;
import org.hibernate.collection.spi.PersistentList;
import org.hibernate.engine.spi.SharedSessionContractImplementor;

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.mapping.type.collection.custom.basic;
package org.hibernate.orm.test.mapping.collections.custom.basic;
import java.util.List;

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.mapping.type.collection.custom.basic;
package org.hibernate.orm.test.mapping.collections.custom.basic;
/**
* @author Steve Ebersole

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.mapping.type.collection.custom.basic;
package org.hibernate.orm.test.mapping.collections.custom.basic;
/**
* @author Steve Ebersole
@ -17,6 +17,6 @@ public class UserCollectionTypeHbmVariantTest extends UserCollectionTypeTest {
@Override
public String[] getMappings() {
return new String[] { "/org/hibernate/orm/test/mapping/type/collection/custom/basic/UserPermissions.hbm.xml" };
return new String[] { "/org/hibernate/orm/test/mapping/collections/custom/basic/UserPermissions.hbm.xml" };
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.mapping.type.collection.custom.basic;
package org.hibernate.orm.test.mapping.collections.custom.basic;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;

View File

@ -2,8 +2,8 @@
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later
~ See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
-->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
@ -13,14 +13,14 @@
This mapping is a basic example of how to write a UserCollectionType.
-->
<hibernate-mapping package="org.hibernate.orm.test.mapping.type.collection.custom.basic" default-access="field">
<hibernate-mapping package="org.hibernate.orm.test.mapping.collections.custom.basic" default-access="field">
<import class="Permission"/>
<class name="User" table="UC_BSC_USER">
<id name="id"/>
<property name="userName"/>
<list name="emailAddresses" fetch="join" cascade="all, delete-orphan" collection-type="org.hibernate.orm.test.mapping.type.collection.custom.basic.MyListType">
<list name="emailAddresses" fetch="join" cascade="all, delete-orphan" collection-type="MyListType">
<key column="userName"/>
<list-index column="displayOrder" base="1"/>
<one-to-many class="Email"/>

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.mapping.type.collection.custom.declaredtype.explicitsemantics;
package org.hibernate.orm.test.mapping.collections.custom.declaredtype;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
@ -15,9 +15,8 @@ import jakarta.persistence.Id;
* @author Gavin King
* @author Steve Ebersole
*/
@Entity(name = "Email")
@Entity
public class Email {
private Long id;
private String address;
@ -29,7 +28,7 @@ public class Email {
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@GeneratedValue( strategy = GenerationType.AUTO )
public Long getId() {
return id;
}
@ -48,11 +47,9 @@ public class Email {
@Override
public boolean equals(Object that) {
if ( !( that instanceof Email ) ) {
return false;
}
if ( !(that instanceof Email ) ) return false;
Email p = (Email) that;
return this.address.equals( p.address );
return this.address.equals(p.address);
}
@Override

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.mapping.type.collection.custom.declaredtype;
package org.hibernate.orm.test.mapping.collections.custom.declaredtype;
import java.util.ArrayList;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.mapping.type.collection.custom.declaredtype;
package org.hibernate.orm.test.mapping.collections.custom.declaredtype;
import java.util.Iterator;
import java.util.Map;
@ -12,6 +12,7 @@ import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.usertype.UserCollectionType;
@ -20,6 +21,16 @@ import org.hibernate.usertype.UserCollectionType;
*/
public class HeadListType implements UserCollectionType {
@Override
public CollectionClassification getClassification() {
return CollectionClassification.LIST;
}
@Override
public Class<?> getCollectionClass() {
return IHeadList.class;
}
@Override
public PersistentCollection instantiate(SharedSessionContractImplementor session, CollectionPersister persister) throws HibernateException {
return new PersistentHeadList( session );

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.mapping.type.collection.custom.declaredtype;
package org.hibernate.orm.test.mapping.collections.custom.declaredtype;
import java.util.List;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.mapping.type.collection.custom.declaredtype;
package org.hibernate.orm.test.mapping.collections.custom.declaredtype;
import org.hibernate.collection.spi.PersistentList;
import org.hibernate.engine.spi.SharedSessionContractImplementor;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.mapping.type.collection.custom.declaredtype;
package org.hibernate.orm.test.mapping.collections.custom.declaredtype;
import org.hibernate.annotations.CollectionType;

View File

@ -1,3 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
@ -21,7 +28,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.orm.test.mapping.type.collection.custom.declaredtype;
package org.hibernate.orm.test.mapping.collections.custom.declaredtype;
/**
* @author Steve Ebersole

View File

@ -0,0 +1,17 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.mapping.collections.custom.declaredtype;
/**
* @author Steve Ebersole
*/
public class UserCollectionTypeHbmVariantTest extends UserCollectionTypeTest {
@Override
public String[] getMappings() {
return new String[] { "mapping/collections/custom/declaredtype/UserPermissions.hbm.xml" };
}
}

View File

@ -1,3 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
@ -21,7 +28,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.orm.test.mapping.type.collection.custom.declaredtype;
package org.hibernate.orm.test.mapping.collections.custom.declaredtype;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;

View File

@ -1,4 +1,10 @@
<?xml version="1.0"?>
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later
~ See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
-->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
@ -7,14 +13,14 @@
This mapping is a basic example of how to write a UserCollectionType.
-->
<hibernate-mapping package="org.hibernate.orm.test.mapping.type.collection.custom.declaredtype" default-access="field">
<hibernate-mapping package="org.hibernate.orm.test.mapping.collections.custom.declaredtype" default-access="field">
<import class="Permission"/>
<class name="org.hibernate.orm.test.mapping.type.collection.custom.declaredtype.User" table="UC_BSC_USER">
<class name="User" table="UC_BSC_USER">
<id name="id"/>
<property name="userName"/>
<list name="emailAddresses" fetch="join" cascade="all, delete-orphan" collection-type="org.hibernate.orm.test.mapping.type.collection.custom.declaredtype.HeadListType">
<list name="emailAddresses" fetch="join" cascade="all, delete-orphan" collection-type="HeadListType">
<key column="userName"/>
<list-index column="displayOrder" base="1"/>
<one-to-many class="Email"/>

View File

@ -1,3 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
@ -21,7 +28,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.orm.test.mapping.type.collection.custom.declaredtype;
package org.hibernate.orm.test.mapping.collections.custom.declaredtype;
import org.hibernate.annotations.CollectionType;

View File

@ -1,3 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
@ -21,7 +28,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.orm.test.mapping.type.collection.custom.declaredtype;
package org.hibernate.orm.test.mapping.collections.custom.declaredtype;
import org.hibernate.AnnotationException;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.mapping.type.collection.custom.parameterized;
package org.hibernate.orm.test.mapping.collections.custom.parameterized;
import java.util.List;

Some files were not shown because too many files have changed in this diff Show More