split UserComponentType out from ComponentType

and add CompositeType.replacePropertyValues()

this refactoring results in significant simplifications/cleanliness
This commit is contained in:
Gavin King 2023-07-22 13:00:38 +02:00
parent 47024e7bd5
commit 2c5ee8f088
6 changed files with 228 additions and 120 deletions

View File

@ -26,6 +26,7 @@ import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.boot.model.source.internal.hbm.MappingDocument; import org.hibernate.boot.model.source.internal.hbm.MappingDocument;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.Mapping;
@ -42,9 +43,13 @@ import org.hibernate.metamodel.spi.EmbeddableInstantiator;
import org.hibernate.property.access.spi.Setter; import org.hibernate.property.access.spi.Setter;
import org.hibernate.generator.Generator; import org.hibernate.generator.Generator;
import org.hibernate.generator.BeforeExecutionGenerator; import org.hibernate.generator.BeforeExecutionGenerator;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.type.ComponentType; import org.hibernate.type.ComponentType;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
import org.hibernate.type.EmbeddedComponentType; import org.hibernate.type.EmbeddedComponentType;
import org.hibernate.type.UserComponentType;
import org.hibernate.usertype.CompositeUserType;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toList;
import static org.hibernate.generator.EventType.INSERT; import static org.hibernate.generator.EventType.INSERT;
@ -327,15 +332,20 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
} }
public Class<?> getComponentClass() throws MappingException { public Class<?> getComponentClass() throws MappingException {
final ClassLoaderService classLoaderService = getMetadata() if ( componentClassName == null ) {
.getMetadataBuildingOptions() return null;
.getServiceRegistry()
.getService( ClassLoaderService.class );
try {
return classLoaderService.classForName( componentClassName );
} }
catch (ClassLoadingException e) { else {
throw new MappingException("component class not found: " + componentClassName, e); final ClassLoaderService classLoaderService = getMetadata()
.getMetadataBuildingOptions()
.getServiceRegistry()
.getService( ClassLoaderService.class );
try {
return classLoaderService.classForName( componentClassName );
}
catch (ClassLoadingException e) {
throw new MappingException("component class not found: " + componentClassName, e);
}
} }
} }
@ -371,12 +381,22 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
this.dynamic = dynamic; this.dynamic = dynamic;
} }
private CompositeUserType<?> createCompositeUserType(Component component) {
final BootstrapContext bootstrapContext = getBuildingContext().getBootstrapContext();
final Class<CompositeUserType<?>> customTypeClass =
bootstrapContext.getClassLoaderAccess().classForName( component.getTypeName() );
return getBuildingContext().getBuildingOptions().disallowExtensionsInCdi()
? FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( customTypeClass )
: bootstrapContext.getServiceRegistry().requireService( ManagedBeanRegistry.class )
.getBean( customTypeClass ).getBeanInstance();
}
@Override @Override
public CompositeType getType() throws MappingException { public CompositeType getType() throws MappingException {
// Resolve the type of the value once and for all as this operation generates a proxy class // Resolve the type of the value once and for all as this operation generates a proxy class
// for each invocation. // for each invocation.
// Unfortunately, there's no better way of doing that as none of the classes are immutable and // Unfortunately, there's no better way of doing that as none of the classes are immutable,
// we can't know for sure the current state of the property or the value. // and we can't know for sure the current state of the property or the value.
CompositeType localType = type; CompositeType localType = type;
if ( localType == null ) { if ( localType == null ) {
@ -387,11 +407,18 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
// Other components should be sorted already // Other components should be sorted already
sortProperties( true ); sortProperties( true );
localType = isEmbedded() final String typeName = getTypeName();
? new EmbeddedComponentType( this, originalPropertyOrder, getBuildingContext() ) if ( typeName == null ) {
: new ComponentType( this, originalPropertyOrder, getBuildingContext() ); localType = isEmbedded()
? new EmbeddedComponentType( this, originalPropertyOrder )
: new ComponentType( this, originalPropertyOrder );
}
else {
final CompositeUserType<?> compositeUserType = createCompositeUserType( this );
localType = new UserComponentType<>( this, originalPropertyOrder, compositeUserType );
}
this.type = localType; type = localType;
} }
} }
} }

View File

@ -19,7 +19,6 @@ import org.hibernate.HibernateException;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.PropertyNotFoundException; import org.hibernate.PropertyNotFoundException;
import org.hibernate.Remove; import org.hibernate.Remove;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer; import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.engine.spi.CascadeStyle;
@ -38,12 +37,9 @@ import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.metamodel.spi.EmbeddableInstantiator; import org.hibernate.metamodel.spi.EmbeddableInstantiator;
import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.type.descriptor.ValueExtractor; import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.spi.CompositeTypeImplementor; import org.hibernate.type.spi.CompositeTypeImplementor;
import org.hibernate.usertype.CompositeUserType;
import static org.hibernate.internal.util.ReflectHelper.isRecord; import static org.hibernate.internal.util.ReflectHelper.isRecord;
@ -68,13 +64,22 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
private final boolean isKey; private final boolean isKey;
private boolean hasNotNullProperty; private boolean hasNotNullProperty;
@SuppressWarnings("rawtypes")
private final CompositeUserType compositeUserType;
private EmbeddableValuedModelPart mappingModelPart; private EmbeddableValuedModelPart mappingModelPart;
public ComponentType(Component component, int[] originalPropertyOrder, MetadataBuildingContext buildingContext) { @Deprecated(forRemoval = true)
public ComponentType(Component component, int[] originalPropertyOrder, MetadataBuildingContext context) {
this( component, originalPropertyOrder );
}
public ComponentType(Component component, int[] originalPropertyOrder) {
this( component, originalPropertyOrder,
component.getComponentClassName() != null
&& !isRecord( component.getComponentClass() ) );
}
public ComponentType(Component component, int[] originalPropertyOrder, boolean mutable) {
this.componentClass = component.isDynamic() ? Map.class : component.getComponentClass(); this.componentClass = component.isDynamic() ? Map.class : component.getComponentClass();
this.mutable = mutable;
this.isAggregate = component.getAggregateColumn() != null; this.isAggregate = component.getAggregateColumn() != null;
this.isKey = component.isKey(); this.isKey = component.isKey();
this.propertySpan = component.getPropertySpan(); this.propertySpan = component.getPropertySpan();
@ -97,23 +102,6 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
} }
i++; i++;
} }
this.compositeUserType =
component.getTypeName() == null ? null : createCompositeUserType( component, buildingContext );
this.mutable = !isRecord( componentClass ) && ( compositeUserType == null || compositeUserType.isMutable() );
}
private static CompositeUserType<?> createCompositeUserType(Component component, MetadataBuildingContext buildingContext) {
final BootstrapContext bootstrapContext = buildingContext.getBootstrapContext();
final Class<CompositeUserType<?>> customTypeClass =
bootstrapContext.getClassLoaderAccess().classForName( component.getTypeName() );
if ( buildingContext.getBuildingOptions().disallowExtensionsInCdi() ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( customTypeClass );
}
else {
return bootstrapContext.getServiceRegistry().requireService( ManagedBeanRegistry.class )
.getBean( customTypeClass ).getBeanInstance();
}
} }
private boolean isAggregate() { private boolean isAggregate() {
@ -178,9 +166,6 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
if ( x == y ) { if ( x == y ) {
return true; return true;
} }
if ( compositeUserType != null ) {
return compositeUserType.equals( x, y );
}
// null value and empty component are considered equivalent // null value and empty component are considered equivalent
for ( int i = 0; i < propertySpan; i++ ) { for ( int i = 0; i < propertySpan; i++ ) {
if ( !propertyTypes[i].isEqual( getPropertyValue( x, i ), getPropertyValue( y, i ) ) ) { if ( !propertyTypes[i].isEqual( getPropertyValue( x, i ), getPropertyValue( y, i ) ) ) {
@ -196,9 +181,6 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
if ( x == y ) { if ( x == y ) {
return true; return true;
} }
if ( compositeUserType != null ) {
return compositeUserType.equals( x, y );
}
// null value and empty component are considered equivalent // null value and empty component are considered equivalent
for ( int i = 0; i < propertySpan; i++ ) { for ( int i = 0; i < propertySpan; i++ ) {
if ( !propertyTypes[i].isEqual( getPropertyValue( x, i ), getPropertyValue( y, i ), factory ) ) { if ( !propertyTypes[i].isEqual( getPropertyValue( x, i ), getPropertyValue( y, i ), factory ) ) {
@ -242,9 +224,6 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
@Override @Override
public int getHashCode(final Object x) { public int getHashCode(final Object x) {
if ( compositeUserType != null ) {
return compositeUserType.hashCode( x );
}
int result = 17; int result = 17;
for ( int i = 0; i < propertySpan; i++ ) { for ( int i = 0; i < propertySpan; i++ ) {
final Object y = getPropertyValue( x, i ); final Object y = getPropertyValue( x, i );
@ -258,9 +237,6 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
@Override @Override
public int getHashCode(final Object x, final SessionFactoryImplementor factory) { public int getHashCode(final Object x, final SessionFactoryImplementor factory) {
if ( compositeUserType != null ) {
return compositeUserType.hashCode( x );
}
int result = 17; int result = 17;
for ( int i = 0; i < propertySpan; i++ ) { for ( int i = 0; i < propertySpan; i++ ) {
final Object y = getPropertyValue( x, i ); final Object y = getPropertyValue( x, i );
@ -273,7 +249,8 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
} }
@Override @Override
public boolean isDirty(final Object x, final Object y, final SharedSessionContractImplementor session) throws HibernateException { public boolean isDirty(final Object x, final Object y, final SharedSessionContractImplementor session)
throws HibernateException {
if ( x == y ) { if ( x == y ) {
return false; return false;
} }
@ -335,7 +312,8 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
final int len = propertyTypes[i].getColumnSpan( session.getFactory() ); final int len = propertyTypes[i].getColumnSpan( session.getFactory() );
final boolean[] subcheckable = new boolean[len]; final boolean[] subcheckable = new boolean[len];
System.arraycopy( checkable, loc, subcheckable, 0, len ); System.arraycopy( checkable, loc, subcheckable, 0, len );
if ( propertyTypes[i].isModified( getPropertyValue( old, i ), getPropertyValue( current, i ), subcheckable, session ) ) { if ( propertyTypes[i].isModified( getPropertyValue( old, i ),
getPropertyValue( current, i ), subcheckable, session ) ) {
return true; return true;
} }
loc += len; loc += len;
@ -493,9 +471,6 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
return null; return null;
} }
if ( compositeUserType != null ) {
return compositeUserType.deepCopy( component );
}
final Object[] values = getPropertyValues( component ); final Object[] values = getPropertyValues( component );
for ( int i = 0; i < propertySpan; i++ ) { for ( int i = 0; i < propertySpan; i++ ) {
values[i] = propertyTypes[i].deepCopy( values[i], factory ); values[i] = propertyTypes[i].deepCopy( values[i], factory );
@ -527,20 +502,10 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
if ( original == null ) { if ( original == null ) {
return null; return null;
} }
if ( compositeUserType != null ) {
return compositeUserType.replace( original, target, owner );
}
//if ( original == target ) return target; //if ( original == target ) return target;
final Object[] originalValues = getPropertyValues( original ); final Object[] originalValues = getPropertyValues( original );
final Object[] resultValues; final Object[] resultValues = target == null ? new Object[originalValues.length] : getPropertyValues( target );
if ( target == null ) {
resultValues = new Object[originalValues.length];
}
else {
resultValues = getPropertyValues( target );
}
final Object[] replacedValues = TypeHelper.replace( final Object[] replacedValues = TypeHelper.replace(
originalValues, originalValues,
@ -552,8 +517,7 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
); );
if ( target == null ) { if ( target == null ) {
return instantiator() return instantiator().instantiate( () -> replacedValues, session.getSessionFactory() );
.instantiate( () -> replacedValues, session.getSessionFactory() );
} }
else { else {
setPropertyValues( target, replacedValues ); setPropertyValues( target, replacedValues );
@ -576,9 +540,6 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
if ( original == null ) { if ( original == null ) {
return null; return null;
} }
if ( compositeUserType != null ) {
return compositeUserType.replace( original, target, owner );
}
//if ( original == target ) return target; //if ( original == target ) return target;
final Object[] originalValues = getPropertyValues( original ); final Object[] originalValues = getPropertyValues( original );
@ -610,6 +571,8 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
} }
} }
@Override @Override
public CascadeStyle getCascadeStyle(int i) { public CascadeStyle getCascadeStyle(int i) {
return cascade[i]; return cascade[i];
@ -626,9 +589,6 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
if ( value == null ) { if ( value == null ) {
return null; return null;
} }
else if ( compositeUserType != null ) {
return compositeUserType.disassemble( value );
}
else { else {
final Object[] values = getPropertyValues( value ); final Object[] values = getPropertyValues( value );
for ( int i = 0; i < propertyTypes.length; i++ ) { for ( int i = 0; i < propertyTypes.length; i++ ) {
@ -639,13 +599,11 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
} }
@Override @Override
public Serializable disassemble(Object value, SessionFactoryImplementor sessionFactory) throws HibernateException { public Serializable disassemble(Object value, SessionFactoryImplementor sessionFactory)
throws HibernateException {
if ( value == null ) { if ( value == null ) {
return null; return null;
} }
else if ( compositeUserType != null ) {
return compositeUserType.disassemble( value );
}
else { else {
final Object[] values = getPropertyValues( value ); final Object[] values = getPropertyValues( value );
for ( int i = 0; i < propertyTypes.length; i++ ) { for ( int i = 0; i < propertyTypes.length; i++ ) {
@ -662,9 +620,6 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
if ( object == null ) { if ( object == null ) {
return null; return null;
} }
else if ( compositeUserType != null ) {
return compositeUserType.assemble( object, owner );
}
else { else {
final Object[] values = (Object[]) object; final Object[] values = (Object[]) object;
final Object[] assembled = new Object[values.length]; final Object[] assembled = new Object[values.length];
@ -753,7 +708,8 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
} }
@Override @Override
public Object extract(CallableStatement statement, int startIndex, SharedSessionContractImplementor session) throws SQLException { public Object extract(CallableStatement statement, int startIndex, SharedSessionContractImplementor session)
throws SQLException {
Object[] values; Object[] values;
if ( isAggregate() ) { if ( isAggregate() ) {
values = (Object[]) jdbcValueExtractor().extract( statement, startIndex, session ); values = (Object[]) jdbcValueExtractor().extract( statement, startIndex, session );
@ -842,8 +798,4 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
} }
return mappingModelPart; return mappingModelPart;
} }
public boolean isCompositeUserType() {
return compositeUserType != null;
}
} }

View File

@ -16,8 +16,8 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
/** /**
* Represents a <em>composite</em> type, a type which itself has typed attributes. * Represents a <em>composite</em> type, a type which itself has typed attributes.
* <p> * <p>
* For example, a type representing an {@linkplain jakarta.persistence.Embeddable embeddable} * For example, a type representing an {@linkplain jakarta.persistence.Embeddable embeddable} class
* class is a composite type. * is a composite type, as is a type backed by a {@link org.hibernate.usertype.CompositeUserType}.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@ -55,7 +55,8 @@ public interface CompositeType extends Type {
* *
* @throws HibernateException Indicates a problem access the property values. * @throws HibernateException Indicates a problem access the property values.
*/ */
Object[] getPropertyValues(Object component, SharedSessionContractImplementor session) throws HibernateException; Object[] getPropertyValues(Object component, SharedSessionContractImplementor session)
throws HibernateException;
/** /**
* Extract the values of the component properties from the given component instance without access to the * Extract the values of the component properties from the given component instance without access to the
@ -81,7 +82,8 @@ public interface CompositeType extends Type {
* *
* @throws HibernateException Indicates a problem access the property value. * @throws HibernateException Indicates a problem access the property value.
*/ */
Object getPropertyValue(Object component, int index, SharedSessionContractImplementor session) throws HibernateException; Object getPropertyValue(Object component, int index, SharedSessionContractImplementor session)
throws HibernateException;
/** /**
* Inject property values onto the given component instance * Inject property values onto the given component instance
@ -95,6 +97,24 @@ public interface CompositeType extends Type {
*/ */
void setPropertyValues(Object component, Object[] values) throws HibernateException; void setPropertyValues(Object component, Object[] values) throws HibernateException;
/**
* Inject property values onto the given component instance, or return a new
* instance with the given property values.
*
* @param component The component instance
* @param values The values to inject
* @return A new instance is necessary
*
* @throws HibernateException Indicates an issue performing the injection
*
* @since 6.3
*/
default Object replacePropertyValues(Object component, Object[] values, SharedSessionContractImplementor session)
throws HibernateException {
setPropertyValues( component, values );
return component;
}
/** /**
* Retrieve the cascade style of the indicated component property. * Retrieve the cascade style of the indicated component property.
* *

View File

@ -18,10 +18,16 @@ import org.hibernate.property.access.spi.Getter;
* @author Gavin King * @author Gavin King
*/ */
public class EmbeddedComponentType extends ComponentType { public class EmbeddedComponentType extends ComponentType {
@Deprecated(forRemoval = true)
public EmbeddedComponentType(Component component, int[] originalPropertyOrder, MetadataBuildingContext buildingContext) { public EmbeddedComponentType(Component component, int[] originalPropertyOrder, MetadataBuildingContext buildingContext) {
super( component, originalPropertyOrder, buildingContext ); super( component, originalPropertyOrder, buildingContext );
} }
public EmbeddedComponentType(Component component, int[] originalPropertyOrder) {
super( component, originalPropertyOrder );
}
@Override @Override
public boolean isEmbedded() { public boolean isEmbedded() {
return true; return true;

View File

@ -11,7 +11,6 @@ import java.util.Map;
import org.hibernate.Internal; import org.hibernate.Internal;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer; import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.spi.EmbeddableInstantiator;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl; import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
@ -195,34 +194,17 @@ public class TypeHelper {
if ( type.isComponentType() ) { if ( type.isComponentType() ) {
final CompositeType compositeType = (CompositeType) type; final CompositeType compositeType = (CompositeType) type;
// need to extract the component values and check for subtype replacements... // need to extract the component values and check for subtype replacements...
final Type[] subtypes = compositeType.getSubtypes(); final Object[] objects =
final Object[] origComponentValues = currentOriginal == null replaceCompositeAssociations(
? new Object[subtypes.length] session,
: compositeType.getPropertyValues( currentOriginal, session ); copyCache,
final Object[] targetComponentValues = target[i] == null foreignKeyDirection,
? new Object[subtypes.length] target[i],
: compositeType.getPropertyValues( target[i], session ); currentOriginal,
final Object[] objects = replaceAssociations( compositeType
origComponentValues, );
targetComponentValues, if ( target[i] != null ) {
subtypes, target[i] = compositeType.replacePropertyValues( target[i], objects, session );
session,
null,
copyCache,
foreignKeyDirection
);
if ( target[i] != null && compositeType instanceof ComponentType ) {
final ComponentType componentType = (ComponentType) compositeType;
if ( componentType.isCompositeUserType() ) {
final EmbeddableInstantiator instantiator = ( (ComponentType) compositeType ).getMappingModelPart()
.getEmbeddableTypeDescriptor()
.getRepresentationStrategy()
.getInstantiator();
target[i] = instantiator.instantiate( () -> objects, session.getSessionFactory() );
}
else {
compositeType.setPropertyValues( target[i], objects );
}
} }
copied[i] = target[i]; copied[i] = target[i];
} }
@ -237,4 +219,26 @@ public class TypeHelper {
return copied; return copied;
} }
private static Object[] replaceCompositeAssociations(
SharedSessionContractImplementor session,
Map<Object, Object> copyCache,
ForeignKeyDirection foreignKeyDirection,
Object target, Object currentOriginal,
CompositeType compositeType) {
final Type[] subtypes = compositeType.getSubtypes();
return replaceAssociations(
currentOriginal == null
? new Object[subtypes.length]
: compositeType.getPropertyValues( currentOriginal, session ),
target == null
? new Object[subtypes.length]
: compositeType.getPropertyValues( target, session ),
subtypes,
session,
null,
copyCache,
foreignKeyDirection
);
}
} }

View File

@ -0,0 +1,99 @@
/*
* 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.type;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.mapping.Component;
import org.hibernate.usertype.CompositeUserType;
import java.io.Serializable;
import java.util.Map;
/**
* Handles {@link CompositeUserType}s.
*
* @author Gavin King
*
* @since 6.3
*/
public class UserComponentType<T> extends ComponentType {
private final CompositeUserType<T> compositeUserType;
public UserComponentType(
Component component,
int[] originalPropertyOrder,
CompositeUserType<T> compositeUserType) {
super( component, originalPropertyOrder, compositeUserType.isMutable() );
this.compositeUserType = compositeUserType;
}
@Override
public boolean isEqual(Object x, Object y) throws HibernateException {
return x==y || compositeUserType.equals( (T) x, (T) y );
}
@Override
public boolean isEqual(Object x, Object y, SessionFactoryImplementor factory)
throws HibernateException {
return isEqual( x, y );
}
@Override
public int getHashCode(Object x) {
return compositeUserType.hashCode( (T) x );
}
@Override
public int getHashCode(Object x, SessionFactoryImplementor factory) {
return getHashCode( x );
}
@Override
public Object deepCopy(Object component, SessionFactoryImplementor factory) {
return component == null ? null : compositeUserType.deepCopy( (T) component );
}
@Override
public Object replace(Object original, Object target, SharedSessionContractImplementor session, Object owner, Map<Object, Object> copyCache) {
return original == null || !isMutable() ? original : compositeUserType.replace( (T) original, (T) target, owner );
}
@Override
public Object replace(Object original, Object target, SharedSessionContractImplementor session, Object owner, Map<Object, Object> copyCache, ForeignKeyDirection foreignKeyDirection) {
return replace( original, target, session, owner, copyCache );
}
@Override
public Serializable disassemble(Object value, SessionFactoryImplementor sessionFactory)
throws HibernateException {
return value == null ? null : compositeUserType.disassemble( (T) value );
}
@Override
public Serializable disassemble(Object value, SharedSessionContractImplementor session, Object owner)
throws HibernateException {
return disassemble( value, session.getFactory() );
}
@Override
public Object assemble(Serializable object, SharedSessionContractImplementor session, Object owner)
throws HibernateException {
return object == null ? null : compositeUserType.assemble( object, owner );
}
@Override
public Object replacePropertyValues(Object component, Object[] values, SharedSessionContractImplementor session)
throws HibernateException {
return getMappingModelPart()
.getEmbeddableTypeDescriptor()
.getRepresentationStrategy()
.getInstantiator().instantiate( () -> values, session.getSessionFactory() );
}
}