HHH-16732 make HQL id() function work for @Any mappings

This commit is contained in:
Gavin 2023-06-01 00:34:21 +02:00 committed by Gavin King
parent 2287f3ce3b
commit 8cc7eb7a66
5 changed files with 52 additions and 20 deletions

View File

@ -8,7 +8,6 @@ package org.hibernate.metamodel.mapping.internal;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.FetchStyle;

View File

@ -107,6 +107,7 @@ import org.hibernate.query.sqm.tree.cte.SqmCteContainer;
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
import org.hibernate.query.sqm.tree.domain.AbstractSqmFrom;
import org.hibernate.query.sqm.tree.domain.SqmAnyValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmCorrelation;
import org.hibernate.query.sqm.tree.domain.SqmCteRoot;
import org.hibernate.query.sqm.tree.domain.SqmDerivedRoot;
@ -2748,21 +2749,23 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
@Override
public SqmPath<?> visitEntityIdReference(HqlParser.EntityIdReferenceContext ctx) {
if ( ctx.getChildCount() == 5 ) {
throw new UnsupportedOperationException( "Path continuation from `id()` reference not yet implemented" );
}
final SqmPath<Object> sqmPath = consumeDomainPath( (HqlParser.PathContext) ctx.getChild( 2 ) );
final DomainType<?> sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType();
if ( sqmPathType instanceof IdentifiableDomainType<?> ) {
final SqmPathSource<?> identifierDescriptor = ( (IdentifiableDomainType<?>) sqmPathType ).getIdentifierDescriptor();
final SqmPath<?> idPath = sqmPath.get( identifierDescriptor.getPathName() );
if ( ctx.getChildCount() != 5 ) {
return idPath;
}
throw new UnsupportedOperationException( "Path continuation from `id()` reference not yet implemented" );
return sqmPath.get( identifierDescriptor.getPathName() );
}
else if ( sqmPath instanceof SqmAnyValuedSimplePath<?> ) {
return sqmPath.resolvePathPart("id", true, getCurrentProcessingState().getCreationState() );
}
else {
throw new SemanticException( "Path does not resolve to an entity type '" + sqmPath.getNavigablePath() + "'" );
}
throw new SemanticException( "Path does not resolve to an entity type '" + sqmPath.getNavigablePath() + "'" );
}
@Override

View File

@ -22,19 +22,19 @@ import org.hibernate.MappingException;
import org.hibernate.PropertyNotFoundException;
import org.hibernate.TransientObjectException;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.engine.internal.ForeignKeys;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadeStyles;
import org.hibernate.engine.spi.Mapping;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.type.spi.TypeConfiguration;
import static org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved;
import static org.hibernate.internal.util.collections.ArrayHelper.join;
import static org.hibernate.pretty.MessageHelper.infoString;
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
@ -79,7 +79,7 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
@Override
public int[] getSqlTypeCodes(Mapping mapping) throws MappingException {
return ArrayHelper.join( discriminatorType.getSqlTypeCodes( mapping ), identifierType.getSqlTypeCodes( mapping ) );
return join( discriminatorType.getSqlTypeCodes( mapping ), identifierType.getSqlTypeCodes( mapping ) );
}
@Override
@ -246,7 +246,7 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
}
else {
entityName = session.bestGuessEntityName( value );
id = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, value, session );
id = getEntityIdentifierIfNotUnsaved( entityName, value, session );
}
// discriminatorType is assumed to be single-column type
@ -295,7 +295,7 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
else {
return new ObjectTypeCacheEntry(
session.bestGuessEntityName( value ),
ForeignKeys.getEntityIdentifierIfNotUnsaved(
getEntityIdentifierIfNotUnsaved(
session.bestGuessEntityName( value ),
value,
session
@ -317,7 +317,7 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
}
else {
final String entityName = session.bestGuessEntityName( original );
final Object id = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, original, session );
final Object id = getEntityIdentifierIfNotUnsaved( entityName, original, session );
return session.internalLoad( entityName, id, eager, false );
}
}
@ -365,7 +365,7 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
private Object getIdentifier(Object value, SharedSessionContractImplementor session) throws HibernateException {
try {
return ForeignKeys.getEntityIdentifierIfNotUnsaved(
return getEntityIdentifierIfNotUnsaved(
session.bestGuessEntityName( value ),
value,
session
@ -469,9 +469,10 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
}
public boolean equals(Object object) {
if (object instanceof ObjectTypeCacheEntry) {
ObjectTypeCacheEntry objectTypeCacheEntry = (ObjectTypeCacheEntry)object;
return Objects.equals( objectTypeCacheEntry.entityName, entityName ) && Objects.equals( objectTypeCacheEntry.id, id );
if ( object instanceof ObjectTypeCacheEntry ) {
final ObjectTypeCacheEntry objectTypeCacheEntry = (ObjectTypeCacheEntry) object;
return Objects.equals( objectTypeCacheEntry.entityName, entityName )
&& Objects.equals( objectTypeCacheEntry.id, id );
}
return false;
}

View File

@ -131,6 +131,24 @@ public class AnyTest {
);
}
@Test
@TestForIssue( jiraKey = "HHH-16732")
public void testHqlAnyIdQuery(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
List<PropertySet> list1 = session.createQuery(
"select p from PropertyHolder p where id(p.property) = 666",
PropertySet.class ).list();
assertEquals( 0, list1.size() );
List<PropertySet> list2 = session.createQuery(
"select p from PropertyHolder p where type(p.property) = IntegerProperty",
PropertySet.class ).list();
assertEquals( 1, list2.size() );
}
);
}
@Test
@TestForIssue( jiraKey = "HHH-15323")
public void testHqlCollectionTypeQuery(SessionFactoryScope scope) {

View File

@ -82,6 +82,17 @@ public class EmbeddedAnyTest {
);
}
@Test
@TestForIssue( jiraKey = "HHH-16732")
public void testEmbeddedIdHql(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final List<Foo> foos = session.createQuery( "from Foo f where id(f.fooEmbedded.bar) = 1", Foo.class )
.list();
}
);
}
@Test
@TestForIssue( jiraKey = "HHH-15323")
public void testEmbeddedTypeHql(SessionFactoryScope scope) {