Introduce `VirtualIdEmbeddable` and `IdClassEmbeddable`
This 3rd commit cleans up some code Still need to - integrate EmbeddableInstantiator work - 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 - share `#finishInit` handling for `EmbeddableMappingType`, `VirtualIdEmbeddable` and `IdClassEmbeddable`
This commit is contained in:
parent
dd4f380ea9
commit
86e8b2751c
|
@ -20,12 +20,6 @@ import org.hibernate.sql.ast.tree.from.TableGroupProducer;
|
|||
* @see EmbeddableValuedModelPart
|
||||
*/
|
||||
public interface EmbeddableMappingType extends ManagedMappingType, SelectableMappings {
|
||||
EmbeddableMappingType createInverseMappingType(
|
||||
EmbeddedAttributeMapping valueMapping,
|
||||
TableGroupProducer declaringTableGroupProducer,
|
||||
SelectableMappings selectableMappings,
|
||||
MappingModelCreationProcess creationProcess);
|
||||
|
||||
EmbeddableValuedModelPart getEmbeddedValueMapping();
|
||||
|
||||
EmbeddableRepresentationStrategy getRepresentationStrategy();
|
||||
|
@ -36,6 +30,12 @@ public interface EmbeddableMappingType extends ManagedMappingType, SelectableMap
|
|||
|
||||
boolean isCreateEmptyCompositesEnabled();
|
||||
|
||||
EmbeddableMappingType createInverseMappingType(
|
||||
EmbeddedAttributeMapping valueMapping,
|
||||
TableGroupProducer declaringTableGroupProducer,
|
||||
SelectableMappings selectableMappings,
|
||||
MappingModelCreationProcess creationProcess);
|
||||
|
||||
@Override
|
||||
default int forEachSelectable(SelectableConsumer consumer) {
|
||||
return ManagedMappingType.super.forEachSelectable( consumer );
|
||||
|
|
|
@ -21,13 +21,11 @@ import org.hibernate.sql.results.graph.Fetchable;
|
|||
import org.hibernate.sql.results.graph.FetchableContainer;
|
||||
|
||||
/**
|
||||
* An embedded (embeddable-valued) model part.
|
||||
* Describes the mapping of an embeddable (composite).
|
||||
*
|
||||
* @see jakarta.persistence.Embedded
|
||||
* @see jakarta.persistence.EmbeddedId
|
||||
* @see jakarta.persistence.Embeddable
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface EmbeddableValuedModelPart extends ModelPart, Fetchable, FetchableContainer, TableGroupJoinProducer {
|
||||
EmbeddableMappingType getEmbeddableTypeDescriptor();
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.metamodel.mapping;
|
||||
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.mapping.IndexedConsumer;
|
||||
import org.hibernate.metamodel.mapping.internal.IdClassEmbeddable;
|
||||
import org.hibernate.metamodel.mapping.internal.VirtualIdEmbeddable;
|
||||
import org.hibernate.sql.results.graph.FetchOptions;
|
||||
import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable;
|
||||
|
||||
/**
|
||||
* A "non-aggregated" composite identifier, which means that the entity itself
|
||||
* does not define a singular representation of its identifier like an
|
||||
* {@link jakarta.persistence.EmbeddedId} does.
|
||||
*
|
||||
* An IdClass can be used to provide a simple, singular representation of the
|
||||
* identifier for easier reference in API calls. JPA requires using an IdClass
|
||||
* when mapping such identifiers. Hibernate supports mapping such identifiers
|
||||
* with or without the IdClass; without, the entity itself is used as the
|
||||
* identifier.
|
||||
*
|
||||
* @see jakarta.persistence.IdClass
|
||||
* @see jakarta.persistence.MapsId
|
||||
*/
|
||||
public interface NonAggregatedIdentifierMapping extends CompositeIdentifierMapping, EmbeddableValuedFetchable, FetchOptions {
|
||||
/**
|
||||
* The virtual-id representation of this id mapping
|
||||
*/
|
||||
VirtualIdEmbeddable getVirtualIdEmbeddable();
|
||||
|
||||
/**
|
||||
* The id-class representation of this id mapping
|
||||
*/
|
||||
IdClassEmbeddable getIdClassEmbeddable();
|
||||
|
||||
/**
|
||||
* The id-class, if there is one, otherwise the virtual-id.
|
||||
*/
|
||||
IdentifierValueMapper getIdentifierValueMapper();
|
||||
|
||||
/**
|
||||
* Think of an AttributeConverter for id values to account for representation
|
||||
* difference between virtual and id-class mappings
|
||||
*/
|
||||
interface IdentifierValueMapper extends EmbeddableMappingType {
|
||||
EmbeddableValuedModelPart getEmbeddedPart();
|
||||
|
||||
/**
|
||||
* Extract the identifier out of the given entity, returning the mapper's
|
||||
* representation
|
||||
*/
|
||||
Object getIdentifier(Object entity, SharedSessionContractImplementor session);
|
||||
|
||||
/**
|
||||
* Extract the identifier out of the given entity, returning the mapper's
|
||||
* representation
|
||||
*/
|
||||
void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session);
|
||||
|
||||
/**
|
||||
* Convenience method to iterate the attributes for this mapper's representation
|
||||
*/
|
||||
default void forEachAttribute(IndexedConsumer<SingularAttributeMapping> consumer) {
|
||||
getEmbeddedPart().getEmbeddableTypeDescriptor().forEachAttributeMapping( (IndexedConsumer) consumer );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -155,7 +155,6 @@ public class EmbeddableMappingTypeImpl implements EmbeddableMappingType, Selecta
|
|||
private SelectableMappings selectableMappings;
|
||||
|
||||
private final EmbeddableValuedModelPart valueMapping;
|
||||
private NavigableRole embeddedRole;
|
||||
|
||||
private final boolean createEmptyCompositesEnabled;
|
||||
|
||||
|
@ -354,10 +353,10 @@ public class EmbeddableMappingTypeImpl implements EmbeddableMappingType, Selecta
|
|||
final boolean updateable = bootPropertyDescriptor.isUpdateable();
|
||||
final boolean includeInOptimisticLocking = bootPropertyDescriptor.isOptimisticLocked();
|
||||
final CascadeStyle cascadeStyle = compositeType.getCascadeStyle( attributeIndex );
|
||||
final MutabilityPlan mutabilityPlan;
|
||||
final MutabilityPlan<?> mutabilityPlan;
|
||||
|
||||
if ( updateable ) {
|
||||
mutabilityPlan = new MutabilityPlan() {
|
||||
mutabilityPlan = new MutabilityPlan<Object>() {
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return true;
|
||||
|
@ -394,7 +393,7 @@ public class EmbeddableMappingTypeImpl implements EmbeddableMappingType, Selecta
|
|||
}
|
||||
|
||||
@Override
|
||||
public MutabilityPlan getMutabilityPlan() {
|
||||
public MutabilityPlan<?> getMutabilityPlan() {
|
||||
return mutabilityPlan;
|
||||
}
|
||||
|
||||
|
@ -523,7 +522,7 @@ public class EmbeddableMappingTypeImpl implements EmbeddableMappingType, Selecta
|
|||
|
||||
// We need the attribute mapping types to finish initialization first before we can build the column mappings
|
||||
creationProcess.registerInitializationCallback(
|
||||
"EmbeddableMappingType(" + embeddedRole + ")#initColumnMappings",
|
||||
"EmbeddableMappingType(" + getEmbeddedValueMapping().getNavigableRole().getFullPath() + ")#initColumnMappings",
|
||||
this::initColumnMappings
|
||||
);
|
||||
return true;
|
||||
|
@ -560,7 +559,7 @@ public class EmbeddableMappingTypeImpl implements EmbeddableMappingType, Selecta
|
|||
}
|
||||
|
||||
@Override
|
||||
public JavaType getMappedJavaTypeDescriptor() {
|
||||
public JavaType<?> getMappedJavaTypeDescriptor() {
|
||||
return embeddableJtd;
|
||||
}
|
||||
|
||||
|
@ -625,10 +624,8 @@ public class EmbeddableMappingTypeImpl implements EmbeddableMappingType, Selecta
|
|||
}
|
||||
|
||||
@Override
|
||||
public void visitFetchables(
|
||||
Consumer<Fetchable> fetchableConsumer,
|
||||
EntityMappingType treatTargetType) {
|
||||
visitAttributeMappings( attributeMapping -> fetchableConsumer.accept( attributeMapping ) );
|
||||
public void visitFetchables(Consumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
|
||||
visitAttributeMappings( fetchableConsumer );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -780,10 +777,8 @@ public class EmbeddableMappingTypeImpl implements EmbeddableMappingType, Selecta
|
|||
}
|
||||
|
||||
@Override
|
||||
public void visitSubParts(
|
||||
Consumer<ModelPart> consumer,
|
||||
EntityMappingType treatTargetType) {
|
||||
visitAttributeMappings( consumer::accept );
|
||||
public void visitSubParts(Consumer<ModelPart> consumer, EntityMappingType treatTargetType) {
|
||||
visitAttributeMappings( consumer );
|
||||
}
|
||||
|
||||
public Object[] getPropertyValues(Object compositeInstance) {
|
||||
|
|
|
@ -35,14 +35,14 @@ 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.internal.EmbeddableMappingTypeImpl;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingModelCreationLogger;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.SelectableConsumer;
|
||||
import org.hibernate.metamodel.mapping.SelectableMapping;
|
||||
|
@ -50,7 +50,7 @@ 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.mapping.internal.NonAggregatedIdentifierMapping.IdentifierValueMapper;
|
||||
import org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping.IdentifierValueMapper;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
|
|
@ -125,10 +125,6 @@ public class MappingModelCreationHelper {
|
|||
final PropertyAccess propertyAccess = entityPersister.getRepresentationStrategy()
|
||||
.resolvePropertyAccess( bootEntityDescriptor.getIdentifierProperty() );
|
||||
|
||||
final StateArrayContributorMetadataAccess attributeMetadataAccess = getStateArrayContributorMetadataAccess(
|
||||
propertyAccess
|
||||
);
|
||||
|
||||
final EmbeddableMappingTypeImpl embeddableMappingType = EmbeddableMappingTypeImpl.from(
|
||||
(Component) bootProperty.getValue(),
|
||||
cidType,
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.metamodel.mapping.internal;
|
||||
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.mapping.IndexedConsumer;
|
||||
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
import org.hibernate.sql.results.graph.FetchOptions;
|
||||
import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface NonAggregatedIdentifierMapping extends CompositeIdentifierMapping, EmbeddableValuedFetchable, FetchOptions {
|
||||
IdClassEmbeddable getIdClassEmbeddable();
|
||||
VirtualIdEmbeddable getVirtualIdEmbeddable();
|
||||
|
||||
IdentifierValueMapper getIdentifierValueMapper();
|
||||
|
||||
/**
|
||||
* Think of an AttributeConverter for id values. Handles representation
|
||||
* difference between virtual and id-class mappings
|
||||
*/
|
||||
interface IdentifierValueMapper extends EmbeddableMappingType {
|
||||
EmbeddableValuedModelPart getEmbeddedPart();
|
||||
|
||||
Object getIdentifier(Object entity, SharedSessionContractImplementor session);
|
||||
void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session);
|
||||
|
||||
default void forEachAttribute(IndexedConsumer<SingularAttributeMapping> consumer) {
|
||||
getEmbeddedPart().getEmbeddableTypeDescriptor().forEachAttributeMapping( (IndexedConsumer) consumer );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@ import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
|||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.SelectableMappings;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.hibernate.metamodel.mapping.EntityMappingType;
|
|||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingModelCreationLogger;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.NonTransientException;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.SelectableConsumer;
|
||||
|
@ -67,7 +68,7 @@ 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.NonAggregatedIdentifierMapping.IdentifierValueMapper;
|
||||
import static org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping.IdentifierValueMapper;
|
||||
|
||||
/**
|
||||
* Embeddable describing the virtual-id aspect of a non-aggregated composite id
|
||||
|
@ -104,7 +105,7 @@ public class VirtualIdEmbeddable implements IdentifierValueMapper {
|
|||
final CompositeType compositeType = (CompositeType) virtualIdSource.getType();
|
||||
this.attributeMappings = arrayList( (compositeType).getPropertyNames().length );
|
||||
|
||||
// todo (6.0) : can this be a separate VirtualIdEmbedded?
|
||||
// todo (6.0) : can/should this be a separate VirtualIdEmbedded?
|
||||
( (CompositeTypeImplementor) compositeType ).injectMappingModelPart( idMapping, creationProcess );
|
||||
|
||||
creationProcess.registerInitializationCallback(
|
||||
|
@ -146,56 +147,6 @@ public class VirtualIdEmbeddable implements IdentifierValueMapper {
|
|||
);
|
||||
}
|
||||
|
||||
public VirtualIdEmbeddable(
|
||||
NonAggregatedIdentifierMapping idMapping,
|
||||
EntityMappingType identifiedEntityMapping,
|
||||
Component bootDescriptor,
|
||||
CompositeType compositeType,
|
||||
String rootTableExpression,
|
||||
String[] rootTableKeyColumnNames,
|
||||
MappingModelCreationProcess creationProcess) {
|
||||
this.sessionFactory = creationProcess.getCreationContext().getSessionFactory();
|
||||
|
||||
this.navigableRole = idMapping.getNavigableRole();
|
||||
this.idMapping = idMapping;
|
||||
this.javaType = identifiedEntityMapping.getJavaTypeDescriptor();
|
||||
this.attributeMappings = arrayList( compositeType.getPropertyNames().length );
|
||||
|
||||
this.representationStrategy = new VirtualIdRepresentationStrategy( identifiedEntityMapping );
|
||||
|
||||
( (CompositeTypeImplementor) compositeType ).injectMappingModelPart( getEmbeddedValueMapping(), creationProcess );
|
||||
|
||||
creationProcess.registerInitializationCallback(
|
||||
"EmbeddableMappingType(" + navigableRole.getFullPath() + ")#finishInitialization",
|
||||
() -> {
|
||||
try {
|
||||
final boolean finished = finishInitialization(
|
||||
bootDescriptor,
|
||||
compositeType,
|
||||
rootTableExpression,
|
||||
rootTableKeyColumnNames,
|
||||
creationProcess
|
||||
);
|
||||
|
||||
if ( finished ) {
|
||||
return finished;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
if ( e instanceof NonTransientException ) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
MappingModelCreationLogger.LOGGER.debugf(
|
||||
"EmbeddableMappingType(%s) finalization was not able to complete successfully",
|
||||
navigableRole
|
||||
);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// IdentifierValueMapper
|
||||
|
||||
|
|
Loading…
Reference in New Issue