split UserComponentType out from ComponentType
and add CompositeType.replacePropertyValues() this refactoring results in significant simplifications/cleanliness
This commit is contained in:
parent
47024e7bd5
commit
2c5ee8f088
|
@ -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,6 +332,10 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<?> getComponentClass() throws MappingException {
|
public Class<?> getComponentClass() throws MappingException {
|
||||||
|
if ( componentClassName == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
final ClassLoaderService classLoaderService = getMetadata()
|
final ClassLoaderService classLoaderService = getMetadata()
|
||||||
.getMetadataBuildingOptions()
|
.getMetadataBuildingOptions()
|
||||||
.getServiceRegistry()
|
.getServiceRegistry()
|
||||||
|
@ -338,6 +347,7 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
|
||||||
throw new MappingException("component class not found: " + componentClassName, e);
|
throw new MappingException("component class not found: " + componentClassName, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public PersistentClass getOwner() {
|
public PersistentClass getOwner() {
|
||||||
return owner;
|
return owner;
|
||||||
|
@ -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 );
|
||||||
|
|
||||||
|
final String typeName = getTypeName();
|
||||||
|
if ( typeName == null ) {
|
||||||
localType = isEmbedded()
|
localType = isEmbedded()
|
||||||
? new EmbeddedComponentType( this, originalPropertyOrder, getBuildingContext() )
|
? new EmbeddedComponentType( this, originalPropertyOrder )
|
||||||
: new ComponentType( this, originalPropertyOrder, getBuildingContext() );
|
: new ComponentType( this, originalPropertyOrder );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final CompositeUserType<?> compositeUserType = createCompositeUserType( this );
|
||||||
|
localType = new UserComponentType<>( this, originalPropertyOrder, compositeUserType );
|
||||||
|
}
|
||||||
|
|
||||||
this.type = localType;
|
type = localType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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]
|
|
||||||
: compositeType.getPropertyValues( currentOriginal, session );
|
|
||||||
final Object[] targetComponentValues = target[i] == null
|
|
||||||
? new Object[subtypes.length]
|
|
||||||
: compositeType.getPropertyValues( target[i], session );
|
|
||||||
final Object[] objects = replaceAssociations(
|
|
||||||
origComponentValues,
|
|
||||||
targetComponentValues,
|
|
||||||
subtypes,
|
|
||||||
session,
|
session,
|
||||||
null,
|
|
||||||
copyCache,
|
copyCache,
|
||||||
foreignKeyDirection
|
foreignKeyDirection,
|
||||||
|
target[i],
|
||||||
|
currentOriginal,
|
||||||
|
compositeType
|
||||||
);
|
);
|
||||||
if ( target[i] != null && compositeType instanceof ComponentType ) {
|
if ( target[i] != null ) {
|
||||||
final ComponentType componentType = (ComponentType) compositeType;
|
target[i] = compositeType.replacePropertyValues( target[i], objects, session );
|
||||||
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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() );
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue