Implemented @Parent
This commit is contained in:
parent
d3978a0871
commit
b26b397d59
|
@ -8,6 +8,7 @@ package org.hibernate.metamodel.mapping;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
|
@ -46,7 +47,9 @@ public interface EmbeddableValuedModelPart extends ModelPart, Fetchable, Fetchab
|
|||
/**
|
||||
* @see org.hibernate.annotations.Parent
|
||||
*/
|
||||
SingularAttributeMapping getParentInjectionAttributeMapping();
|
||||
default PropertyAccess getParentInjectionAttributePropertyAccess() {
|
||||
return null;
|
||||
}
|
||||
|
||||
Expression toSqlExpression(
|
||||
TableGroup tableGroup,
|
||||
|
|
|
@ -22,9 +22,9 @@ import org.hibernate.metamodel.mapping.EntityMappingType;
|
|||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.property.access.internal.PropertyAccessStrategyBasicImpl;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
|
@ -62,6 +62,7 @@ public class EmbeddedAttributeMapping
|
|||
private final String tableExpression;
|
||||
private final String[] attrColumnNames;
|
||||
private final EmbeddableMappingType embeddableMappingType;
|
||||
private final PropertyAccess parentInjectionAttributeProperyAccess;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public EmbeddedAttributeMapping(
|
||||
|
@ -71,6 +72,7 @@ public class EmbeddedAttributeMapping
|
|||
String tableExpression,
|
||||
String[] attrColumnNames,
|
||||
StateArrayContributorMetadataAccess attributeMetadataAccess,
|
||||
String parentInjectionAttributeName,
|
||||
FetchStrategy mappedFetchStrategy,
|
||||
EmbeddableMappingType embeddableMappingType,
|
||||
ManagedMappingType declaringType,
|
||||
|
@ -83,6 +85,15 @@ public class EmbeddedAttributeMapping
|
|||
declaringType,
|
||||
propertyAccess
|
||||
);
|
||||
if ( parentInjectionAttributeName != null ) {
|
||||
parentInjectionAttributeProperyAccess = PropertyAccessStrategyBasicImpl.INSTANCE.buildPropertyAccess(
|
||||
embeddableMappingType.getMappedJavaTypeDescriptor().getJavaType(),
|
||||
parentInjectionAttributeName
|
||||
);
|
||||
}
|
||||
else {
|
||||
parentInjectionAttributeProperyAccess = null;
|
||||
}
|
||||
this.navigableRole = navigableRole;
|
||||
this.tableExpression = tableExpression;
|
||||
this.attrColumnNames = attrColumnNames;
|
||||
|
@ -99,12 +110,6 @@ public class EmbeddedAttributeMapping
|
|||
return embeddableMappingType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingularAttributeMapping getParentInjectionAttributeMapping() {
|
||||
// todo (6.0) : implement
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContainingTableExpression() {
|
||||
return tableExpression;
|
||||
|
@ -115,6 +120,11 @@ public class EmbeddedAttributeMapping
|
|||
return Arrays.asList( attrColumnNames );
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyAccess getParentInjectionAttributePropertyAccess() {
|
||||
return parentInjectionAttributeProperyAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJdbcTypes(
|
||||
Consumer<JdbcMapping> action,
|
||||
|
|
|
@ -22,9 +22,10 @@ import org.hibernate.metamodel.mapping.JdbcMapping;
|
|||
import org.hibernate.metamodel.mapping.MappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.property.access.internal.PropertyAccessStrategyBasicImpl;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
|
@ -59,7 +60,7 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
|
|||
|
||||
private final String containingTableExpression;
|
||||
|
||||
private final SingularAttributeMapping parentInjectionAttribute;
|
||||
private final PropertyAccess parentInjectionAttributeProperyAccess;
|
||||
private final List<String> columnExpressions;
|
||||
private final String sqlAliasStem;
|
||||
|
||||
|
@ -68,15 +69,24 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
|
|||
CollectionPersister collectionDescriptor,
|
||||
Nature nature,
|
||||
EmbeddableMappingType embeddableMappingType,
|
||||
SingularAttributeMapping parentInjectionAttribute,
|
||||
String parentInjectionAttributeName,
|
||||
String containingTableExpression,
|
||||
List<String> columnExpressions,
|
||||
String sqlAliasStem) {
|
||||
this.navigableRole = collectionDescriptor.getNavigableRole().appendContainer( nature.getName() );
|
||||
this.collectionDescriptor = collectionDescriptor;
|
||||
this.nature = nature;
|
||||
if ( parentInjectionAttributeName != null ) {
|
||||
parentInjectionAttributeProperyAccess = PropertyAccessStrategyBasicImpl.INSTANCE.buildPropertyAccess(
|
||||
embeddableMappingType.getMappedJavaTypeDescriptor().getJavaType(),
|
||||
parentInjectionAttributeName
|
||||
);
|
||||
}
|
||||
else {
|
||||
parentInjectionAttributeProperyAccess = null;
|
||||
}
|
||||
this.embeddableMappingType = embeddableMappingType;
|
||||
this.parentInjectionAttribute = parentInjectionAttribute;
|
||||
|
||||
this.containingTableExpression = containingTableExpression;
|
||||
this.columnExpressions = columnExpressions;
|
||||
this.sqlAliasStem = sqlAliasStem;
|
||||
|
@ -108,8 +118,8 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
|
|||
}
|
||||
|
||||
@Override
|
||||
public SingularAttributeMapping getParentInjectionAttributeMapping() {
|
||||
return parentInjectionAttribute;
|
||||
public PropertyAccess getParentInjectionAttributePropertyAccess() {
|
||||
return parentInjectionAttributeProperyAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -413,8 +413,9 @@ public class MappingModelCreationHelper {
|
|||
creationProcess
|
||||
);
|
||||
|
||||
final Component component = (Component) bootProperty.getValue();
|
||||
final EmbeddableMappingType embeddableMappingType = EmbeddableMappingType.from(
|
||||
(Component) bootProperty.getValue(),
|
||||
component,
|
||||
attrType,
|
||||
attributeMappingType -> new EmbeddedAttributeMapping(
|
||||
attrName,
|
||||
|
@ -423,6 +424,7 @@ public class MappingModelCreationHelper {
|
|||
tableExpression,
|
||||
attrColumnNames,
|
||||
attributeMetadataAccess,
|
||||
component.getParentProperty(),
|
||||
FetchStrategy.IMMEDIATE_JOIN,
|
||||
attributeMappingType,
|
||||
declaringType,
|
||||
|
@ -1115,7 +1117,7 @@ public class MappingModelCreationHelper {
|
|||
CollectionPart.Nature.INDEX,
|
||||
inflightDescriptor,
|
||||
// parent-injection
|
||||
null,
|
||||
component.getParentProperty(),
|
||||
tableExpression,
|
||||
columnExpressions,
|
||||
sqlAliasStem
|
||||
|
@ -1206,7 +1208,7 @@ public class MappingModelCreationHelper {
|
|||
CollectionPart.Nature.ELEMENT,
|
||||
embeddableMappingType,
|
||||
// parent-injection
|
||||
null,
|
||||
component.getParentProperty(),
|
||||
tableExpression,
|
||||
columnExpressions,
|
||||
sqlAliasStem
|
||||
|
|
|
@ -9,16 +9,20 @@ package org.hibernate.sql.results.graph.embeddable;
|
|||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMapping;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.results.graph.AbstractFetchParentAccess;
|
||||
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
||||
import org.hibernate.sql.results.graph.DomainResultAssembler;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
import org.hibernate.sql.results.graph.FetchParentAccess;
|
||||
import org.hibernate.sql.results.graph.Initializer;
|
||||
import org.hibernate.sql.results.graph.collection.CollectionInitializer;
|
||||
import org.hibernate.sql.results.graph.entity.EntityInitializer;
|
||||
import org.hibernate.sql.results.internal.NullValueAssembler;
|
||||
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
||||
|
||||
|
@ -28,7 +32,7 @@ import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
|||
public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentAccess implements EmbeddableInitializer {
|
||||
private final NavigablePath navigablePath;
|
||||
private final EmbeddableValuedModelPart embeddedModelPartDescriptor;
|
||||
private final FetchParentAccess fetchParentAccess;
|
||||
private FetchParentAccess fetchParentAccess;
|
||||
|
||||
private final Map<StateArrayContributorMapping, DomainResultAssembler> assemblerMap;
|
||||
|
||||
|
@ -92,26 +96,27 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
|
|||
// todo (6.0) : register "parent resolution listener" if the composite is defined for `@Parent`
|
||||
// something like:
|
||||
|
||||
final SingularAttributeMapping parentInjectionTarget = embeddedModelPartDescriptor.getParentInjectionAttributeMapping();
|
||||
final PropertyAccess parentInjectionPropertyAccess = embeddedModelPartDescriptor.getParentInjectionAttributePropertyAccess();
|
||||
|
||||
if ( parentInjectionTarget != null ) {
|
||||
getFetchParentAccess().findFirstEntityDescriptorAccess().registerResolutionListener(
|
||||
// todo (6.0) : this is the legacy behavior
|
||||
// - the first entity is injected as the parent, even if the composite
|
||||
// is defined on another composite
|
||||
owner -> {
|
||||
if ( compositeInstance == null ) {
|
||||
return;
|
||||
if ( parentInjectionPropertyAccess != null ) {
|
||||
if ( getFetchParentAccess() != null ) {
|
||||
getFetchParentAccess().findFirstEntityDescriptorAccess().registerResolutionListener(
|
||||
// todo (6.0) : this is the legacy behavior
|
||||
// - the first entity is injected as the parent, even if the composite
|
||||
// is defined on another composite
|
||||
owner -> {
|
||||
if ( compositeInstance == null ) {
|
||||
return;
|
||||
}
|
||||
parentInjectionPropertyAccess.getSetter().set(
|
||||
compositeInstance,
|
||||
owner,
|
||||
rowProcessingState.getSession().getFactory()
|
||||
);
|
||||
}
|
||||
parentInjectionTarget.getPropertyAccess().getSetter().set(
|
||||
compositeInstance,
|
||||
owner,
|
||||
rowProcessingState.getSession().getFactory()
|
||||
);
|
||||
}
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -130,6 +135,33 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
|
|||
@Override
|
||||
public void initializeInstance(RowProcessingState rowProcessingState) {
|
||||
|
||||
final PropertyAccess parentInjectionPropertyAccess = embeddedModelPartDescriptor.getParentInjectionAttributePropertyAccess();
|
||||
|
||||
if ( parentInjectionPropertyAccess != null && getFetchParentAccess() == null ) {
|
||||
Initializer initializer = rowProcessingState.resolveInitializer( navigablePath.getParent() );
|
||||
final Object owner;
|
||||
if ( initializer instanceof CollectionInitializer ) {
|
||||
owner = ( (CollectionInitializer) initializer ).getCollectionInstance().getOwner();
|
||||
}
|
||||
else if ( initializer instanceof EntityInitializer ) {
|
||||
owner = ( (EntityInitializer) initializer ).getEntityInstance();
|
||||
|
||||
parentInjectionPropertyAccess.getSetter().set(
|
||||
compositeInstance,
|
||||
owner,
|
||||
rowProcessingState.getSession().getFactory()
|
||||
);
|
||||
}
|
||||
else {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
parentInjectionPropertyAccess.getSetter().set(
|
||||
compositeInstance,
|
||||
owner,
|
||||
rowProcessingState.getSession().getFactory()
|
||||
);
|
||||
}
|
||||
|
||||
EmbeddableLoadingLogger.INSTANCE.debugf(
|
||||
"Initializing composite instance [%s] : %s",
|
||||
navigablePath,
|
||||
|
|
|
@ -484,7 +484,6 @@ public class EmbeddedTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected(reason = "@Parent annotation mapping has not yet been implemented")
|
||||
public void testParent(SessionFactoryScope scope) {
|
||||
Book book = new Book();
|
||||
scope.inTransaction(
|
||||
|
|
Loading…
Reference in New Issue