Introduce `VirtualIdEmbeddable` and `IdClassEmbeddable` + instantiators
- shared `#finishInitialization` handling for `VirtualIdEmbeddable` and `IdClassEmbeddable` note: was not yet able to get that working with `EmbeddableMappingType` - clean up ComponentType, esp wrt its use of ComponentTuplizer Still need to - integrate embedded forms. `VirtualIdEmbeddable` does not really need it as it can use the id-mapping itself as the embedded form. But `IdClassEmbedded` should really be integrated - integrate `VirtualKeyEmbeddable` and `VirtualKeyEmbedded` for use as inverse composite fks - ability to use the containing composite owner as the parent of a composite (legacy behavior is to always use the "first" entity
This commit is contained in:
parent
55bfc59db1
commit
8ab27a0ff0
|
@ -6,13 +6,48 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.mapping.internal;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.SharedSessionContract;
|
||||
import org.hibernate.bytecode.spi.ReflectionOptimizer;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.mapping.Any;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Selectable;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadata;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
|
||||
import org.hibernate.property.access.spi.Getter;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.type.AnyType;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.CollectionType;
|
||||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.EntityType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* Base support for EmbeddableMappingType implementations
|
||||
|
@ -71,4 +106,286 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
|
|||
} );
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
protected interface ConcreteTableResolver {
|
||||
String resolve(Column column, JdbcEnvironment jdbcEnvironment);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
protected interface SuccessfulCompletionCallback {
|
||||
void success();
|
||||
}
|
||||
|
||||
protected static class IllegalAttributeType extends RuntimeException {
|
||||
public IllegalAttributeType(String message) {
|
||||
super( message );
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
protected interface AttributeTypeValidator {
|
||||
void check(String name, Type type) throws IllegalAttributeType;
|
||||
}
|
||||
|
||||
protected static boolean finishInitialization(
|
||||
NavigableRole navigableRole,
|
||||
Component bootDescriptor,
|
||||
CompositeType compositeType,
|
||||
String rootTableExpression,
|
||||
String[] rootTableKeyColumnNames,
|
||||
EmbeddableMappingType declarer,
|
||||
EmbeddableRepresentationStrategy representationStrategy,
|
||||
AttributeTypeValidator attributeTypeValidator,
|
||||
ConcreteTableResolver concreteTableResolver,
|
||||
Consumer<AttributeMapping> attributeConsumer,
|
||||
SuccessfulCompletionCallback completionCallback,
|
||||
MappingModelCreationProcess creationProcess) {
|
||||
final SessionFactoryImplementor sessionFactory = creationProcess.getCreationContext().getSessionFactory();
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
|
||||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final Dialect dialect = jdbcEnvironment.getDialect();
|
||||
|
||||
final Type[] subtypes = compositeType.getSubtypes();
|
||||
|
||||
int attributeIndex = 0;
|
||||
int columnPosition = 0;
|
||||
|
||||
final Iterator<Property> propertyIterator = bootDescriptor.getPropertyIterator();
|
||||
while ( propertyIterator.hasNext() ) {
|
||||
final Property bootPropertyDescriptor = propertyIterator.next();
|
||||
final Type subtype = subtypes[ attributeIndex ];
|
||||
|
||||
attributeTypeValidator.check( bootPropertyDescriptor.getName(), subtype );
|
||||
|
||||
final PropertyAccess propertyAccess = representationStrategy.resolvePropertyAccess( bootPropertyDescriptor );
|
||||
final AttributeMapping attributeMapping;
|
||||
|
||||
if ( subtype instanceof BasicType ) {
|
||||
final BasicValue basicValue = (BasicValue) bootPropertyDescriptor.getValue();
|
||||
final Selectable selectable = basicValue.getColumn();
|
||||
final String containingTableExpression;
|
||||
final String columnExpression;
|
||||
if ( rootTableKeyColumnNames == null ) {
|
||||
if ( selectable.isFormula() ) {
|
||||
columnExpression = selectable.getTemplate( dialect, creationProcess.getSqmFunctionRegistry() );
|
||||
}
|
||||
else {
|
||||
columnExpression = selectable.getText( dialect );
|
||||
}
|
||||
|
||||
if ( selectable instanceof Column ) {
|
||||
containingTableExpression = concreteTableResolver.resolve( (Column) selectable, jdbcEnvironment );
|
||||
}
|
||||
else {
|
||||
containingTableExpression = rootTableExpression;
|
||||
}
|
||||
}
|
||||
else {
|
||||
containingTableExpression = rootTableExpression;
|
||||
columnExpression = rootTableKeyColumnNames[ columnPosition ];
|
||||
}
|
||||
|
||||
attributeMapping = MappingModelCreationHelper.buildBasicAttributeMapping(
|
||||
bootPropertyDescriptor.getName(),
|
||||
navigableRole.append( bootPropertyDescriptor.getName() ),
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
declarer,
|
||||
(BasicType<?>) subtype,
|
||||
containingTableExpression,
|
||||
columnExpression,
|
||||
selectable.isFormula(),
|
||||
selectable.getCustomReadExpression(),
|
||||
selectable.getCustomWriteExpression(),
|
||||
propertyAccess,
|
||||
compositeType.getCascadeStyle( attributeIndex ),
|
||||
creationProcess
|
||||
);
|
||||
|
||||
columnPosition++;
|
||||
}
|
||||
else if ( subtype instanceof AnyType ) {
|
||||
final Any bootValueMapping = (Any) bootPropertyDescriptor.getValue();
|
||||
final AnyType anyType = (AnyType) subtype;
|
||||
|
||||
final boolean nullable = bootValueMapping.isNullable();
|
||||
final boolean insertable = bootPropertyDescriptor.isInsertable();
|
||||
final boolean updateable = bootPropertyDescriptor.isUpdateable();
|
||||
final boolean includeInOptimisticLocking = bootPropertyDescriptor.isOptimisticLocked();
|
||||
final CascadeStyle cascadeStyle = compositeType.getCascadeStyle( attributeIndex );
|
||||
final MutabilityPlan<?> mutabilityPlan;
|
||||
|
||||
if ( updateable ) {
|
||||
mutabilityPlan = new MutabilityPlan<Object>() {
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object deepCopy(Object value) {
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return anyType.deepCopy( value, creationProcess.getCreationContext().getSessionFactory() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable disassemble(Object value, SharedSessionContract session) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object assemble(Serializable cached, SharedSessionContract session) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
mutabilityPlan = ImmutableMutabilityPlan.INSTANCE;
|
||||
}
|
||||
|
||||
final StateArrayContributorMetadataAccess attributeMetadataAccess = entityMappingType -> new StateArrayContributorMetadata() {
|
||||
@Override
|
||||
public PropertyAccess getPropertyAccess() {
|
||||
return propertyAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutabilityPlan<?> getMutabilityPlan() {
|
||||
return mutabilityPlan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullable() {
|
||||
return nullable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInsertable() {
|
||||
return insertable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpdatable() {
|
||||
return updateable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludedInDirtyChecking() {
|
||||
// todo (6.0) : do not believe this is correct
|
||||
return updateable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludedInOptimisticLocking() {
|
||||
return includeInOptimisticLocking;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CascadeStyle getCascadeStyle() {
|
||||
return cascadeStyle;
|
||||
}
|
||||
};
|
||||
|
||||
attributeMapping = new DiscriminatedAssociationAttributeMapping(
|
||||
navigableRole.append( bootPropertyDescriptor.getName() ),
|
||||
typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Object.class ),
|
||||
declarer,
|
||||
attributeIndex,
|
||||
attributeMetadataAccess,
|
||||
bootPropertyDescriptor.isLazy() ? FetchTiming.DELAYED : FetchTiming.IMMEDIATE,
|
||||
propertyAccess,
|
||||
bootPropertyDescriptor,
|
||||
anyType,
|
||||
bootValueMapping,
|
||||
creationProcess
|
||||
);
|
||||
}
|
||||
else if ( subtype instanceof CompositeType ) {
|
||||
final CompositeType subCompositeType = (CompositeType) subtype;
|
||||
final int columnSpan = subCompositeType.getColumnSpan( sessionFactory );
|
||||
final String subTableExpression;
|
||||
final String[] subRootTableKeyColumnNames;
|
||||
if ( rootTableKeyColumnNames == null ) {
|
||||
subTableExpression = rootTableExpression;
|
||||
subRootTableKeyColumnNames = null;
|
||||
}
|
||||
else {
|
||||
subTableExpression = rootTableExpression;
|
||||
subRootTableKeyColumnNames = new String[ columnSpan ];
|
||||
System.arraycopy( rootTableKeyColumnNames, columnPosition, subRootTableKeyColumnNames, 0, columnSpan );
|
||||
}
|
||||
|
||||
attributeMapping = MappingModelCreationHelper.buildEmbeddedAttributeMapping(
|
||||
bootPropertyDescriptor.getName(),
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
declarer,
|
||||
subCompositeType,
|
||||
subTableExpression,
|
||||
subRootTableKeyColumnNames,
|
||||
propertyAccess,
|
||||
compositeType.getCascadeStyle( attributeIndex ),
|
||||
creationProcess
|
||||
);
|
||||
|
||||
columnPosition += columnSpan;
|
||||
}
|
||||
else if ( subtype instanceof CollectionType ) {
|
||||
final EntityPersister entityPersister = creationProcess.getEntityPersister( bootDescriptor.getOwner()
|
||||
.getEntityName() );
|
||||
|
||||
attributeMapping = MappingModelCreationHelper.buildPluralAttributeMapping(
|
||||
bootPropertyDescriptor.getName(),
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
entityPersister,
|
||||
propertyAccess,
|
||||
compositeType.getCascadeStyle( attributeIndex ),
|
||||
compositeType.getFetchMode( attributeIndex ),
|
||||
creationProcess
|
||||
);
|
||||
}
|
||||
else if ( subtype instanceof EntityType ) {
|
||||
final EntityPersister entityPersister = creationProcess.getEntityPersister( bootDescriptor.getOwner()
|
||||
.getEntityName() );
|
||||
|
||||
attributeMapping = MappingModelCreationHelper.buildSingularAssociationAttributeMapping(
|
||||
bootPropertyDescriptor.getName(),
|
||||
navigableRole.append( bootPropertyDescriptor.getName() ),
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
entityPersister,
|
||||
entityPersister,
|
||||
(EntityType) subtype,
|
||||
representationStrategy.resolvePropertyAccess( bootPropertyDescriptor ),
|
||||
compositeType.getCascadeStyle( attributeIndex ),
|
||||
creationProcess
|
||||
);
|
||||
columnPosition += bootPropertyDescriptor.getColumnSpan();
|
||||
}
|
||||
else {
|
||||
throw new MappingException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Unable to determine attribute nature : %s#%s",
|
||||
bootDescriptor.getOwner().getEntityName(),
|
||||
bootPropertyDescriptor.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
attributeConsumer.accept( attributeMapping );
|
||||
|
||||
attributeIndex++;
|
||||
}
|
||||
|
||||
completionCallback.success();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -275,6 +275,32 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
|
|||
String rootTableExpression,
|
||||
String[] rootTableKeyColumnNames,
|
||||
MappingModelCreationProcess creationProcess) {
|
||||
// for some reason I cannot get this to work, though only a single test fails - `CompositeElementTest`
|
||||
// return finishInitialization(
|
||||
// getNavigableRole(),
|
||||
// bootDescriptor,
|
||||
// compositeType,
|
||||
// rootTableExpression,
|
||||
// rootTableKeyColumnNames,
|
||||
// this,
|
||||
// representationStrategy,
|
||||
// (name, type) -> {},
|
||||
// (column, jdbcEnvironment) -> getTableIdentifierExpression(
|
||||
// column.getValue().getTable(),
|
||||
// jdbcEnvironment
|
||||
// ),
|
||||
// this::addAttribute,
|
||||
// () -> {
|
||||
// // We need the attribute mapping types to finish initialization first before we can build the column mappings
|
||||
// creationProcess.registerInitializationCallback(
|
||||
// "EmbeddableMappingType(" + getEmbeddedValueMapping().getNavigableRole().getFullPath() + ")#initColumnMappings",
|
||||
// this::initColumnMappings
|
||||
// );
|
||||
// },
|
||||
// creationProcess
|
||||
// );
|
||||
// todo (6.0) - get this ^^ to work, or drop the comment
|
||||
|
||||
final SessionFactoryImplementor sessionFactory = creationProcess.getCreationContext().getSessionFactory();
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
|
||||
|
|
|
@ -6,33 +6,20 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.mapping.internal;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.SharedSessionContract;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.engine.spi.EntityKey;
|
||||
import org.hibernate.engine.spi.PersistenceContext;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.mapping.Any;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.IndexedConsumer;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.RootClass;
|
||||
import org.hibernate.mapping.Selectable;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
|
@ -49,7 +36,6 @@ import org.hibernate.metamodel.mapping.SelectableConsumer;
|
|||
import org.hibernate.metamodel.mapping.SelectableMapping;
|
||||
import org.hibernate.metamodel.mapping.SelectableMappings;
|
||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadata;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
|
||||
|
@ -63,16 +49,10 @@ import org.hibernate.sql.ast.tree.from.TableGroupProducer;
|
|||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.type.AnyType;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.CollectionType;
|
||||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.EntityType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
||||
import org.hibernate.type.spi.CompositeTypeImplementor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import static org.hibernate.internal.util.collections.CollectionHelper.arrayList;
|
||||
import static org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper.getStateArrayContributorMetadataAccess;
|
||||
|
@ -468,8 +448,6 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// init
|
||||
|
||||
|
@ -479,263 +457,38 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden
|
|||
String rootTableExpression,
|
||||
String[] rootTableKeyColumnNames,
|
||||
MappingModelCreationProcess creationProcess) {
|
||||
final SessionFactoryImplementor sessionFactory = creationProcess.getCreationContext().getSessionFactory();
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
|
||||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final Dialect dialect = jdbcEnvironment.getDialect();
|
||||
|
||||
final Type[] subtypes = compositeType.getSubtypes();
|
||||
|
||||
int attributeIndex = 0;
|
||||
int columnPosition = 0;
|
||||
|
||||
// Reset the attribute mappings that were added in previous attempts
|
||||
this.attributeMappings.clear();
|
||||
|
||||
final Iterator<Property> propertyIterator = bootDescriptor.getPropertyIterator();
|
||||
while ( propertyIterator.hasNext() ) {
|
||||
final Property bootPropertyDescriptor = propertyIterator.next();
|
||||
|
||||
final PropertyAccess propertyAccess = getRepresentationStrategy().resolvePropertyAccess( bootPropertyDescriptor );
|
||||
|
||||
final AttributeMapping attributeMapping;
|
||||
|
||||
final Type subtype = subtypes[ attributeIndex ];
|
||||
if ( subtype instanceof BasicType ) {
|
||||
final BasicValue basicValue = (BasicValue) bootPropertyDescriptor.getValue();
|
||||
final Selectable selectable = basicValue.getColumn();
|
||||
final String containingTableExpression;
|
||||
final String columnExpression;
|
||||
if ( rootTableKeyColumnNames == null ) {
|
||||
if ( selectable.isFormula() ) {
|
||||
columnExpression = selectable.getTemplate( dialect, creationProcess.getSqmFunctionRegistry() );
|
||||
return finishInitialization(
|
||||
navigableRole,
|
||||
bootDescriptor,
|
||||
compositeType,
|
||||
rootTableExpression,
|
||||
rootTableKeyColumnNames,
|
||||
this,
|
||||
representationStrategy,
|
||||
(attributeName, attributeType) -> {
|
||||
if ( attributeType instanceof CollectionType ) {
|
||||
throw new IllegalAttributeType( "An IdClass cannot define collection attributes : " + attributeName );
|
||||
}
|
||||
else {
|
||||
columnExpression = selectable.getText( dialect );
|
||||
if ( attributeType instanceof AnyType ) {
|
||||
throw new IllegalAttributeType( "An IdClass cannot define <any/> attributes : " + attributeName );
|
||||
}
|
||||
if ( selectable instanceof Column ) {
|
||||
containingTableExpression = getTableIdentifierExpression(
|
||||
( (Column) selectable ).getValue().getTable(),
|
||||
jdbcEnvironment
|
||||
);
|
||||
}
|
||||
else {
|
||||
containingTableExpression = rootTableExpression;
|
||||
}
|
||||
}
|
||||
else {
|
||||
containingTableExpression = rootTableExpression;
|
||||
columnExpression = rootTableKeyColumnNames[ columnPosition ];
|
||||
}
|
||||
|
||||
attributeMapping = MappingModelCreationHelper.buildBasicAttributeMapping(
|
||||
bootPropertyDescriptor.getName(),
|
||||
navigableRole.append( bootPropertyDescriptor.getName() ),
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
this,
|
||||
(BasicType<?>) subtype,
|
||||
containingTableExpression,
|
||||
columnExpression,
|
||||
selectable.isFormula(),
|
||||
selectable.getCustomReadExpression(),
|
||||
selectable.getCustomWriteExpression(),
|
||||
propertyAccess,
|
||||
compositeType.getCascadeStyle( attributeIndex ),
|
||||
creationProcess
|
||||
);
|
||||
|
||||
columnPosition++;
|
||||
}
|
||||
else if ( subtype instanceof AnyType ) {
|
||||
final Any bootValueMapping = (Any) bootPropertyDescriptor.getValue();
|
||||
final AnyType anyType = (AnyType) subtype;
|
||||
|
||||
final boolean nullable = bootValueMapping.isNullable();
|
||||
final boolean insertable = bootPropertyDescriptor.isInsertable();
|
||||
final boolean updateable = bootPropertyDescriptor.isUpdateable();
|
||||
final boolean includeInOptimisticLocking = bootPropertyDescriptor.isOptimisticLocked();
|
||||
final CascadeStyle cascadeStyle = compositeType.getCascadeStyle( attributeIndex );
|
||||
final MutabilityPlan<?> mutabilityPlan;
|
||||
|
||||
if ( updateable ) {
|
||||
mutabilityPlan = new MutabilityPlan<Object>() {
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object deepCopy(Object value) {
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return anyType.deepCopy( value, creationProcess.getCreationContext().getSessionFactory() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable disassemble(Object value, SharedSessionContract session) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object assemble(Serializable cached, SharedSessionContract session) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
mutabilityPlan = ImmutableMutabilityPlan.INSTANCE;
|
||||
}
|
||||
|
||||
final StateArrayContributorMetadataAccess attributeMetadataAccess = entityMappingType -> new StateArrayContributorMetadata() {
|
||||
@Override
|
||||
public PropertyAccess getPropertyAccess() {
|
||||
return propertyAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutabilityPlan<?> getMutabilityPlan() {
|
||||
return mutabilityPlan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullable() {
|
||||
return nullable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInsertable() {
|
||||
return insertable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpdatable() {
|
||||
return updateable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludedInDirtyChecking() {
|
||||
// todo (6.0) : do not believe this is correct
|
||||
return updateable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludedInOptimisticLocking() {
|
||||
return includeInOptimisticLocking;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CascadeStyle getCascadeStyle() {
|
||||
return cascadeStyle;
|
||||
}
|
||||
};
|
||||
|
||||
attributeMapping = new DiscriminatedAssociationAttributeMapping(
|
||||
navigableRole.append( bootPropertyDescriptor.getName() ),
|
||||
typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Object.class ),
|
||||
this,
|
||||
attributeIndex,
|
||||
attributeMetadataAccess,
|
||||
bootPropertyDescriptor.isLazy() ? FetchTiming.DELAYED : FetchTiming.IMMEDIATE,
|
||||
propertyAccess,
|
||||
bootPropertyDescriptor,
|
||||
anyType,
|
||||
bootValueMapping,
|
||||
creationProcess
|
||||
);
|
||||
}
|
||||
else if ( subtype instanceof CompositeType ) {
|
||||
final CompositeType subCompositeType = (CompositeType) subtype;
|
||||
final int columnSpan = subCompositeType.getColumnSpan( sessionFactory );
|
||||
final String subTableExpression;
|
||||
final String[] subRootTableKeyColumnNames;
|
||||
if ( rootTableKeyColumnNames == null ) {
|
||||
subTableExpression = rootTableExpression;
|
||||
subRootTableKeyColumnNames = null;
|
||||
}
|
||||
else {
|
||||
subTableExpression = rootTableExpression;
|
||||
subRootTableKeyColumnNames = new String[ columnSpan ];
|
||||
System.arraycopy( rootTableKeyColumnNames, columnPosition, subRootTableKeyColumnNames, 0, columnSpan );
|
||||
}
|
||||
|
||||
attributeMapping = MappingModelCreationHelper.buildEmbeddedAttributeMapping(
|
||||
bootPropertyDescriptor.getName(),
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
this,
|
||||
subCompositeType,
|
||||
subTableExpression,
|
||||
subRootTableKeyColumnNames,
|
||||
propertyAccess,
|
||||
compositeType.getCascadeStyle( attributeIndex ),
|
||||
creationProcess
|
||||
);
|
||||
|
||||
columnPosition += columnSpan;
|
||||
}
|
||||
else if ( subtype instanceof CollectionType ) {
|
||||
final EntityPersister entityPersister = creationProcess.getEntityPersister( bootDescriptor.getOwner()
|
||||
.getEntityName() );
|
||||
|
||||
attributeMapping = MappingModelCreationHelper.buildPluralAttributeMapping(
|
||||
bootPropertyDescriptor.getName(),
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
entityPersister,
|
||||
propertyAccess,
|
||||
compositeType.getCascadeStyle( attributeIndex ),
|
||||
compositeType.getFetchMode( attributeIndex ),
|
||||
creationProcess
|
||||
);
|
||||
}
|
||||
else if ( subtype instanceof EntityType ) {
|
||||
final EntityPersister entityPersister = creationProcess.getEntityPersister( bootDescriptor.getOwner()
|
||||
.getEntityName() );
|
||||
|
||||
attributeMapping = MappingModelCreationHelper.buildSingularAssociationAttributeMapping(
|
||||
bootPropertyDescriptor.getName(),
|
||||
navigableRole.append( bootPropertyDescriptor.getName() ),
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
entityPersister,
|
||||
entityPersister,
|
||||
(EntityType) subtype,
|
||||
getRepresentationStrategy().resolvePropertyAccess( bootPropertyDescriptor ),
|
||||
compositeType.getCascadeStyle( attributeIndex ),
|
||||
creationProcess
|
||||
);
|
||||
columnPosition += bootPropertyDescriptor.getColumnSpan();
|
||||
}
|
||||
else {
|
||||
throw new MappingException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Unable to determine attribute nature : %s#%s",
|
||||
bootDescriptor.getOwner().getEntityName(),
|
||||
bootPropertyDescriptor.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
addAttribute( (SingularAttributeMapping) attributeMapping );
|
||||
|
||||
attributeIndex++;
|
||||
}
|
||||
|
||||
// We need the attribute mapping types to finish initialization first before we can build the column mappings
|
||||
creationProcess.registerInitializationCallback(
|
||||
"EmbeddableMappingType(" + navigableRole + ")#initColumnMappings",
|
||||
this::initColumnMappings
|
||||
},
|
||||
(column, jdbcEnvironment) -> getTableIdentifierExpression( column.getValue().getTable(), jdbcEnvironment ),
|
||||
this::addAttribute,
|
||||
() -> {
|
||||
// We need the attribute mapping types to finish initialization first before we can build the column mappings
|
||||
creationProcess.registerInitializationCallback(
|
||||
"IdClassEmbeddable(" + getNavigableRole() + ")#initColumnMappings",
|
||||
this::initColumnMappings
|
||||
);
|
||||
},
|
||||
creationProcess
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static String getTableIdentifierExpression(Table table, JdbcEnvironment jdbcEnvironment) {
|
||||
return jdbcEnvironment
|
||||
.getQualifiedObjectNameFormatter().format(
|
||||
|
@ -749,6 +502,10 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden
|
|||
return true;
|
||||
}
|
||||
|
||||
private void addAttribute(AttributeMapping attributeMapping) {
|
||||
addAttribute( (SingularAttributeMapping) attributeMapping );
|
||||
}
|
||||
|
||||
private void addAttribute(SingularAttributeMapping attributeMapping) {
|
||||
// check if we've already seen this attribute...
|
||||
for ( int i = 0; i < attributeMappings.size(); i++ ) {
|
||||
|
|
|
@ -6,29 +6,14 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.mapping.internal;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.SharedSessionContract;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.mapping.Any;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.IndexedConsumer;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Selectable;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
|
@ -44,11 +29,8 @@ import org.hibernate.metamodel.mapping.SelectableConsumer;
|
|||
import org.hibernate.metamodel.mapping.SelectableMapping;
|
||||
import org.hibernate.metamodel.mapping.SelectableMappings;
|
||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadata;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
|
@ -56,15 +38,9 @@ import org.hibernate.sql.ast.tree.from.TableGroupProducer;
|
|||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.type.AnyType;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.CollectionType;
|
||||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.EntityType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
|
||||
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
||||
import org.hibernate.type.spi.CompositeTypeImplementor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import static org.hibernate.internal.util.collections.CollectionHelper.arrayList;
|
||||
import static org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping.IdentifierValueMapper;
|
||||
|
@ -375,259 +351,37 @@ public class VirtualIdEmbeddable extends AbstractEmbeddableMapping implements Id
|
|||
String rootTableExpression,
|
||||
String[] rootTableKeyColumnNames,
|
||||
MappingModelCreationProcess creationProcess) {
|
||||
final SessionFactoryImplementor sessionFactory = creationProcess.getCreationContext().getSessionFactory();
|
||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
|
||||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final Dialect dialect = jdbcEnvironment.getDialect();
|
||||
|
||||
final Type[] subtypes = compositeType.getSubtypes();
|
||||
|
||||
int attributeIndex = 0;
|
||||
int columnPosition = 0;
|
||||
|
||||
// Reset the attribute mappings that were added in previous attempts
|
||||
this.attributeMappings.clear();
|
||||
|
||||
final Iterator<Property> propertyIterator = bootDescriptor.getPropertyIterator();
|
||||
while ( propertyIterator.hasNext() ) {
|
||||
final Property bootPropertyDescriptor = propertyIterator.next();
|
||||
|
||||
final PropertyAccess propertyAccess = getRepresentationStrategy().resolvePropertyAccess( bootPropertyDescriptor );
|
||||
|
||||
final AttributeMapping attributeMapping;
|
||||
|
||||
final Type subtype = subtypes[ attributeIndex ];
|
||||
if ( subtype instanceof BasicType ) {
|
||||
final BasicValue basicValue = (BasicValue) bootPropertyDescriptor.getValue();
|
||||
final Selectable selectable = basicValue.getColumn();
|
||||
final String containingTableExpression;
|
||||
final String columnExpression;
|
||||
if ( rootTableKeyColumnNames == null ) {
|
||||
if ( selectable.isFormula() ) {
|
||||
columnExpression = selectable.getTemplate( dialect, creationProcess.getSqmFunctionRegistry() );
|
||||
return finishInitialization(
|
||||
navigableRole,
|
||||
bootDescriptor,
|
||||
compositeType,
|
||||
rootTableExpression,
|
||||
rootTableKeyColumnNames,
|
||||
this,
|
||||
representationStrategy,
|
||||
(attributeName, attributeType) -> {
|
||||
if ( attributeType instanceof CollectionType ) {
|
||||
throw new IllegalAttributeType( "A \"virtual id\" cannot define collection attributes : " + attributeName );
|
||||
}
|
||||
else {
|
||||
columnExpression = selectable.getText( dialect );
|
||||
if ( attributeType instanceof AnyType ) {
|
||||
throw new IllegalAttributeType( "A \"virtual id\" cannot define <any/> attributes : " + attributeName );
|
||||
}
|
||||
if ( selectable instanceof Column ) {
|
||||
containingTableExpression = getTableIdentifierExpression(
|
||||
( (Column) selectable ).getValue().getTable(),
|
||||
jdbcEnvironment
|
||||
);
|
||||
}
|
||||
else {
|
||||
containingTableExpression = rootTableExpression;
|
||||
}
|
||||
}
|
||||
else {
|
||||
containingTableExpression = rootTableExpression;
|
||||
columnExpression = rootTableKeyColumnNames[ columnPosition ];
|
||||
}
|
||||
|
||||
attributeMapping = MappingModelCreationHelper.buildBasicAttributeMapping(
|
||||
bootPropertyDescriptor.getName(),
|
||||
navigableRole.append( bootPropertyDescriptor.getName() ),
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
this,
|
||||
(BasicType<?>) subtype,
|
||||
containingTableExpression,
|
||||
columnExpression,
|
||||
selectable.isFormula(),
|
||||
selectable.getCustomReadExpression(),
|
||||
selectable.getCustomWriteExpression(),
|
||||
propertyAccess,
|
||||
compositeType.getCascadeStyle( attributeIndex ),
|
||||
creationProcess
|
||||
);
|
||||
|
||||
columnPosition++;
|
||||
}
|
||||
else if ( subtype instanceof AnyType ) {
|
||||
final Any bootValueMapping = (Any) bootPropertyDescriptor.getValue();
|
||||
final AnyType anyType = (AnyType) subtype;
|
||||
|
||||
final boolean nullable = bootValueMapping.isNullable();
|
||||
final boolean insertable = bootPropertyDescriptor.isInsertable();
|
||||
final boolean updateable = bootPropertyDescriptor.isUpdateable();
|
||||
final boolean includeInOptimisticLocking = bootPropertyDescriptor.isOptimisticLocked();
|
||||
final CascadeStyle cascadeStyle = compositeType.getCascadeStyle( attributeIndex );
|
||||
final MutabilityPlan<?> mutabilityPlan;
|
||||
|
||||
if ( updateable ) {
|
||||
mutabilityPlan = new MutabilityPlan<Object>() {
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object deepCopy(Object value) {
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return anyType.deepCopy( value, creationProcess.getCreationContext().getSessionFactory() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable disassemble(Object value, SharedSessionContract session) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object assemble(Serializable cached, SharedSessionContract session) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
mutabilityPlan = ImmutableMutabilityPlan.INSTANCE;
|
||||
}
|
||||
|
||||
final StateArrayContributorMetadataAccess attributeMetadataAccess = entityMappingType -> new StateArrayContributorMetadata() {
|
||||
@Override
|
||||
public PropertyAccess getPropertyAccess() {
|
||||
return propertyAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutabilityPlan<?> getMutabilityPlan() {
|
||||
return mutabilityPlan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullable() {
|
||||
return nullable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInsertable() {
|
||||
return insertable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpdatable() {
|
||||
return updateable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludedInDirtyChecking() {
|
||||
// todo (6.0) : do not believe this is correct
|
||||
return updateable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludedInOptimisticLocking() {
|
||||
return includeInOptimisticLocking;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CascadeStyle getCascadeStyle() {
|
||||
return cascadeStyle;
|
||||
}
|
||||
};
|
||||
|
||||
attributeMapping = new DiscriminatedAssociationAttributeMapping(
|
||||
navigableRole.append( bootPropertyDescriptor.getName() ),
|
||||
typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Object.class ),
|
||||
this,
|
||||
attributeIndex,
|
||||
attributeMetadataAccess,
|
||||
bootPropertyDescriptor.isLazy() ? FetchTiming.DELAYED : FetchTiming.IMMEDIATE,
|
||||
propertyAccess,
|
||||
bootPropertyDescriptor,
|
||||
anyType,
|
||||
bootValueMapping,
|
||||
creationProcess
|
||||
);
|
||||
}
|
||||
else if ( subtype instanceof CompositeType ) {
|
||||
final CompositeType subCompositeType = (CompositeType) subtype;
|
||||
final int columnSpan = subCompositeType.getColumnSpan( sessionFactory );
|
||||
final String subTableExpression;
|
||||
final String[] subRootTableKeyColumnNames;
|
||||
if ( rootTableKeyColumnNames == null ) {
|
||||
subTableExpression = rootTableExpression;
|
||||
subRootTableKeyColumnNames = null;
|
||||
}
|
||||
else {
|
||||
subTableExpression = rootTableExpression;
|
||||
subRootTableKeyColumnNames = new String[ columnSpan ];
|
||||
System.arraycopy( rootTableKeyColumnNames, columnPosition, subRootTableKeyColumnNames, 0, columnSpan );
|
||||
}
|
||||
|
||||
attributeMapping = MappingModelCreationHelper.buildEmbeddedAttributeMapping(
|
||||
bootPropertyDescriptor.getName(),
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
this,
|
||||
subCompositeType,
|
||||
subTableExpression,
|
||||
subRootTableKeyColumnNames,
|
||||
propertyAccess,
|
||||
compositeType.getCascadeStyle( attributeIndex ),
|
||||
creationProcess
|
||||
);
|
||||
|
||||
columnPosition += columnSpan;
|
||||
}
|
||||
else if ( subtype instanceof CollectionType ) {
|
||||
final EntityPersister entityPersister = creationProcess.getEntityPersister( bootDescriptor.getOwner()
|
||||
.getEntityName() );
|
||||
|
||||
attributeMapping = MappingModelCreationHelper.buildPluralAttributeMapping(
|
||||
bootPropertyDescriptor.getName(),
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
entityPersister,
|
||||
propertyAccess,
|
||||
compositeType.getCascadeStyle( attributeIndex ),
|
||||
compositeType.getFetchMode( attributeIndex ),
|
||||
creationProcess
|
||||
);
|
||||
}
|
||||
else if ( subtype instanceof EntityType ) {
|
||||
final EntityPersister entityPersister = creationProcess.getEntityPersister( bootDescriptor.getOwner()
|
||||
.getEntityName() );
|
||||
|
||||
attributeMapping = MappingModelCreationHelper.buildSingularAssociationAttributeMapping(
|
||||
bootPropertyDescriptor.getName(),
|
||||
navigableRole.append( bootPropertyDescriptor.getName() ),
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
entityPersister,
|
||||
entityPersister,
|
||||
(EntityType) subtype,
|
||||
getRepresentationStrategy().resolvePropertyAccess( bootPropertyDescriptor ),
|
||||
compositeType.getCascadeStyle( attributeIndex ),
|
||||
creationProcess
|
||||
);
|
||||
columnPosition += bootPropertyDescriptor.getColumnSpan();
|
||||
}
|
||||
else {
|
||||
throw new MappingException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Unable to determine attribute nature : %s#%s",
|
||||
bootDescriptor.getOwner().getEntityName(),
|
||||
bootPropertyDescriptor.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
addAttribute( (SingularAttributeMapping) attributeMapping );
|
||||
|
||||
attributeIndex++;
|
||||
}
|
||||
|
||||
// We need the attribute mapping types to finish initialization first before we can build the column mappings
|
||||
creationProcess.registerInitializationCallback(
|
||||
"EmbeddableMappingType(" + navigableRole + ")#initColumnMappings",
|
||||
this::initColumnMappings
|
||||
},
|
||||
(column, jdbcEnvironment) -> getTableIdentifierExpression( column.getValue().getTable(), jdbcEnvironment ),
|
||||
this::addAttribute,
|
||||
() -> {
|
||||
// We need the attribute mapping types to finish initialization first before we can build the column mappings
|
||||
creationProcess.registerInitializationCallback(
|
||||
"VirtualIdEmbeddable(" + navigableRole + ")#initColumnMappings",
|
||||
this::initColumnMappings
|
||||
);
|
||||
},
|
||||
creationProcess
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -645,6 +399,10 @@ public class VirtualIdEmbeddable extends AbstractEmbeddableMapping implements Id
|
|||
return true;
|
||||
}
|
||||
|
||||
private void addAttribute(AttributeMapping attributeMapping) {
|
||||
addAttribute( (SingularAttributeMapping) attributeMapping );
|
||||
}
|
||||
|
||||
private void addAttribute(SingularAttributeMapping attributeMapping) {
|
||||
// check if we've already seen this attribute...
|
||||
for ( int i = 0; i < attributeMappings.size(); i++ ) {
|
||||
|
|
Loading…
Reference in New Issue