mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-11 21:54:50 +00:00
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;
|
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.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.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.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.metamodel.spi.RuntimeModelCreationContext;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
|
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
|
||||||
import org.hibernate.property.access.spi.Getter;
|
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.JavaType;
|
||||||
|
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base support for EmbeddableMappingType implementations
|
* Base support for EmbeddableMappingType implementations
|
||||||
@ -71,4 +106,286 @@ public void setValues(Object component, Object[] values) {
|
|||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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 @@ private boolean finishInitialization(
|
|||||||
String rootTableExpression,
|
String rootTableExpression,
|
||||||
String[] rootTableKeyColumnNames,
|
String[] rootTableKeyColumnNames,
|
||||||
MappingModelCreationProcess creationProcess) {
|
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 SessionFactoryImplementor sessionFactory = creationProcess.getCreationContext().getSessionFactory();
|
||||||
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||||
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
|
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
|
||||||
|
@ -6,33 +6,20 @@
|
|||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.mapping.internal;
|
package org.hibernate.metamodel.mapping.internal;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.hibernate.MappingException;
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.SharedSessionContract;
|
|
||||||
import org.hibernate.dialect.Dialect;
|
|
||||||
import org.hibernate.engine.FetchStyle;
|
import org.hibernate.engine.FetchStyle;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
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.EntityKey;
|
||||||
import org.hibernate.engine.spi.PersistenceContext;
|
import org.hibernate.engine.spi.PersistenceContext;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
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.Component;
|
||||||
import org.hibernate.mapping.IndexedConsumer;
|
import org.hibernate.mapping.IndexedConsumer;
|
||||||
import org.hibernate.mapping.Property;
|
|
||||||
import org.hibernate.mapping.RootClass;
|
import org.hibernate.mapping.RootClass;
|
||||||
import org.hibernate.mapping.Selectable;
|
|
||||||
import org.hibernate.mapping.Table;
|
import org.hibernate.mapping.Table;
|
||||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||||
@ -49,7 +36,6 @@
|
|||||||
import org.hibernate.metamodel.mapping.SelectableMapping;
|
import org.hibernate.metamodel.mapping.SelectableMapping;
|
||||||
import org.hibernate.metamodel.mapping.SelectableMappings;
|
import org.hibernate.metamodel.mapping.SelectableMappings;
|
||||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadata;
|
|
||||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||||
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
|
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
|
||||||
@ -63,16 +49,10 @@
|
|||||||
import org.hibernate.sql.results.graph.DomainResult;
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
import org.hibernate.type.AnyType;
|
import org.hibernate.type.AnyType;
|
||||||
import org.hibernate.type.BasicType;
|
|
||||||
import org.hibernate.type.CollectionType;
|
import org.hibernate.type.CollectionType;
|
||||||
import org.hibernate.type.CompositeType;
|
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.JavaType;
|
||||||
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
|
||||||
import org.hibernate.type.spi.CompositeTypeImplementor;
|
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.internal.util.collections.CollectionHelper.arrayList;
|
||||||
import static org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper.getStateArrayContributorMetadataAccess;
|
import static org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper.getStateArrayContributorMetadataAccess;
|
||||||
@ -468,8 +448,6 @@ public EmbeddableMappingType createInverseMappingType(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// init
|
// init
|
||||||
|
|
||||||
@ -479,263 +457,38 @@ private boolean finishInitialization(
|
|||||||
String rootTableExpression,
|
String rootTableExpression,
|
||||||
String[] rootTableKeyColumnNames,
|
String[] rootTableKeyColumnNames,
|
||||||
MappingModelCreationProcess creationProcess) {
|
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
|
// Reset the attribute mappings that were added in previous attempts
|
||||||
this.attributeMappings.clear();
|
this.attributeMappings.clear();
|
||||||
|
|
||||||
final Iterator<Property> propertyIterator = bootDescriptor.getPropertyIterator();
|
return finishInitialization(
|
||||||
while ( propertyIterator.hasNext() ) {
|
navigableRole,
|
||||||
final Property bootPropertyDescriptor = propertyIterator.next();
|
bootDescriptor,
|
||||||
|
compositeType,
|
||||||
final PropertyAccess propertyAccess = getRepresentationStrategy().resolvePropertyAccess( bootPropertyDescriptor );
|
rootTableExpression,
|
||||||
|
rootTableKeyColumnNames,
|
||||||
final AttributeMapping attributeMapping;
|
this,
|
||||||
|
representationStrategy,
|
||||||
final Type subtype = subtypes[ attributeIndex ];
|
(attributeName, attributeType) -> {
|
||||||
if ( subtype instanceof BasicType ) {
|
if ( attributeType instanceof CollectionType ) {
|
||||||
final BasicValue basicValue = (BasicValue) bootPropertyDescriptor.getValue();
|
throw new IllegalAttributeType( "An IdClass cannot define collection attributes : " + attributeName );
|
||||||
final Selectable selectable = basicValue.getColumn();
|
|
||||||
final String containingTableExpression;
|
|
||||||
final String columnExpression;
|
|
||||||
if ( rootTableKeyColumnNames == null ) {
|
|
||||||
if ( selectable.isFormula() ) {
|
|
||||||
columnExpression = selectable.getTemplate( dialect, creationProcess.getSqmFunctionRegistry() );
|
|
||||||
}
|
}
|
||||||
else {
|
if ( attributeType instanceof AnyType ) {
|
||||||
columnExpression = selectable.getText( dialect );
|
throw new IllegalAttributeType( "An IdClass cannot define <any/> attributes : " + attributeName );
|
||||||
}
|
}
|
||||||
if ( selectable instanceof Column ) {
|
},
|
||||||
containingTableExpression = getTableIdentifierExpression(
|
(column, jdbcEnvironment) -> getTableIdentifierExpression( column.getValue().getTable(), jdbcEnvironment ),
|
||||||
( (Column) selectable ).getValue().getTable(),
|
this::addAttribute,
|
||||||
jdbcEnvironment
|
() -> {
|
||||||
);
|
// We need the attribute mapping types to finish initialization first before we can build the column mappings
|
||||||
}
|
creationProcess.registerInitializationCallback(
|
||||||
else {
|
"IdClassEmbeddable(" + getNavigableRole() + ")#initColumnMappings",
|
||||||
containingTableExpression = rootTableExpression;
|
this::initColumnMappings
|
||||||
}
|
);
|
||||||
}
|
},
|
||||||
else {
|
creationProcess
|
||||||
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
|
|
||||||
);
|
);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static String getTableIdentifierExpression(Table table, JdbcEnvironment jdbcEnvironment) {
|
private static String getTableIdentifierExpression(Table table, JdbcEnvironment jdbcEnvironment) {
|
||||||
return jdbcEnvironment
|
return jdbcEnvironment
|
||||||
.getQualifiedObjectNameFormatter().format(
|
.getQualifiedObjectNameFormatter().format(
|
||||||
@ -749,6 +502,10 @@ private boolean initColumnMappings() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addAttribute(AttributeMapping attributeMapping) {
|
||||||
|
addAttribute( (SingularAttributeMapping) attributeMapping );
|
||||||
|
}
|
||||||
|
|
||||||
private void addAttribute(SingularAttributeMapping attributeMapping) {
|
private void addAttribute(SingularAttributeMapping attributeMapping) {
|
||||||
// check if we've already seen this attribute...
|
// check if we've already seen this attribute...
|
||||||
for ( int i = 0; i < attributeMappings.size(); i++ ) {
|
for ( int i = 0; i < attributeMappings.size(); i++ ) {
|
||||||
|
@ -6,29 +6,14 @@
|
|||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.mapping.internal;
|
package org.hibernate.metamodel.mapping.internal;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.hibernate.MappingException;
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
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.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.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.Component;
|
||||||
import org.hibernate.mapping.IndexedConsumer;
|
import org.hibernate.mapping.IndexedConsumer;
|
||||||
import org.hibernate.mapping.Property;
|
|
||||||
import org.hibernate.mapping.Selectable;
|
|
||||||
import org.hibernate.mapping.Table;
|
import org.hibernate.mapping.Table;
|
||||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||||
@ -44,11 +29,8 @@
|
|||||||
import org.hibernate.metamodel.mapping.SelectableMapping;
|
import org.hibernate.metamodel.mapping.SelectableMapping;
|
||||||
import org.hibernate.metamodel.mapping.SelectableMappings;
|
import org.hibernate.metamodel.mapping.SelectableMappings;
|
||||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
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.model.domain.NavigableRole;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.property.access.spi.PropertyAccess;
|
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.sql.ast.Clause;
|
import org.hibernate.sql.ast.Clause;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
@ -56,15 +38,9 @@
|
|||||||
import org.hibernate.sql.results.graph.DomainResult;
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
import org.hibernate.type.AnyType;
|
import org.hibernate.type.AnyType;
|
||||||
import org.hibernate.type.BasicType;
|
|
||||||
import org.hibernate.type.CollectionType;
|
import org.hibernate.type.CollectionType;
|
||||||
import org.hibernate.type.CompositeType;
|
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.CompositeTypeImplementor;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
|
||||||
|
|
||||||
import static org.hibernate.internal.util.collections.CollectionHelper.arrayList;
|
import static org.hibernate.internal.util.collections.CollectionHelper.arrayList;
|
||||||
import static org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping.IdentifierValueMapper;
|
import static org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping.IdentifierValueMapper;
|
||||||
@ -375,259 +351,37 @@ private boolean finishInitialization(
|
|||||||
String rootTableExpression,
|
String rootTableExpression,
|
||||||
String[] rootTableKeyColumnNames,
|
String[] rootTableKeyColumnNames,
|
||||||
MappingModelCreationProcess creationProcess) {
|
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
|
// Reset the attribute mappings that were added in previous attempts
|
||||||
this.attributeMappings.clear();
|
this.attributeMappings.clear();
|
||||||
|
|
||||||
final Iterator<Property> propertyIterator = bootDescriptor.getPropertyIterator();
|
return finishInitialization(
|
||||||
while ( propertyIterator.hasNext() ) {
|
navigableRole,
|
||||||
final Property bootPropertyDescriptor = propertyIterator.next();
|
bootDescriptor,
|
||||||
|
compositeType,
|
||||||
final PropertyAccess propertyAccess = getRepresentationStrategy().resolvePropertyAccess( bootPropertyDescriptor );
|
rootTableExpression,
|
||||||
|
rootTableKeyColumnNames,
|
||||||
final AttributeMapping attributeMapping;
|
this,
|
||||||
|
representationStrategy,
|
||||||
final Type subtype = subtypes[ attributeIndex ];
|
(attributeName, attributeType) -> {
|
||||||
if ( subtype instanceof BasicType ) {
|
if ( attributeType instanceof CollectionType ) {
|
||||||
final BasicValue basicValue = (BasicValue) bootPropertyDescriptor.getValue();
|
throw new IllegalAttributeType( "A \"virtual id\" cannot define collection attributes : " + attributeName );
|
||||||
final Selectable selectable = basicValue.getColumn();
|
|
||||||
final String containingTableExpression;
|
|
||||||
final String columnExpression;
|
|
||||||
if ( rootTableKeyColumnNames == null ) {
|
|
||||||
if ( selectable.isFormula() ) {
|
|
||||||
columnExpression = selectable.getTemplate( dialect, creationProcess.getSqmFunctionRegistry() );
|
|
||||||
}
|
}
|
||||||
else {
|
if ( attributeType instanceof AnyType ) {
|
||||||
columnExpression = selectable.getText( dialect );
|
throw new IllegalAttributeType( "A \"virtual id\" cannot define <any/> attributes : " + attributeName );
|
||||||
}
|
}
|
||||||
if ( selectable instanceof Column ) {
|
},
|
||||||
containingTableExpression = getTableIdentifierExpression(
|
(column, jdbcEnvironment) -> getTableIdentifierExpression( column.getValue().getTable(), jdbcEnvironment ),
|
||||||
( (Column) selectable ).getValue().getTable(),
|
this::addAttribute,
|
||||||
jdbcEnvironment
|
() -> {
|
||||||
);
|
// We need the attribute mapping types to finish initialization first before we can build the column mappings
|
||||||
}
|
creationProcess.registerInitializationCallback(
|
||||||
else {
|
"VirtualIdEmbeddable(" + navigableRole + ")#initColumnMappings",
|
||||||
containingTableExpression = rootTableExpression;
|
this::initColumnMappings
|
||||||
}
|
);
|
||||||
}
|
},
|
||||||
else {
|
creationProcess
|
||||||
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
|
|
||||||
);
|
);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -645,6 +399,10 @@ private boolean initColumnMappings() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addAttribute(AttributeMapping attributeMapping) {
|
||||||
|
addAttribute( (SingularAttributeMapping) attributeMapping );
|
||||||
|
}
|
||||||
|
|
||||||
private void addAttribute(SingularAttributeMapping attributeMapping) {
|
private void addAttribute(SingularAttributeMapping attributeMapping) {
|
||||||
// check if we've already seen this attribute...
|
// check if we've already seen this attribute...
|
||||||
for ( int i = 0; i < attributeMappings.size(); i++ ) {
|
for ( int i = 0; i < attributeMappings.size(); i++ ) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user