diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/EmbeddableInstantiator.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/EmbeddableInstantiator.java index 64299e1c5b..29bf2a1acc 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/EmbeddableInstantiator.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/EmbeddableInstantiator.java @@ -6,11 +6,8 @@ */ package org.hibernate.metamodel.spi; -import java.util.function.Supplier; - import org.hibernate.Incubating; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.metamodel.spi.Instantiator; /** * Contract for instantiating embeddable values diff --git a/hibernate-core/src/main/java/org/hibernate/type/CustomType.java b/hibernate-core/src/main/java/org/hibernate/type/CustomType.java index a05552cd7d..7f1d799860 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/CustomType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/CustomType.java @@ -43,12 +43,11 @@ import org.hibernate.usertype.UserVersionType; * handle the case of the wrapped type implementing them so we can pass them * along. * - * todo (6.0) : ^^ this introduces a problem in code that relies on `instance of` checks - * against any of these interfaces when the wrapped type does not - * * @author Gavin King * @author Steve Ebersole */ +// todo (6.0) : ^^ this introduces a problem in code that relies on `instanceof` checks +// against any of these interfaces when the wrapped type does not public class CustomType extends AbstractType implements ConvertedBasicType, ProcedureParameterNamedBinder, ProcedureParameterExtractionAware { diff --git a/hibernate-core/src/main/java/org/hibernate/usertype/CompositeUserType.java b/hibernate-core/src/main/java/org/hibernate/usertype/CompositeUserType.java index c78e11de50..9fe87cb161 100644 --- a/hibernate-core/src/main/java/org/hibernate/usertype/CompositeUserType.java +++ b/hibernate-core/src/main/java/org/hibernate/usertype/CompositeUserType.java @@ -15,39 +15,47 @@ import org.hibernate.metamodel.spi.EmbeddableInstantiator; import org.hibernate.metamodel.spi.ValueAccess; /** - * A {@link UserType} that may be dereferenced in a query. + * This interface should be implemented by user-defined custom types + * that have persistent attributes and can be thought of as something + * more like an {@linkplain jakarta.persistence.Embeddable embeddable} + * object. However, these persistent "attributes" need not necessarily + * correspond directly to Java fields or properties. *

- * This interface allows a custom type to define "properties". - * These need not necessarily correspond to physical JavaBeans - * style properties. + * A value type managed by a {@code CompositeUserType} may be used in + * almost every way that a regular embeddable type may be used. It may + * even contain many-to-one associations. *

- * A {@code CompositeUserType} may be used in almost every way - * that an {@linkplain jakarta.persistence.Embeddable embeddable} - * type may be used. It may even contain many-to-one associations. + * To "map" the attributes of a composite custom type, each + * {@code CompositeUserType} provides a {@linkplain #embeddable() + * regular embeddable class} with the same logical structure as the + * {@linkplain #returnedClass() value type managed by the custom + * type}. *

- * Implementors must be immutable and must declare a public - * default constructor. + * For example, if we implement a {@code CompositeUserType} for a + * {@code MonetaryAmount} class, we would also provide a + * {@code MonetaryAmountEmbeddable} class with a field for each + * logical persistent attribute of the custom type. Of course, + * {@code MonetaryAmountEmbeddable} is never instantiated at runtime, + * and is never referenced in any entity class. It is a source of + * metadata only. *

- * Unlike {@code UserType}, cacheability does not depend upon - * serializability. Instead, {@link #assemble(Serializable, Object)} - * and {@link #disassemble(Object)} provide conversion to and - * from a cacheable representation. + * Properties of this embeddable class are sorted alphabetically by + * name, and assigned an index based on this ordering. *

- * Properties are ordered by name, that is, they are sprted - * alphabetically such that - * {@code properties[i].name < properties[i+1].name} - * for all {@code i >= 0}. + * Every implementor of {@code CompositeUserType} must be immutable + * and must declare a public default constructor. */ @Incubating public interface CompositeUserType extends EmbeddableInstantiator { /** - * Get the value of a property. + * Get the value of the property with the given index. Properties + * of the {@link #embeddable()} are sorted by name and assigned an + * index based on this ordering. * * @param component an instance of class mapped by this "type" * @param property the property index * @return the property value - * @throws HibernateException */ Object getPropertyValue(J component, int property) throws HibernateException; @@ -56,15 +64,11 @@ public interface CompositeUserType extends EmbeddableInstantiator { /** * The class that represents the embeddable mapping of the type. - * - * @return Class */ Class embeddable(); /** * The class returned by {@code instantiate()}. - * - * @return Class */ Class returnedClass(); diff --git a/hibernate-core/src/main/java/org/hibernate/usertype/UserCollectionType.java b/hibernate-core/src/main/java/org/hibernate/usertype/UserCollectionType.java index d44d23d3e1..8dcb871102 100644 --- a/hibernate-core/src/main/java/org/hibernate/usertype/UserCollectionType.java +++ b/hibernate-core/src/main/java/org/hibernate/usertype/UserCollectionType.java @@ -16,7 +16,7 @@ import org.hibernate.metamodel.CollectionClassification; import org.hibernate.persister.collection.CollectionPersister; /** - * A custom type for mapping user-written classes that implement {@code PersistentCollection} + * A custom type for mapping user-written classes which implement {@link PersistentCollection}. * * @see PersistentCollection * diff --git a/hibernate-core/src/main/java/org/hibernate/usertype/UserType.java b/hibernate-core/src/main/java/org/hibernate/usertype/UserType.java index 78d5669dd2..3699342b09 100644 --- a/hibernate-core/src/main/java/org/hibernate/usertype/UserType.java +++ b/hibernate-core/src/main/java/org/hibernate/usertype/UserType.java @@ -21,33 +21,37 @@ import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.spi.TypeConfiguration; /** - * This interface should be implemented by user-defined "types". - * A "type" class is not the actual property type - it - * is a class that knows how to serialize instances of another - * class to and from JDBC. + * This interface should be implemented by user-defined custom types. + * A custom type is not an actual persistent attribute type, + * rather it is a class responsible for serializing instances of some + * other class to and from JDBC. This other class should have "value" + * semantics, since its identity is lost as part of this serialization + * process. *

- * This interface + * Every implementor of {@code UserType} must be immutable and must + * declare a public default constructor. + *

+ * This interface: *

    - *
  • abstracts user code from future changes to the {@code Type} - * interface,
  • - *
  • simplifies the implementation of custom types and
  • - *
  • hides certain "internal" interfaces from user code.
  • + *
  • abstracts user code away from changes to the interface + * {@link org.hibernate.type.Type}, + *
  • simplifies the implementation of custom types, and + *
  • hides certain SPI interfaces from user code. *
+ * The class {@link org.hibernate.type.CustomType} automatically adapts + * between {@code UserType} and {@link org.hibernate.type.Type}. *

- * Implementors must be immutable and must declare a public - * default constructor. + * In principle, a custom type could implement {@code Type} directly, + * or extend one of the abstract classes in {@link org.hibernate.type}. + * But this approach risks breakage resulting from future incompatible + * changes to classes or interfaces in that package, and is therefore + * discouraged. *

- * The actual class mapped by a {@code UserType} may be just - * about anything. - *

- * {@code CompositeUserType} provides an extended version of - * this interface that is useful for more complex cases. - *

- * Alternatively, custom types could implement {@code Type} - * directly or extend one of the abstract classes in - * {@link org.hibernate.type}. This approach risks future - * incompatible changes to classes or interfaces in that - * package. + * A custom type implemented as a {@code UserType} is treated as a + * non-composite value, and does not have persistent attributes which + * may be used in queries. If a custom type does have attributes, and + * can be thought of as something more like an embeddable object, it + * might be better to implement {@link CompositeUserType}. * * @see org.hibernate.type.Type * @see org.hibernate.type.CustomType diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/cut/ImmutableMonetoryAmountUserType.java b/hibernate-core/src/test/java/org/hibernate/orm/test/cut/ImmutableMonetoryAmountUserType.java index fe52b2b37d..1a1206b881 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/cut/ImmutableMonetoryAmountUserType.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/cut/ImmutableMonetoryAmountUserType.java @@ -33,7 +33,7 @@ public class ImmutableMonetoryAmountUserType implements CompositeUserType returnedClass() { return ImmutableMonetoryAmount.class; }