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