HHH-16997 Embedded components in HibernateProxy are not initialized when entity has reference to another entity of the same type + HHH-16901 Embedded field in entity association from composite key not correctly instantiated
This commit is contained in:
parent
7cb00f3521
commit
22535bbd92
|
@ -170,7 +170,7 @@ public abstract class AbstractPluralAttribute<D, C, E>
|
|||
"`lhs` cannot be null for a sub-navigable reference - " + getName()
|
||||
);
|
||||
}
|
||||
final SqmPathSource<?> parentPathSource = parent.getReferencedPathSource();
|
||||
final SqmPathSource<?> parentPathSource = parent.getResolvedModel();
|
||||
NavigablePath navigablePath = parent.getNavigablePath();
|
||||
if ( parentPathSource instanceof PluralPersistentAttribute<?, ?, ?> ) {
|
||||
navigablePath = navigablePath.append( CollectionPart.Nature.ELEMENT.getName() );
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.metamodel.model.domain.internal;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||
import org.hibernate.query.sqm.SqmJoinable;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
|
@ -47,7 +48,9 @@ public class EmbeddedSqmPathSource<J>
|
|||
@Override
|
||||
public SqmPath<J> createSqmPath(SqmPath<?> lhs, SqmPathSource<?> intermediatePathSource) {
|
||||
return new SqmEmbeddedValuedSimplePath<>(
|
||||
PathHelper.append( lhs, this, intermediatePathSource ),
|
||||
pathModel instanceof SqmJoinable<?, ?>
|
||||
? ( (SqmJoinable<?, ?>) pathModel ).createNavigablePath( lhs, null )
|
||||
: PathHelper.append( lhs, this, intermediatePathSource ),
|
||||
pathModel,
|
||||
lhs,
|
||||
lhs.nodeBuilder()
|
||||
|
|
|
@ -173,7 +173,7 @@ public class SingularAttributeImpl<D,J>
|
|||
"LHS cannot be null for a sub-navigable reference - " + getName()
|
||||
);
|
||||
}
|
||||
final SqmPathSource<?> parentPathSource = parent.getReferencedPathSource();
|
||||
final SqmPathSource<?> parentPathSource = parent.getResolvedModel();
|
||||
NavigablePath navigablePath = parent.getNavigablePath();
|
||||
if ( parentPathSource instanceof PluralPersistentAttribute<?, ?, ?> ) {
|
||||
navigablePath = navigablePath.append( CollectionPart.Nature.ELEMENT.getName() );
|
||||
|
@ -224,7 +224,7 @@ public class SingularAttributeImpl<D,J>
|
|||
);
|
||||
}
|
||||
NavigablePath navigablePath = parent.getNavigablePath();
|
||||
if ( parent.getReferencedPathSource() instanceof PluralPersistentAttribute<?, ?, ?> ) {
|
||||
if ( parent.getResolvedModel() instanceof PluralPersistentAttribute<?, ?, ?> ) {
|
||||
navigablePath = navigablePath.append( CollectionPart.Nature.ELEMENT.getName() );
|
||||
}
|
||||
if ( getDeclaringType() instanceof IdentifiableDomainType<?> ) {
|
||||
|
|
|
@ -53,7 +53,7 @@ public class SqmCreationHelper {
|
|||
);
|
||||
}
|
||||
NavigablePath navigablePath = lhs.getNavigablePath();
|
||||
if ( lhs.getReferencedPathSource() instanceof PluralPersistentAttribute<?, ?, ?>
|
||||
if ( lhs.getResolvedModel() instanceof PluralPersistentAttribute<?, ?, ?>
|
||||
&& CollectionPart.Nature.fromName( subNavigable ) == null ) {
|
||||
navigablePath = navigablePath.append( CollectionPart.Nature.ELEMENT.getName() );
|
||||
}
|
||||
|
|
|
@ -5049,7 +5049,11 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
return expression;
|
||||
}
|
||||
final BasicValuedPathInterpretation<?> basicPath = (BasicValuedPathInterpretation<?>) expression;
|
||||
final AbstractEntityPersister persister = (AbstractEntityPersister) basicPath.getTableGroup().getModelPart().getPartMappingType();
|
||||
final TableGroup tableGroup = basicPath.getTableGroup();
|
||||
final TableGroup elementTableGroup = tableGroup instanceof PluralTableGroup
|
||||
? ( (PluralTableGroup) tableGroup ).getElementTableGroup()
|
||||
: tableGroup;
|
||||
final AbstractEntityPersister persister = (AbstractEntityPersister) elementTableGroup.getModelPart().getPartMappingType();
|
||||
// Only need a case expression around the basic valued path for the parent treat expression
|
||||
// if the column of the basic valued path is shared between subclasses
|
||||
if ( persister.isSharedColumn( basicPath.getColumnReference().getColumnExpression() ) ) {
|
||||
|
|
|
@ -103,6 +103,11 @@ public class SqmTreatedBagJoin<O,T, S extends T> extends SqmBagJoin<O,S> impleme
|
|||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource<?> getResolvedModel() {
|
||||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmAttributeJoin<O, S> makeCopy(SqmCreationProcessingState creationProcessingState) {
|
||||
return new SqmTreatedBagJoin<>( wrappedPath, treatTarget, getAlias() );
|
||||
|
|
|
@ -91,8 +91,12 @@ public class SqmTreatedCrossJoin<T, S extends T> extends SqmCrossJoin<S> impleme
|
|||
|
||||
@Override
|
||||
public EntityDomainType<S> getReferencedPathSource() {
|
||||
//noinspection unchecked
|
||||
return (EntityDomainType<S>) wrappedPath.getReferencedPathSource();
|
||||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource<?> getResolvedModel() {
|
||||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -77,6 +77,11 @@ public class SqmTreatedEntityJoin<T, S extends T> extends SqmEntityJoin<S> imple
|
|||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityDomainType<S> getModel() {
|
||||
return getTreatTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath<T> getWrappedPath() {
|
||||
return wrappedPath;
|
||||
|
|
|
@ -102,6 +102,11 @@ public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> imple
|
|||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource<?> getResolvedModel() {
|
||||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath<?> resolveIndexedAccess(
|
||||
SqmExpression<?> selector,
|
||||
|
|
|
@ -98,6 +98,11 @@ public class SqmTreatedMapJoin<O, K, V, S extends V> extends SqmMapJoin<O, K, S>
|
|||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource<?> getResolvedModel() {
|
||||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmMapJoin<O, K, S> makeCopy(SqmCreationProcessingState creationProcessingState) {
|
||||
return new SqmTreatedMapJoin<>(
|
||||
|
|
|
@ -91,6 +91,16 @@ public class SqmTreatedPluralPartJoin<O,T, S extends T> extends SqmPluralPartJoi
|
|||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource<S> getReferencedPathSource() {
|
||||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource<?> getResolvedModel() {
|
||||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHqlString(StringBuilder sb) {
|
||||
sb.append( "treat(" );
|
||||
|
|
|
@ -100,6 +100,11 @@ public class SqmTreatedSetJoin<O,T, S extends T> extends SqmSetJoin<O,S> impleme
|
|||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource<?> getResolvedModel() {
|
||||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmAttributeJoin<O, S> makeCopy(SqmCreationProcessingState creationProcessingState) {
|
||||
return new SqmTreatedSetJoin<>( wrappedPath, treatTarget, getAlias() );
|
||||
|
|
|
@ -109,6 +109,16 @@ public class SqmTreatedSimplePath<T, S extends T>
|
|||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource<S> getReferencedPathSource() {
|
||||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource<?> getResolvedModel() {
|
||||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S1 extends S> SqmTreatedSimplePath<S,S1> treatAs(Class<S1> treatJavaType) throws PathException {
|
||||
return super.treatAs( treatJavaType );
|
||||
|
|
|
@ -97,7 +97,12 @@ public class SqmTreatedSingularJoin<O,T, S extends T> extends SqmSingularJoin<O,
|
|||
|
||||
@Override
|
||||
public EntityDomainType<S> getReferencedPathSource() {
|
||||
return getTreatTarget();
|
||||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource<?> getResolvedModel() {
|
||||
return treatTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,13 +8,14 @@ package org.hibernate.sql.results.graph.embeddable;
|
|||
|
||||
import org.hibernate.engine.internal.ManagedTypeHelper;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.internal.AbstractCompositeIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||
import org.hibernate.metamodel.mapping.VirtualModelPart;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.EmbeddedIdentifierMappingImpl;
|
||||
import org.hibernate.metamodel.spi.ValueAccess;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
|
@ -68,31 +69,20 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
|
|||
final int size = embeddableTypeDescriptor.getNumberOfFetchables();
|
||||
this.rowState = new Object[ size ];
|
||||
|
||||
this.isPartOfKey = isPartOfKey( embedded, navigablePath );
|
||||
this.isPartOfKey = isPartOfKey( embedded, navigablePath, fetchParentAccess );
|
||||
// We never want to create empty composites for the FK target or PK, otherwise collections would break
|
||||
this.createEmptyCompositesEnabled = !isPartOfKey && embeddableTypeDescriptor.isCreateEmptyCompositesEnabled();
|
||||
|
||||
this.sessionFactory = creationState.getSqlAstCreationContext().getSessionFactory();
|
||||
this.assemblers = createAssemblers( resultDescriptor, creationState, embeddableTypeDescriptor );
|
||||
}
|
||||
|
||||
private static boolean isPartOfKey(EmbeddableValuedModelPart modelPart, NavigablePath navigablePath) {
|
||||
private static boolean isPartOfKey(EmbeddableValuedModelPart modelPart, NavigablePath navigablePath, FetchParentAccess fetchParentAccess) {
|
||||
return modelPart.isEntityIdentifierMapping()
|
||||
|| isPartOfKey( navigablePath )
|
||||
|| modelPart.getNavigableRole() != null && isPartOfKey( modelPart.getNavigableRole() );
|
||||
}
|
||||
|
||||
private static boolean isPartOfKey(NavigablePath navigablePath) {
|
||||
return ForeignKeyDescriptor.PART_NAME.equals( navigablePath.getLocalName() )
|
||||
|| ForeignKeyDescriptor.PART_NAME.equals( navigablePath.getLocalName() )
|
||||
|| ForeignKeyDescriptor.TARGET_PART_NAME.equals( navigablePath.getLocalName() )
|
||||
|| navigablePath instanceof EntityIdentifierNavigablePath
|
||||
|| navigablePath.getParent().getParent() != null && isPartOfKey( navigablePath.getParent() );
|
||||
}
|
||||
|
||||
private static boolean isPartOfKey(NavigableRole navigableRole) {
|
||||
final NavigableRole parent = navigableRole.getParent();
|
||||
return parent != null
|
||||
&& ( parent.getLocalName().equals( EntityIdentifierMapping.ID_ROLE_NAME ) || isPartOfKey( parent ) );
|
||||
|| fetchParentAccess != null && fetchParentAccess.isEmbeddableInitializer()
|
||||
&& ( (AbstractEmbeddableInitializer) fetchParentAccess ).isPartOfKey;
|
||||
}
|
||||
|
||||
protected DomainResultAssembler<?>[] createAssemblers(
|
||||
|
|
|
@ -74,6 +74,7 @@ public class EmbeddableAscDescQueryTest {
|
|||
public void tearDown(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.createMutationQuery( "update EntityA a set a.componentA.entityA = null" ).executeUpdate();
|
||||
session.createMutationQuery( "delete from EntityB" ).executeUpdate();
|
||||
session.createMutationQuery( "delete from EntityC" ).executeUpdate();
|
||||
session.createMutationQuery( "delete from EntityA" ).executeUpdate();
|
||||
|
|
Loading…
Reference in New Issue