HHH-18125 Support for `type()` and `treat()` operators for Embeddables
This commit is contained in:
parent
11384ab917
commit
2e9acf1ded
|
@ -543,8 +543,8 @@ The following special functions make it possible to discover or narrow expressio
|
||||||
|===
|
|===
|
||||||
| Special function | Purpose | Signature | JPA standard
|
| Special function | Purpose | Signature | JPA standard
|
||||||
|
|
||||||
| `type()` | The (concrete) entity type | `type(e)` | ✔
|
| `type()` | The (concrete) entity or embeddable type | `type(e)` | ✔
|
||||||
| `treat()` | Narrow an entity type | `treat(e as Entity)` | ✔
|
| `treat()` | Narrow an entity or embeddable type | `treat(e as Entity)` | ✔
|
||||||
| `cast()` | Narrow a basic type | `cast(x as Type)` | ✖
|
| `cast()` | Narrow a basic type | `cast(x as Type)` | ✖
|
||||||
| `str()` | Cast to a string | `str(x)` | ✖
|
| `str()` | Cast to a string | `str(x)` | ✖
|
||||||
|===
|
|===
|
||||||
|
@ -555,7 +555,7 @@ Let's see what these functions do.
|
||||||
[discrete]
|
[discrete]
|
||||||
===== Evaluating an entity type
|
===== Evaluating an entity type
|
||||||
|
|
||||||
The function `type()`, applied to an identification variable or entity-valued path expression, evaluates to the concrete type, that is, the Java `Class`, of the referenced entity.
|
The function `type()`, applied to an identification variable or to an entity-valued or embeddable-valued path expression, evaluates to the concrete type, that is, the Java `Class`, of the referenced entity or embeddable.
|
||||||
This is mainly useful when dealing with entity inheritance hierarchies.
|
This is mainly useful when dealing with entity inheritance hierarchies.
|
||||||
|
|
||||||
[[entity-type-exp-example]]
|
[[entity-type-exp-example]]
|
||||||
|
@ -571,7 +571,7 @@ where type(payment) = CreditCardPayment
|
||||||
===== Narrowing an entity type
|
===== Narrowing an entity type
|
||||||
|
|
||||||
The function `treat()` may be used to narrow the type of an identification variable.
|
The function `treat()` may be used to narrow the type of an identification variable.
|
||||||
This is useful when dealing with entity inheritance hierarchies.
|
This is useful when dealing with entity or embeddable inheritance hierarchies.
|
||||||
|
|
||||||
[[treat-example]]
|
[[treat-example]]
|
||||||
[source, hql]
|
[source, hql]
|
||||||
|
|
|
@ -395,7 +395,7 @@ It's possible to customize the discriminator column mapping:
|
||||||
* For the whole `@Embeddable` type, by using `@DiscriminatorColumn` or `@DiscriminatorFormula` on the *root* class of the inheritance hierarchy
|
* For the whole `@Embeddable` type, by using `@DiscriminatorColumn` or `@DiscriminatorFormula` on the *root* class of the inheritance hierarchy
|
||||||
(NOTE: if using the same inheritance-enabled embeddable type for two different properties in the same entity mapping,
|
(NOTE: if using the same inheritance-enabled embeddable type for two different properties in the same entity mapping,
|
||||||
this will cause a column name conflict);
|
this will cause a column name conflict);
|
||||||
* For a specific `@Embedded` property, by using the `@AttributeOverride` annotation with the special name `{discriminator}`.
|
* For a specific `@Embedded` property, by using the `@AttributeOverride` annotation with the special name `+{discriminator}+`.
|
||||||
|
|
||||||
Finally, to specify custom discriminator values for each subtype one can annotate the inheritance hierarchy's
|
Finally, to specify custom discriminator values for each subtype one can annotate the inheritance hierarchy's
|
||||||
classes with `@DiscriminatorValue`.
|
classes with `@DiscriminatorValue`.
|
||||||
|
@ -407,6 +407,8 @@ Embeddable inheritance is *NOT* supported for `@EmbeddedId`, embeddable types us
|
||||||
and embedded properties using a custom `@CompositeType`.
|
and embedded properties using a custom `@CompositeType`.
|
||||||
====
|
====
|
||||||
|
|
||||||
|
Note that the `type()` and `treat()` functions are also supported for embeddable inheritance, see <<chapters/jndi/QueryLanguage.adoc#hql-functions-typecasts,types and typecasts>>.
|
||||||
|
|
||||||
[[embeddable-inheritance-example]]
|
[[embeddable-inheritance-example]]
|
||||||
.Example mapping of an embeddable inheritance hierarchy
|
.Example mapping of an embeddable inheritance hierarchy
|
||||||
[source,java]
|
[source,java]
|
||||||
|
|
|
@ -750,8 +750,8 @@ The following special functions make it possible to discover or narrow expressio
|
||||||
|===
|
|===
|
||||||
| Special function | Purpose | Signature | JPA standard
|
| Special function | Purpose | Signature | JPA standard
|
||||||
|
|
||||||
| `type()` | The (concrete) entity name | `type(e)` | ✓
|
| `type()` | The (concrete) entity or embeddable type | `type(e)` | ✓
|
||||||
| `treat()` | Narrow an entity type | `treat(e as Entity)` | ✓
|
| `treat()` | Narrow an entity or embeddable type | `treat(e as Entity)` | ✓
|
||||||
| `cast()` | Narrow a basic type | `cast(x as Type)` | ✗
|
| `cast()` | Narrow a basic type | `cast(x as Type)` | ✗
|
||||||
| `str()` | Cast to a string | `str(x)` | ✗
|
| `str()` | Cast to a string | `str(x)` | ✗
|
||||||
|===
|
|===
|
||||||
|
@ -761,7 +761,7 @@ Let's see what these functions do.
|
||||||
[[hql-function-type]]
|
[[hql-function-type]]
|
||||||
===== `type()`
|
===== `type()`
|
||||||
|
|
||||||
The function `type()`, applied to an identification variable, evaluates to the entity name of the referenced entity.
|
The function `type()`, applied to an identification variable or to an entity-valued or embeddable-valued path expression, evaluates to the concrete type, that is, the Java `Class`, of the referenced entity or embeddable.
|
||||||
This is mainly useful when dealing with entity inheritance hierarchies.
|
This is mainly useful when dealing with entity inheritance hierarchies.
|
||||||
|
|
||||||
[[hql-entity-type-exp-example]]
|
[[hql-entity-type-exp-example]]
|
||||||
|
@ -777,7 +777,7 @@ include::{example-dir-hql}/HQLTest.java[tags=hql-entity-type-exp-example]
|
||||||
===== `treat()`
|
===== `treat()`
|
||||||
|
|
||||||
The function `treat()` may be used to narrow the type of an identification variable.
|
The function `treat()` may be used to narrow the type of an identification variable.
|
||||||
This is useful when dealing with entity inheritance hierarchies.
|
This is useful when dealing with entity or embeddable inheritance hierarchies.
|
||||||
|
|
||||||
[[hql-treat-example]]
|
[[hql-treat-example]]
|
||||||
====
|
====
|
||||||
|
|
|
@ -18,6 +18,7 @@ import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.DuplicateMappingException;
|
import org.hibernate.DuplicateMappingException;
|
||||||
|
@ -95,6 +96,7 @@ import org.hibernate.mapping.RootClass;
|
||||||
import org.hibernate.mapping.SimpleValue;
|
import org.hibernate.mapping.SimpleValue;
|
||||||
import org.hibernate.mapping.Table;
|
import org.hibernate.mapping.Table;
|
||||||
import org.hibernate.metamodel.CollectionClassification;
|
import org.hibernate.metamodel.CollectionClassification;
|
||||||
|
import org.hibernate.metamodel.mapping.DiscriminatorType;
|
||||||
import org.hibernate.metamodel.spi.EmbeddableInstantiator;
|
import org.hibernate.metamodel.spi.EmbeddableInstantiator;
|
||||||
import org.hibernate.query.named.NamedObjectRepository;
|
import org.hibernate.query.named.NamedObjectRepository;
|
||||||
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
|
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
|
||||||
|
@ -136,6 +138,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
||||||
private final List<Component> composites = new ArrayList<>();
|
private final List<Component> composites = new ArrayList<>();
|
||||||
private final Map<Class<?>, Component> genericComponentsMap = new HashMap<>();
|
private final Map<Class<?>, Component> genericComponentsMap = new HashMap<>();
|
||||||
private final Map<XClass, List<XClass>> embeddableSubtypes = new HashMap<>();
|
private final Map<XClass, List<XClass>> embeddableSubtypes = new HashMap<>();
|
||||||
|
private final Map<Class<?>, DiscriminatorType<?>> embeddableDiscriminatorTypesMap = new HashMap<>();
|
||||||
private final Map<String,Collection> collectionBindingMap = new HashMap<>();
|
private final Map<String,Collection> collectionBindingMap = new HashMap<>();
|
||||||
|
|
||||||
private final Map<String, FilterDefinition> filterDefinitionMap = new HashMap<>();
|
private final Map<String, FilterDefinition> filterDefinitionMap = new HashMap<>();
|
||||||
|
@ -296,6 +299,13 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
||||||
return subclasses != null ? subclasses : List.of();
|
return subclasses != null ? subclasses : List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiscriminatorType<?> resolveEmbeddableDiscriminatorType(
|
||||||
|
Class<?> embeddableClass,
|
||||||
|
Supplier<DiscriminatorType<?>> supplier) {
|
||||||
|
return embeddableDiscriminatorTypesMap.computeIfAbsent( embeddableClass, k -> supplier.get() );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SessionFactoryBuilder getSessionFactoryBuilder() {
|
public SessionFactoryBuilder getSessionFactoryBuilder() {
|
||||||
throw new UnsupportedOperationException(
|
throw new UnsupportedOperationException(
|
||||||
|
@ -2072,6 +2082,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
||||||
entityBindingMap,
|
entityBindingMap,
|
||||||
composites,
|
composites,
|
||||||
genericComponentsMap,
|
genericComponentsMap,
|
||||||
|
embeddableDiscriminatorTypesMap,
|
||||||
mappedSuperClasses,
|
mappedSuperClasses,
|
||||||
collectionBindingMap,
|
collectionBindingMap,
|
||||||
typeDefRegistry.copyRegistrationMap(),
|
typeDefRegistry.copyRegistrationMap(),
|
||||||
|
|
|
@ -16,6 +16,7 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
@ -60,6 +61,7 @@ import org.hibernate.mapping.Property;
|
||||||
import org.hibernate.mapping.Table;
|
import org.hibernate.mapping.Table;
|
||||||
import org.hibernate.mapping.UserDefinedObjectType;
|
import org.hibernate.mapping.UserDefinedObjectType;
|
||||||
import org.hibernate.mapping.UserDefinedType;
|
import org.hibernate.mapping.UserDefinedType;
|
||||||
|
import org.hibernate.metamodel.mapping.DiscriminatorType;
|
||||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||||
import org.hibernate.query.internal.NamedObjectRepositoryImpl;
|
import org.hibernate.query.internal.NamedObjectRepositoryImpl;
|
||||||
import org.hibernate.query.named.NamedObjectRepository;
|
import org.hibernate.query.named.NamedObjectRepository;
|
||||||
|
@ -91,6 +93,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
||||||
private final Map<String,PersistentClass> entityBindingMap;
|
private final Map<String,PersistentClass> entityBindingMap;
|
||||||
private final List<Component> composites;
|
private final List<Component> composites;
|
||||||
private final Map<Class<?>, Component> genericComponentsMap;
|
private final Map<Class<?>, Component> genericComponentsMap;
|
||||||
|
private final Map<Class<?>, DiscriminatorType<?>> embeddableDiscriminatorTypesMap;
|
||||||
private final Map<Class<?>, MappedSuperclass> mappedSuperclassMap;
|
private final Map<Class<?>, MappedSuperclass> mappedSuperclassMap;
|
||||||
private final Map<String,Collection> collectionBindingMap;
|
private final Map<String,Collection> collectionBindingMap;
|
||||||
private final Map<String, TypeDefinition> typeDefinitionMap;
|
private final Map<String, TypeDefinition> typeDefinitionMap;
|
||||||
|
@ -112,6 +115,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
||||||
Map<String, PersistentClass> entityBindingMap,
|
Map<String, PersistentClass> entityBindingMap,
|
||||||
List<Component> composites,
|
List<Component> composites,
|
||||||
Map<Class<?>, Component> genericComponentsMap,
|
Map<Class<?>, Component> genericComponentsMap,
|
||||||
|
Map<Class<?>, DiscriminatorType<?>> embeddableDiscriminatorTypesMap,
|
||||||
Map<Class<?>, MappedSuperclass> mappedSuperclassMap,
|
Map<Class<?>, MappedSuperclass> mappedSuperclassMap,
|
||||||
Map<String, Collection> collectionBindingMap,
|
Map<String, Collection> collectionBindingMap,
|
||||||
Map<String, TypeDefinition> typeDefinitionMap,
|
Map<String, TypeDefinition> typeDefinitionMap,
|
||||||
|
@ -132,6 +136,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
||||||
this.entityBindingMap = entityBindingMap;
|
this.entityBindingMap = entityBindingMap;
|
||||||
this.composites = composites;
|
this.composites = composites;
|
||||||
this.genericComponentsMap = genericComponentsMap;
|
this.genericComponentsMap = genericComponentsMap;
|
||||||
|
this.embeddableDiscriminatorTypesMap = embeddableDiscriminatorTypesMap;
|
||||||
this.mappedSuperclassMap = mappedSuperclassMap;
|
this.mappedSuperclassMap = mappedSuperclassMap;
|
||||||
this.collectionBindingMap = collectionBindingMap;
|
this.collectionBindingMap = collectionBindingMap;
|
||||||
this.typeDefinitionMap = typeDefinitionMap;
|
this.typeDefinitionMap = typeDefinitionMap;
|
||||||
|
@ -569,6 +574,13 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
||||||
return genericComponentsMap.get( componentClass );
|
return genericComponentsMap.get( componentClass );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiscriminatorType<?> resolveEmbeddableDiscriminatorType(
|
||||||
|
Class<?> embeddableClass,
|
||||||
|
Supplier<DiscriminatorType<?>> supplier) {
|
||||||
|
return embeddableDiscriminatorTypesMap.computeIfAbsent( embeddableClass, k -> supplier.get() );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public org.hibernate.type.Type getIdentifierType(String entityName) throws MappingException {
|
public org.hibernate.type.Type getIdentifierType(String entityName) throws MappingException {
|
||||||
final PersistentClass pc = entityBindingMap.get( entityName );
|
final PersistentClass pc = entityBindingMap.get( entityName );
|
||||||
|
@ -664,4 +676,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
||||||
return genericComponentsMap;
|
return genericComponentsMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<Class<?>, DiscriminatorType<?>> getEmbeddableDiscriminatorTypesMap() {
|
||||||
|
return embeddableDiscriminatorTypesMap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,7 @@ import static org.hibernate.boot.model.internal.GeneratorBinder.buildIdGenerator
|
||||||
import static org.hibernate.boot.model.internal.InheritanceState.getInheritanceStateOfSuperEntity;
|
import static org.hibernate.boot.model.internal.InheritanceState.getInheritanceStateOfSuperEntity;
|
||||||
import static org.hibernate.boot.model.internal.InheritanceState.getSuperclassInheritanceState;
|
import static org.hibernate.boot.model.internal.InheritanceState.getSuperclassInheritanceState;
|
||||||
import static org.hibernate.internal.CoreLogging.messageLogger;
|
import static org.hibernate.internal.CoreLogging.messageLogger;
|
||||||
|
import static org.hibernate.internal.util.StringHelper.unqualify;
|
||||||
import static org.hibernate.mapping.MetadataSource.ANNOTATIONS;
|
import static org.hibernate.mapping.MetadataSource.ANNOTATIONS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -404,7 +405,7 @@ public final class AnnotationBinder {
|
||||||
private static void handleImport(XClass annotatedClass, MetadataBuildingContext context) {
|
private static void handleImport(XClass annotatedClass, MetadataBuildingContext context) {
|
||||||
if ( annotatedClass.isAnnotationPresent( Imported.class ) ) {
|
if ( annotatedClass.isAnnotationPresent( Imported.class ) ) {
|
||||||
String qualifiedName = annotatedClass.getName();
|
String qualifiedName = annotatedClass.getName();
|
||||||
String name = StringHelper.unqualify( qualifiedName );
|
String name = unqualify( qualifiedName );
|
||||||
String rename = annotatedClass.getAnnotation( Imported.class ).rename();
|
String rename = annotatedClass.getAnnotation( Imported.class ).rename();
|
||||||
context.getMetadataCollector().addImport( rename.isEmpty() ? name : rename, qualifiedName );
|
context.getMetadataCollector().addImport( rename.isEmpty() ? name : rename, qualifiedName );
|
||||||
}
|
}
|
||||||
|
@ -693,6 +694,11 @@ public final class AnnotationBinder {
|
||||||
getSuperclassInheritanceState( clazz, inheritanceStatePerClass );
|
getSuperclassInheritanceState( clazz, inheritanceStatePerClass );
|
||||||
final InheritanceState state =
|
final InheritanceState state =
|
||||||
new InheritanceState( clazz, inheritanceStatePerClass, buildingContext );
|
new InheritanceState( clazz, inheritanceStatePerClass, buildingContext );
|
||||||
|
final AnnotatedClassType classType = buildingContext.getMetadataCollector().getClassType( clazz );
|
||||||
|
if ( classType == EMBEDDABLE && !clazz.isAnnotationPresent( Imported.class ) ) {
|
||||||
|
final String className = clazz.getName();
|
||||||
|
buildingContext.getMetadataCollector().addImport( unqualify( className ), className );
|
||||||
|
}
|
||||||
if ( superclassState != null ) {
|
if ( superclassState != null ) {
|
||||||
//the classes are ordered thus preventing an NPE
|
//the classes are ordered thus preventing an NPE
|
||||||
superclassState.setHasSiblings( true );
|
superclassState.setHasSiblings( true );
|
||||||
|
@ -700,7 +706,7 @@ public final class AnnotationBinder {
|
||||||
getInheritanceStateOfSuperEntity( clazz, inheritanceStatePerClass );
|
getInheritanceStateOfSuperEntity( clazz, inheritanceStatePerClass );
|
||||||
if ( superEntityState != null ) {
|
if ( superEntityState != null ) {
|
||||||
state.setHasParents( true );
|
state.setHasParents( true );
|
||||||
if ( buildingContext.getMetadataCollector().getClassType( clazz ) == EMBEDDABLE ) {
|
if ( classType == EMBEDDABLE ) {
|
||||||
buildingContext.getMetadataCollector().registerEmbeddableSubclass(
|
buildingContext.getMetadataCollector().registerEmbeddableSubclass(
|
||||||
superEntityState.getClazz(),
|
superEntityState.getClazz(),
|
||||||
clazz
|
clazz
|
||||||
|
@ -712,7 +718,7 @@ public final class AnnotationBinder {
|
||||||
state.setType( superclassState.getType() );
|
state.setType( superclassState.getType() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch ( buildingContext.getMetadataCollector().getClassType( clazz ) ) {
|
switch ( classType ) {
|
||||||
case ENTITY:
|
case ENTITY:
|
||||||
case MAPPED_SUPERCLASS:
|
case MAPPED_SUPERCLASS:
|
||||||
case EMBEDDABLE:
|
case EMBEDDABLE:
|
||||||
|
|
|
@ -11,6 +11,7 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
|
@ -30,6 +31,7 @@ import org.hibernate.mapping.FetchProfile;
|
||||||
import org.hibernate.mapping.MappedSuperclass;
|
import org.hibernate.mapping.MappedSuperclass;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.mapping.Table;
|
import org.hibernate.mapping.Table;
|
||||||
|
import org.hibernate.metamodel.mapping.DiscriminatorType;
|
||||||
import org.hibernate.query.named.NamedObjectRepository;
|
import org.hibernate.query.named.NamedObjectRepository;
|
||||||
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
|
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
|
||||||
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
||||||
|
@ -249,6 +251,13 @@ public abstract class AbstractDelegatingMetadata implements MetadataImplementor
|
||||||
return delegate().getGenericComponent( componentClass );
|
return delegate().getGenericComponent( componentClass );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiscriminatorType<?> resolveEmbeddableDiscriminatorType(
|
||||||
|
Class<?> embeddableClass,
|
||||||
|
Supplier<DiscriminatorType<?>> supplier) {
|
||||||
|
return delegate().resolveEmbeddableDiscriminatorType( embeddableClass, supplier );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NamedObjectRepository buildNamedQueryRepository(SessionFactoryImplementor sessionFactory) {
|
public NamedObjectRepository buildNamedQueryRepository(SessionFactoryImplementor sessionFactory) {
|
||||||
return delegate().buildNamedQueryRepository( sessionFactory );
|
return delegate().buildNamedQueryRepository( sessionFactory );
|
||||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.boot.spi;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.Incubating;
|
import org.hibernate.Incubating;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
@ -15,6 +16,7 @@ import org.hibernate.boot.Metadata;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.mapping.Component;
|
import org.hibernate.mapping.Component;
|
||||||
import org.hibernate.mapping.MappedSuperclass;
|
import org.hibernate.mapping.MappedSuperclass;
|
||||||
|
import org.hibernate.metamodel.mapping.DiscriminatorType;
|
||||||
import org.hibernate.query.named.NamedObjectRepository;
|
import org.hibernate.query.named.NamedObjectRepository;
|
||||||
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
@ -58,4 +60,6 @@ public interface MetadataImplementor extends Metadata {
|
||||||
void visitRegisteredComponents(Consumer<Component> consumer);
|
void visitRegisteredComponents(Consumer<Component> consumer);
|
||||||
|
|
||||||
Component getGenericComponent(Class<?> componentClass);
|
Component getGenericComponent(Class<?> componentClass);
|
||||||
|
|
||||||
|
DiscriminatorType<?> resolveEmbeddableDiscriminatorType(Class<?> embeddableClass, Supplier<DiscriminatorType<?>> supplier);
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,8 +136,8 @@ public class StructHelper {
|
||||||
instantiator = representationStrategy.getInstantiator();
|
instantiator = representationStrategy.getInstantiator();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// the discriminator here is the composite class name because it gets converted to the domain type when extracted
|
// the discriminator here is the composite class because it gets converted to the domain type when extracted
|
||||||
instantiator = representationStrategy.getInstantiatorForClass( (String) attributeValues.getDiscriminator() );
|
instantiator = representationStrategy.getInstantiatorForClass( ( (Class<?>) attributeValues.getDiscriminator() ).getName() );
|
||||||
}
|
}
|
||||||
return instantiator.instantiate( attributeValues, sessionFactory );
|
return instantiator.instantiate( attributeValues, sessionFactory );
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.hibernate.metamodel.UnsupportedMappingException;
|
||||||
import org.hibernate.metamodel.ValueClassification;
|
import org.hibernate.metamodel.ValueClassification;
|
||||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
|
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.DiscriminatorType;
|
||||||
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.EntityIdentifierMapping;
|
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||||
|
@ -268,7 +269,7 @@ public class AttributeFactory {
|
||||||
false,
|
false,
|
||||||
context.getJpaMetamodel()
|
context.getJpaMetamodel()
|
||||||
);
|
);
|
||||||
context.registerEmbeddableType( embeddableType, component);
|
context.registerEmbeddableType( embeddableType, component );
|
||||||
|
|
||||||
if ( component.isPolymorphic() ) {
|
if ( component.isPolymorphic() ) {
|
||||||
final java.util.Collection<String> embeddableSubclasses = component.getDiscriminatorValues().values();
|
final java.util.Collection<String> embeddableSubclasses = component.getDiscriminatorValues().values();
|
||||||
|
@ -283,12 +284,14 @@ public class AttributeFactory {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final Class<?> subclass = cls.classForName( subclassName );
|
final Class<?> subclass = cls.classForName( subclassName );
|
||||||
context.registerEmbeddableType( new EmbeddableTypeImpl<>(
|
final EmbeddableTypeImpl<?> subType = new EmbeddableTypeImpl<>(
|
||||||
context.getJavaTypeRegistry().resolveManagedTypeDescriptor( subclass ),
|
context.getJavaTypeRegistry().resolveManagedTypeDescriptor( subclass ),
|
||||||
domainTypes.get( component.getSuperclass( subclassName ) ),
|
domainTypes.get( component.getSuperclass( subclassName ) ),
|
||||||
false,
|
false,
|
||||||
context.getJpaMetamodel()
|
context.getJpaMetamodel()
|
||||||
), component );
|
);
|
||||||
|
domainTypes.put( subclassName, subType );
|
||||||
|
context.registerEmbeddableType( subType, component );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
package org.hibernate.metamodel.internal;
|
package org.hibernate.metamodel.internal;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
|
@ -47,7 +47,7 @@ public class DefaultDiscriminatorConverter<O,R> extends DiscriminatorConverter<O
|
||||||
JavaType<O> domainJavaType,
|
JavaType<O> domainJavaType,
|
||||||
JavaType<R> relationalJavaType,
|
JavaType<R> relationalJavaType,
|
||||||
MappingMetamodelImplementor mappingMetamodel) {
|
MappingMetamodelImplementor mappingMetamodel) {
|
||||||
super( discriminatorRole, domainJavaType, relationalJavaType );
|
super( discriminatorRole.getFullPath(), domainJavaType, relationalJavaType );
|
||||||
this.mappingMetamodel = mappingMetamodel;
|
this.mappingMetamodel = mappingMetamodel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
package org.hibernate.metamodel.mapping;
|
package org.hibernate.metamodel.mapping;
|
||||||
|
|
||||||
import org.hibernate.metamodel.RepresentationMode;
|
import org.hibernate.metamodel.RepresentationMode;
|
||||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
|
||||||
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||||
import org.hibernate.type.descriptor.java.JavaType;
|
import org.hibernate.type.descriptor.java.JavaType;
|
||||||
|
|
||||||
|
@ -20,21 +19,21 @@ import java.util.function.Function;
|
||||||
*/
|
*/
|
||||||
public abstract class DiscriminatorConverter<O,R> implements BasicValueConverter<O,R> {
|
public abstract class DiscriminatorConverter<O,R> implements BasicValueConverter<O,R> {
|
||||||
|
|
||||||
private final NavigableRole discriminatorRole;
|
private final String discriminatorName;
|
||||||
private final JavaType<O> domainJavaType;
|
private final JavaType<O> domainJavaType;
|
||||||
private final JavaType<R> relationalJavaType;
|
private final JavaType<R> relationalJavaType;
|
||||||
|
|
||||||
public DiscriminatorConverter(
|
public DiscriminatorConverter(
|
||||||
NavigableRole discriminatorRole,
|
String discriminatorName,
|
||||||
JavaType<O> domainJavaType,
|
JavaType<O> domainJavaType,
|
||||||
JavaType<R> relationalJavaType) {
|
JavaType<R> relationalJavaType) {
|
||||||
this.discriminatorRole = discriminatorRole;
|
this.discriminatorName = discriminatorName;
|
||||||
this.domainJavaType = domainJavaType;
|
this.domainJavaType = domainJavaType;
|
||||||
this.relationalJavaType = relationalJavaType;
|
this.relationalJavaType = relationalJavaType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NavigableRole getNavigableRole() {
|
public String getDiscriminatorName() {
|
||||||
return discriminatorRole;
|
return discriminatorName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -95,7 +94,7 @@ public abstract class DiscriminatorConverter<O,R> implements BasicValueConverter
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "DiscriminatorConverter(" + discriminatorRole.getFullPath() + ")";
|
return "DiscriminatorConverter(" + discriminatorName + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void forEachValueDetail(Consumer<DiscriminatorValueDetails> consumer);
|
public abstract void forEachValueDetail(Consumer<DiscriminatorValueDetails> consumer);
|
||||||
|
|
|
@ -15,6 +15,8 @@ import java.util.function.Function;
|
||||||
|
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.metamodel.mapping.internal.EmbeddableDiscriminatorValueDetailsImpl;
|
import org.hibernate.metamodel.mapping.internal.EmbeddableDiscriminatorValueDetailsImpl;
|
||||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
|
@ -29,32 +31,34 @@ import org.hibernate.type.descriptor.java.JavaType;
|
||||||
*/
|
*/
|
||||||
public class EmbeddableDiscriminatorConverter<O, R> extends DiscriminatorConverter<O, R> {
|
public class EmbeddableDiscriminatorConverter<O, R> extends DiscriminatorConverter<O, R> {
|
||||||
public static <O, R> EmbeddableDiscriminatorConverter<O, R> fromValueMappings(
|
public static <O, R> EmbeddableDiscriminatorConverter<O, R> fromValueMappings(
|
||||||
NavigableRole role,
|
String discriminatedType,
|
||||||
JavaType<O> domainJavaType,
|
JavaType<O> domainJavaType,
|
||||||
BasicType<R> underlyingJdbcMapping,
|
BasicType<R> underlyingJdbcMapping,
|
||||||
Map<Object, String> valueMappings) {
|
Map<Object, String> valueMappings,
|
||||||
final List<DiscriminatorValueDetails> valueDetailsList = new ArrayList<>( valueMappings.size() );
|
SessionFactoryImplementor sessionFactory) {
|
||||||
|
final List<EmbeddableDiscriminatorValueDetailsImpl> valueDetailsList = new ArrayList<>( valueMappings.size() );
|
||||||
|
final ClassLoaderService cls = sessionFactory.getServiceRegistry().requireService( ClassLoaderService.class );
|
||||||
valueMappings.forEach( (value, embeddableClassName) -> valueDetailsList.add( new EmbeddableDiscriminatorValueDetailsImpl(
|
valueMappings.forEach( (value, embeddableClassName) -> valueDetailsList.add( new EmbeddableDiscriminatorValueDetailsImpl(
|
||||||
value,
|
value,
|
||||||
embeddableClassName
|
cls.classForName( embeddableClassName )
|
||||||
) ) );
|
) ) );
|
||||||
return new EmbeddableDiscriminatorConverter<>(
|
return new EmbeddableDiscriminatorConverter<>(
|
||||||
role,
|
discriminatedType,
|
||||||
domainJavaType,
|
domainJavaType,
|
||||||
underlyingJdbcMapping.getJavaTypeDescriptor(),
|
underlyingJdbcMapping.getJavaTypeDescriptor(),
|
||||||
valueDetailsList
|
valueDetailsList
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Map<Object, DiscriminatorValueDetails> discriminatorValueToDetailsMap;
|
private final Map<Object, EmbeddableDiscriminatorValueDetailsImpl> discriminatorValueToDetailsMap;
|
||||||
private final Map<String, DiscriminatorValueDetails> embeddableClassNameToDetailsMap;
|
private final Map<String, EmbeddableDiscriminatorValueDetailsImpl> embeddableClassNameToDetailsMap;
|
||||||
|
|
||||||
public EmbeddableDiscriminatorConverter(
|
public EmbeddableDiscriminatorConverter(
|
||||||
NavigableRole discriminatorRole,
|
String discriminatorName,
|
||||||
JavaType<O> domainJavaType,
|
JavaType<O> domainJavaType,
|
||||||
JavaType<R> relationalJavaType,
|
JavaType<R> relationalJavaType,
|
||||||
List<DiscriminatorValueDetails> valueMappings) {
|
List<EmbeddableDiscriminatorValueDetailsImpl> valueMappings) {
|
||||||
super( discriminatorRole, domainJavaType, relationalJavaType );
|
super( discriminatorName, domainJavaType, relationalJavaType );
|
||||||
|
|
||||||
this.discriminatorValueToDetailsMap = new HashMap<>( valueMappings.size() );
|
this.discriminatorValueToDetailsMap = new HashMap<>( valueMappings.size() );
|
||||||
this.embeddableClassNameToDetailsMap = new HashMap<>( valueMappings.size() );
|
this.embeddableClassNameToDetailsMap = new HashMap<>( valueMappings.size() );
|
||||||
|
@ -68,32 +72,18 @@ public class EmbeddableDiscriminatorConverter<O, R> extends DiscriminatorConvert
|
||||||
public O toDomainValue(R relationalForm) {
|
public O toDomainValue(R relationalForm) {
|
||||||
assert relationalForm == null || getRelationalJavaType().isInstance( relationalForm );
|
assert relationalForm == null || getRelationalJavaType().isInstance( relationalForm );
|
||||||
|
|
||||||
final DiscriminatorValueDetails matchingValueDetails = getDetailsForDiscriminatorValue( relationalForm );
|
final EmbeddableDiscriminatorValueDetailsImpl matchingValueDetails = getDetailsForDiscriminatorValue( relationalForm );
|
||||||
if ( matchingValueDetails == null ) {
|
if ( matchingValueDetails == null ) {
|
||||||
throw new IllegalStateException( "Could not resolve discriminator value" );
|
throw new IllegalStateException( "Could not resolve discriminator value" );
|
||||||
}
|
}
|
||||||
|
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return (O) matchingValueDetails.getIndicatedEntityName();
|
return (O) matchingValueDetails.getEmbeddableClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public R toRelationalValue(O domainForm) {
|
public EmbeddableDiscriminatorValueDetailsImpl getDetailsForDiscriminatorValue(Object value) {
|
||||||
assert domainForm == null || domainForm instanceof String;
|
final EmbeddableDiscriminatorValueDetailsImpl valueMatch = discriminatorValueToDetailsMap.get( value );
|
||||||
|
|
||||||
if ( domainForm == null ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String embeddableClassName = (String) domainForm;
|
|
||||||
|
|
||||||
//noinspection unchecked
|
|
||||||
return (R) getDetailsForEntityName( embeddableClassName ).getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DiscriminatorValueDetails getDetailsForDiscriminatorValue(Object value) {
|
|
||||||
final DiscriminatorValueDetails valueMatch = discriminatorValueToDetailsMap.get( value );
|
|
||||||
if ( valueMatch != null ) {
|
if ( valueMatch != null ) {
|
||||||
return valueMatch;
|
return valueMatch;
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ public class MappedDiscriminatorConverter<O,R> extends DiscriminatorConverter<O,
|
||||||
JavaType<O> domainJavaType,
|
JavaType<O> domainJavaType,
|
||||||
JavaType<R> relationalJavaType,
|
JavaType<R> relationalJavaType,
|
||||||
List<DiscriminatorValueDetails> valueMappings) {
|
List<DiscriminatorValueDetails> valueMappings) {
|
||||||
super( discriminatorRole, domainJavaType, relationalJavaType );
|
super( discriminatorRole.getFullPath(), domainJavaType, relationalJavaType );
|
||||||
|
|
||||||
this.discriminatorValueToEntityNameMap = CollectionHelper.concurrentMap( valueMappings.size() );
|
this.discriminatorValueToEntityNameMap = CollectionHelper.concurrentMap( valueMappings.size() );
|
||||||
this.entityNameToDiscriminatorValueMap = CollectionHelper.concurrentMap( valueMappings.size() );
|
this.entityNameToDiscriminatorValueMap = CollectionHelper.concurrentMap( valueMappings.size() );
|
||||||
|
|
|
@ -27,8 +27,8 @@ public class DiscriminatorTypeImpl<O> extends ConvertedBasicTypeImpl<O> implemen
|
||||||
BasicType<?> underlyingJdbcMapping,
|
BasicType<?> underlyingJdbcMapping,
|
||||||
DiscriminatorConverter<O,?> discriminatorValueConverter) {
|
DiscriminatorConverter<O,?> discriminatorValueConverter) {
|
||||||
super(
|
super(
|
||||||
discriminatorValueConverter.getNavigableRole().getFullPath(),
|
discriminatorValueConverter.getDiscriminatorName(),
|
||||||
"Discriminator type " + discriminatorValueConverter.getNavigableRole().getFullPath(),
|
"Discriminator type " + discriminatorValueConverter.getDiscriminatorName(),
|
||||||
underlyingJdbcMapping.getJdbcType(),
|
underlyingJdbcMapping.getJdbcType(),
|
||||||
discriminatorValueConverter
|
discriminatorValueConverter
|
||||||
);
|
);
|
||||||
|
|
|
@ -20,11 +20,15 @@ import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
*/
|
*/
|
||||||
public class EmbeddableDiscriminatorValueDetailsImpl implements DiscriminatorValueDetails {
|
public class EmbeddableDiscriminatorValueDetailsImpl implements DiscriminatorValueDetails {
|
||||||
final Object value;
|
final Object value;
|
||||||
final String embeddableClassName;
|
final Class<?> embeddableClass;
|
||||||
|
|
||||||
public EmbeddableDiscriminatorValueDetailsImpl(Object value, String embeddableClassName) {
|
public EmbeddableDiscriminatorValueDetailsImpl(Object value, Class<?> embeddableClass) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.embeddableClassName = embeddableClassName;
|
this.embeddableClass = embeddableClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> getEmbeddableClass() {
|
||||||
|
return embeddableClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -34,7 +38,7 @@ public class EmbeddableDiscriminatorValueDetailsImpl implements DiscriminatorVal
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getIndicatedEntityName() {
|
public String getIndicatedEntityName() {
|
||||||
return embeddableClassName;
|
return embeddableClass.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -16,7 +16,6 @@ import java.util.function.Function;
|
||||||
|
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.SharedSessionContract;
|
import org.hibernate.SharedSessionContract;
|
||||||
import org.hibernate.WrongClassException;
|
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.dialect.aggregate.AggregateSupport;
|
import org.hibernate.dialect.aggregate.AggregateSupport;
|
||||||
|
@ -47,6 +46,7 @@ import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.metamodel.mapping.SelectableConsumer;
|
import org.hibernate.metamodel.mapping.SelectableConsumer;
|
||||||
import org.hibernate.metamodel.mapping.SelectableMapping;
|
import org.hibernate.metamodel.mapping.SelectableMapping;
|
||||||
import org.hibernate.metamodel.mapping.SelectableMappings;
|
import org.hibernate.metamodel.mapping.SelectableMappings;
|
||||||
|
@ -54,7 +54,6 @@ import org.hibernate.metamodel.mapping.SelectablePath;
|
||||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||||
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
|
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
|
||||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||||
import org.hibernate.persister.entity.DiscriminatorHelper;
|
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.property.access.spi.Getter;
|
import org.hibernate.property.access.spi.Getter;
|
||||||
import org.hibernate.property.access.spi.PropertyAccess;
|
import org.hibernate.property.access.spi.PropertyAccess;
|
||||||
|
@ -83,6 +82,7 @@ import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||||
import org.hibernate.type.spi.CompositeTypeImplementor;
|
import org.hibernate.type.spi.CompositeTypeImplementor;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
import static org.hibernate.internal.util.StringHelper.qualify;
|
||||||
import static org.hibernate.persister.entity.DiscriminatorHelper.getDiscriminatorType;
|
import static org.hibernate.persister.entity.DiscriminatorHelper.getDiscriminatorType;
|
||||||
|
|
||||||
import static org.hibernate.type.SqlTypes.JSON;
|
import static org.hibernate.type.SqlTypes.JSON;
|
||||||
|
@ -736,9 +736,12 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
|
||||||
scale = column.getScale();
|
scale = column.getScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
final DiscriminatorType<?> discriminatorType = buildDiscriminatorType(
|
final DiscriminatorType<?> discriminatorType = creationContext.getMetadata().resolveEmbeddableDiscriminatorType(
|
||||||
bootDescriptor,
|
bootDescriptor.getComponentClass(),
|
||||||
creationContext
|
() -> buildDiscriminatorType(
|
||||||
|
bootDescriptor,
|
||||||
|
creationContext
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
return new ExplicitColumnDiscriminatorMappingImpl(
|
return new ExplicitColumnDiscriminatorMappingImpl(
|
||||||
|
@ -758,17 +761,18 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DiscriminatorType<?> buildDiscriminatorType(
|
private static DiscriminatorType<?> buildDiscriminatorType(
|
||||||
Component bootDescriptor,
|
Component bootDescriptor,
|
||||||
RuntimeModelCreationContext creationContext) {
|
RuntimeModelCreationContext creationContext) {
|
||||||
final JavaTypeRegistry javaTypeRegistry = creationContext.getSessionFactory().getTypeConfiguration().getJavaTypeRegistry();
|
final JavaTypeRegistry javaTypeRegistry = creationContext.getSessionFactory().getTypeConfiguration().getJavaTypeRegistry();
|
||||||
final JavaType<String> domainJavaType = javaTypeRegistry.resolveDescriptor( String.class );
|
final JavaType<String> domainJavaType = javaTypeRegistry.resolveDescriptor( Class.class );
|
||||||
final BasicType<?> discriminatorType = getDiscriminatorType( bootDescriptor );
|
final BasicType<?> discriminatorType = getDiscriminatorType( bootDescriptor );
|
||||||
final DiscriminatorConverter<String, ?> converter = EmbeddableDiscriminatorConverter.fromValueMappings(
|
final DiscriminatorConverter<String, ?> converter = EmbeddableDiscriminatorConverter.fromValueMappings(
|
||||||
getNavigableRole().append( EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME ),
|
qualify( bootDescriptor.getComponentClassName(), EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME ),
|
||||||
domainJavaType,
|
domainJavaType,
|
||||||
discriminatorType,
|
discriminatorType,
|
||||||
bootDescriptor.getDiscriminatorValues()
|
bootDescriptor.getDiscriminatorValues(),
|
||||||
|
creationContext.getSessionFactory()
|
||||||
);
|
);
|
||||||
return new DiscriminatorTypeImpl<>( discriminatorType, converter );
|
return new DiscriminatorTypeImpl<>( discriminatorType, converter );
|
||||||
}
|
}
|
||||||
|
@ -882,6 +886,15 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelPart findSubPart(String name, EntityMappingType treatTargetType) {
|
||||||
|
if ( EntityDiscriminatorMapping.matchesRoleName( name ) ) {
|
||||||
|
return discriminatorMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.findSubPart( name, treatTargetType );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X, Y> int breakDownJdbcValues(
|
public <X, Y> int breakDownJdbcValues(
|
||||||
Object domainValue,
|
Object domainValue,
|
||||||
|
|
|
@ -6,8 +6,10 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.model.domain;
|
package org.hibernate.metamodel.model.domain;
|
||||||
|
|
||||||
import org.hibernate.query.BindableType;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.hibernate.query.sqm.SqmExpressible;
|
import org.hibernate.query.sqm.SqmExpressible;
|
||||||
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
|
|
||||||
import jakarta.persistence.metamodel.EmbeddableType;
|
import jakarta.persistence.metamodel.EmbeddableType;
|
||||||
|
|
||||||
|
@ -20,5 +22,16 @@ import jakarta.persistence.metamodel.EmbeddableType;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface EmbeddableDomainType<J>
|
public interface EmbeddableDomainType<J>
|
||||||
extends ManagedDomainType<J>, EmbeddableType<J>, SqmExpressible<J> {
|
extends TreatableDomainType<J>, EmbeddableType<J>, SqmExpressible<J> {
|
||||||
|
@Override
|
||||||
|
default EmbeddableDomainType<J> getSqmType() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Collection<? extends EmbeddableDomainType<? extends J>> getSubTypes();
|
||||||
|
|
||||||
|
default boolean isPolymorphic() {
|
||||||
|
return getSuperType() != null || !getSubTypes().isEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,14 +17,14 @@ import org.hibernate.query.sqm.SqmPathSource;
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface EntityDomainType<J> extends IdentifiableDomainType<J>, EntityType<J>, SqmPathSource<J> {
|
public interface EntityDomainType<J> extends IdentifiableDomainType<J>, EntityType<J>, TreatableDomainType<J> {
|
||||||
String getHibernateEntityName();
|
String getHibernateEntityName();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Collection<? extends EntityDomainType<? extends J>> getSubTypes();
|
Collection<? extends EntityDomainType<? extends J>> getSubTypes();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default DomainType<J> getSqmType() {
|
default EntityDomainType<J> getSqmType() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,11 +47,21 @@ public interface JpaMetamodel extends Metamodel {
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// Extended features
|
// Extended features
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access to a managed type through its name
|
||||||
|
*/
|
||||||
|
<X> ManagedDomainType<X> managedType(String typeName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access to an entity supporting Hibernate's entity-name feature
|
* Access to an entity supporting Hibernate's entity-name feature
|
||||||
*/
|
*/
|
||||||
<X> EntityDomainType<X> entity(String entityName);
|
<X> EntityDomainType<X> entity(String entityName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access to an embeddable type from FQN
|
||||||
|
*/
|
||||||
|
<X> EmbeddableDomainType<X> embeddable(String embeddableName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specialized handling for resolving entity-name references in
|
* Specialized handling for resolving entity-name references in
|
||||||
* an HQL query
|
* an HQL query
|
||||||
|
|
|
@ -37,9 +37,6 @@ public interface ManagedDomainType<J> extends SqmExpressible<J>, DomainType<J>,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The descriptor of the supertype of this type.
|
* The descriptor of the supertype of this type.
|
||||||
*
|
|
||||||
* @apiNote we define this here in anticipation of eventually supporting
|
|
||||||
* embeddable inheritance
|
|
||||||
*/
|
*/
|
||||||
ManagedDomainType<? super J> getSuperType();
|
ManagedDomainType<? super J> getSuperType();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* 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.model.domain;
|
||||||
|
|
||||||
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Marco Belladelli
|
||||||
|
*/
|
||||||
|
public interface TreatableDomainType<J> extends ManagedDomainType<J>, SqmPathSource<J> {
|
||||||
|
@Override
|
||||||
|
default DomainType<J> getSqmType() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* 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.model.domain.internal;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.model.domain.DomainType;
|
||||||
|
import org.hibernate.query.ReturnableType;
|
||||||
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
|
|
||||||
|
import static jakarta.persistence.metamodel.Bindable.BindableType.SINGULAR_ATTRIBUTE;
|
||||||
|
import static org.hibernate.metamodel.mapping.EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract SqmPathSource implementation for discriminators
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public abstract class AbstractDiscriminatorSqmPathSource<D> extends AbstractSqmPathSource<D>
|
||||||
|
implements ReturnableType<D> {
|
||||||
|
public AbstractDiscriminatorSqmPathSource(DomainType<D> domainType) {
|
||||||
|
super( DISCRIMINATOR_ROLE_NAME, null, domainType, SINGULAR_ATTRIBUTE );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPathSource<?> findSubPathSource(String name) {
|
||||||
|
throw new IllegalStateException( "Entity discriminator cannot be de-referenced" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PersistenceType getPersistenceType() {
|
||||||
|
return PersistenceType.BASIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<D> getJavaType() {
|
||||||
|
return getExpressibleJavaType().getJavaTypeClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainType<D> getSqmType() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,12 +7,17 @@
|
||||||
package org.hibernate.metamodel.model.domain.internal;
|
package org.hibernate.metamodel.model.domain.internal;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.UnsupportedMappingException;
|
||||||
import org.hibernate.metamodel.model.domain.AbstractManagedType;
|
import org.hibernate.metamodel.model.domain.AbstractManagedType;
|
||||||
import org.hibernate.metamodel.model.domain.DomainType;
|
import org.hibernate.metamodel.model.domain.DomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
||||||
import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor;
|
import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor;
|
||||||
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
import org.hibernate.type.descriptor.java.JavaType;
|
import org.hibernate.type.descriptor.java.JavaType;
|
||||||
|
|
||||||
import jakarta.persistence.metamodel.SingularAttribute;
|
import jakarta.persistence.metamodel.SingularAttribute;
|
||||||
|
@ -56,4 +61,40 @@ public class EmbeddableTypeImpl<J>
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends EmbeddableDomainType<? extends J>> getSubTypes() {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (Collection<? extends EmbeddableDomainType<? extends J>>) super.getSubTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPathName() {
|
||||||
|
return getTypeName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EmbeddableDomainType<J> getSqmPathType() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPathSource<?> findSubPathSource(String name) {
|
||||||
|
final PersistentAttribute<? super J, ?> attribute = getSqmPathType().findAttribute( name );
|
||||||
|
if ( attribute != null ) {
|
||||||
|
return (SqmPathSource<?>) attribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (SqmPathSource<?>) findSubTypesAttribute( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPath<J> createSqmPath(SqmPath<?> lhs, SqmPathSource<?> intermediatePathSource) {
|
||||||
|
throw new UnsupportedMappingException( "EmbeddableType cannot be used to create an SqmPath" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BindableType getBindableType() {
|
||||||
|
return BindableType.SINGULAR_ATTRIBUTE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* 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.model.domain.internal;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.model.domain.DiscriminatorSqmPath;
|
||||||
|
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||||
|
import org.hibernate.query.sqm.NodeBuilder;
|
||||||
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
|
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||||
|
import org.hibernate.query.sqm.tree.domain.AbstractSqmPath;
|
||||||
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
|
import org.hibernate.spi.NavigablePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link SqmPath} specialization for an embeddable discriminator
|
||||||
|
*
|
||||||
|
* @author Marco Belladelli
|
||||||
|
*/
|
||||||
|
public class EmbeddedDiscriminatorSqmPath<T> extends AbstractSqmPath<T> implements DiscriminatorSqmPath<T> {
|
||||||
|
private final EmbeddableDomainType<T> embeddableDomainType;
|
||||||
|
|
||||||
|
@SuppressWarnings( { "rawtypes", "unchecked" } )
|
||||||
|
protected EmbeddedDiscriminatorSqmPath(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
SqmPathSource referencedPathSource,
|
||||||
|
SqmPath<?> lhs,
|
||||||
|
EmbeddableDomainType embeddableDomainType,
|
||||||
|
NodeBuilder nodeBuilder) {
|
||||||
|
super( navigablePath, referencedPathSource, lhs, nodeBuilder );
|
||||||
|
this.embeddableDomainType = embeddableDomainType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EmbeddableDomainType<T> getExpressible() {
|
||||||
|
return embeddableDomainType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EmbeddedDiscriminatorSqmPath<T> copy(SqmCopyContext context) {
|
||||||
|
final EmbeddedDiscriminatorSqmPath<T> existing = context.getCopy( this );
|
||||||
|
if ( existing != null ) {
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
//noinspection unchecked
|
||||||
|
return context.registerCopy(
|
||||||
|
this,
|
||||||
|
(EmbeddedDiscriminatorSqmPath<T>) getLhs().copy( context ).type()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||||
|
return walker.visitDiscriminatorPath( this );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* 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.model.domain.internal;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||||
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SqmPathSource implementation for embeddable discriminator
|
||||||
|
*
|
||||||
|
* @author Marco Belladelli
|
||||||
|
*/
|
||||||
|
public class EmbeddedDiscriminatorSqmPathSource<D> extends AbstractDiscriminatorSqmPathSource<D> {
|
||||||
|
private final EmbeddableDomainType<D> embeddableDomainType;
|
||||||
|
|
||||||
|
public EmbeddedDiscriminatorSqmPathSource(EmbeddableDomainType<D> embeddableDomainType) {
|
||||||
|
super( embeddableDomainType );
|
||||||
|
this.embeddableDomainType = embeddableDomainType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPath<D> createSqmPath(SqmPath<?> lhs, SqmPathSource<?> intermediatePathSource) {
|
||||||
|
return new EmbeddedDiscriminatorSqmPath<>(
|
||||||
|
PathHelper.append( lhs, this, intermediatePathSource ),
|
||||||
|
pathModel,
|
||||||
|
lhs,
|
||||||
|
embeddableDomainType,
|
||||||
|
lhs.nodeBuilder()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,8 @@ import org.hibernate.query.sqm.SqmPathSource;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
|
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
|
|
||||||
|
import static org.hibernate.metamodel.mapping.EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
|
@ -21,6 +23,7 @@ public class EmbeddedSqmPathSource<J>
|
||||||
extends AbstractSqmPathSource<J>
|
extends AbstractSqmPathSource<J>
|
||||||
implements CompositeSqmPathSource<J> {
|
implements CompositeSqmPathSource<J> {
|
||||||
private final boolean isGeneric;
|
private final boolean isGeneric;
|
||||||
|
private final EmbeddedDiscriminatorSqmPathSource<?> discriminatorPathSource;
|
||||||
|
|
||||||
public EmbeddedSqmPathSource(
|
public EmbeddedSqmPathSource(
|
||||||
String localPathName,
|
String localPathName,
|
||||||
|
@ -30,6 +33,12 @@ public class EmbeddedSqmPathSource<J>
|
||||||
boolean isGeneric) {
|
boolean isGeneric) {
|
||||||
super( localPathName, pathModel, domainType, jpaBindableType );
|
super( localPathName, pathModel, domainType, jpaBindableType );
|
||||||
this.isGeneric = isGeneric;
|
this.isGeneric = isGeneric;
|
||||||
|
if ( domainType.isPolymorphic() ) {
|
||||||
|
discriminatorPathSource = new EmbeddedDiscriminatorSqmPathSource<>( domainType );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
discriminatorPathSource = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -38,18 +47,17 @@ public class EmbeddedSqmPathSource<J>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPathSource<?> findSubPathSource(String name, JpaMetamodelImplementor metamodel) {
|
public SqmPathSource<?> findSubPathSource(String name) {
|
||||||
final PersistentAttribute<? super J, ?> attribute = getSqmPathType().findAttribute( name );
|
final SqmPathSource<?> subPathSource = getSqmPathType().findSubPathSource( name );
|
||||||
if ( attribute != null ) {
|
if ( subPathSource != null ) {
|
||||||
return (SqmPathSource<?>) attribute;
|
return subPathSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (SqmPathSource<?>) getSqmPathType().findSubTypesAttribute( name );
|
if ( name.equals( DISCRIMINATOR_ROLE_NAME ) && discriminatorPathSource != null ) {
|
||||||
}
|
return discriminatorPathSource;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
return null;
|
||||||
public SqmPathSource<?> findSubPathSource(String name) {
|
|
||||||
return (SqmPathSource<?>) getSqmPathType().findAttribute( name );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -49,8 +49,8 @@ public class EntityDiscriminatorSqmPath<T> extends AbstractSqmPath<T> implements
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DiscriminatorSqmPathSource getExpressible() {
|
public EntityDiscriminatorSqmPathSource getExpressible() {
|
||||||
return (DiscriminatorSqmPathSource) getNodeType();
|
return (EntityDiscriminatorSqmPathSource) getNodeType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -9,28 +9,23 @@ package org.hibernate.metamodel.model.domain.internal;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.metamodel.model.domain.DomainType;
|
import org.hibernate.metamodel.model.domain.DomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
import org.hibernate.query.ReturnableType;
|
|
||||||
import org.hibernate.query.sqm.SqmPathSource;
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
|
|
||||||
import static jakarta.persistence.metamodel.Bindable.BindableType.SINGULAR_ATTRIBUTE;
|
|
||||||
import static org.hibernate.metamodel.mapping.EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SqmPathSource implementation for entity discriminator
|
* SqmPathSource implementation for entity discriminator
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class DiscriminatorSqmPathSource<D> extends AbstractSqmPathSource<D>
|
public class EntityDiscriminatorSqmPathSource<D> extends AbstractDiscriminatorSqmPathSource<D> {
|
||||||
implements ReturnableType<D> {
|
|
||||||
private final EntityDomainType<?> entityDomainType;
|
private final EntityDomainType<?> entityDomainType;
|
||||||
private final EntityMappingType entityMapping;
|
private final EntityMappingType entityMapping;
|
||||||
|
|
||||||
public DiscriminatorSqmPathSource(
|
public EntityDiscriminatorSqmPathSource(
|
||||||
DomainType<D> discriminatorValueType,
|
DomainType<D> discriminatorValueType,
|
||||||
EntityDomainType<?> entityDomainType,
|
EntityDomainType<?> entityDomainType,
|
||||||
EntityMappingType entityMapping) {
|
EntityMappingType entityMapping) {
|
||||||
super( DISCRIMINATOR_ROLE_NAME, null, discriminatorValueType, SINGULAR_ATTRIBUTE );
|
super( discriminatorValueType );
|
||||||
this.entityDomainType = entityDomainType;
|
this.entityDomainType = entityDomainType;
|
||||||
this.entityMapping = entityMapping;
|
this.entityMapping = entityMapping;
|
||||||
}
|
}
|
||||||
|
@ -54,24 +49,4 @@ public class DiscriminatorSqmPathSource<D> extends AbstractSqmPathSource<D>
|
||||||
lhs.nodeBuilder()
|
lhs.nodeBuilder()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public SqmPathSource<?> findSubPathSource(String name) {
|
|
||||||
throw new IllegalStateException( "Entity discriminator cannot be de-referenced" );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PersistenceType getPersistenceType() {
|
|
||||||
return PersistenceType.BASIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<D> getJavaType() {
|
|
||||||
return getExpressibleJavaType().getJavaTypeClass();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DomainType<D> getSqmType() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -85,7 +85,7 @@ public class EntityTypeImpl<J>
|
||||||
.resolve( StandardBasicTypes.STRING );
|
.resolve( StandardBasicTypes.STRING );
|
||||||
}
|
}
|
||||||
|
|
||||||
this.discriminatorPathSource = discriminatorType == null ? null : new DiscriminatorSqmPathSource(
|
this.discriminatorPathSource = discriminatorType == null ? null : new EntityDiscriminatorSqmPathSource(
|
||||||
discriminatorType,
|
discriminatorType,
|
||||||
this,
|
this,
|
||||||
entityDescriptor
|
entityDescriptor
|
||||||
|
|
|
@ -10,6 +10,7 @@ import java.io.ObjectStreamException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -17,6 +18,7 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.hibernate.boot.model.NamedEntityGraphDefinition;
|
import org.hibernate.boot.model.NamedEntityGraphDefinition;
|
||||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||||
|
@ -88,10 +90,9 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
||||||
private final MappingMetamodel mappingMetamodel;
|
private final MappingMetamodel mappingMetamodel;
|
||||||
private final ServiceRegistry serviceRegistry;
|
private final ServiceRegistry serviceRegistry;
|
||||||
|
|
||||||
private final Map<String, EntityDomainType<?>> jpaEntityTypeMap = new TreeMap<>(); // Need ordering for deterministic implementers list in SqmPolymorphicRootDescriptor
|
private final Map<String, ManagedDomainType<?>> managedTypeByName = new TreeMap<>();
|
||||||
private final Map<Class<?>, ManagedDomainType<?>> jpaManagedTypeMap = new HashMap<>();
|
private final Map<Class<?>, ManagedDomainType<?>> managedTypeByClass = new HashMap<>();
|
||||||
private final Set<ManagedDomainType<?>> jpaManagedTypes = new HashSet<>();
|
private JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting;
|
||||||
private final Set<EmbeddableDomainType<?>> jpaEmbeddables = new HashSet<>();
|
|
||||||
private final Map<String, Set<String>> allowedEnumLiteralTexts = new HashMap<>();
|
private final Map<String, Set<String>> allowedEnumLiteralTexts = new HashMap<>();
|
||||||
|
|
||||||
private final transient Map<String, RootGraphImplementor<?>> entityGraphMap = new ConcurrentHashMap<>();
|
private final transient Map<String, RootGraphImplementor<?>> entityGraphMap = new ConcurrentHashMap<>();
|
||||||
|
@ -129,9 +130,35 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> EntityDomainType<X> entity(String entityName) {
|
public <X> ManagedDomainType<X> managedType(String typeName) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return entityName==null ? null : (EntityDomainType<X>) jpaEntityTypeMap.get( entityName );
|
return typeName == null ? null : (ManagedDomainType<X>) managedTypeByName.get( typeName );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <X> EntityDomainType<X> entity(String entityName) {
|
||||||
|
if ( entityName == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final ManagedDomainType<?> managedType = managedTypeByName.get( entityName );
|
||||||
|
if ( !( managedType instanceof EntityDomainType<?> ) ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
//noinspection unchecked
|
||||||
|
return (EntityDomainType<X>) managedType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <X> EmbeddableDomainType<X> embeddable(String embeddableName) {
|
||||||
|
if ( embeddableName == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final ManagedDomainType<?> managedType = managedTypeByName.get( embeddableName );
|
||||||
|
if ( !( managedType instanceof EmbeddableDomainType<?> ) ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
//noinspection unchecked
|
||||||
|
return (EmbeddableDomainType<X>) managedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -173,13 +200,13 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
||||||
@Override
|
@Override
|
||||||
public <X> ManagedDomainType<X> findManagedType(Class<X> cls) {
|
public <X> ManagedDomainType<X> findManagedType(Class<X> cls) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return (ManagedDomainType<X>) jpaManagedTypeMap.get( cls );
|
return (ManagedDomainType<X>) managedTypeByClass.get( cls );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> EntityDomainType<X> findEntityType(Class<X> cls) {
|
public <X> EntityDomainType<X> findEntityType(Class<X> cls) {
|
||||||
final ManagedType<?> type = jpaManagedTypeMap.get( cls );
|
final ManagedType<?> type = managedTypeByClass.get( cls );
|
||||||
if ( !( type instanceof EntityType<?> ) ) {
|
if ( !( type instanceof EntityDomainType<?> ) ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
|
@ -188,7 +215,7 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> ManagedDomainType<X> managedType(Class<X> cls) {
|
public <X> ManagedDomainType<X> managedType(Class<X> cls) {
|
||||||
final ManagedType<?> type = jpaManagedTypeMap.get( cls );
|
final ManagedType<?> type = managedTypeByClass.get( cls );
|
||||||
if ( type == null ) {
|
if ( type == null ) {
|
||||||
// per JPA
|
// per JPA
|
||||||
throw new IllegalArgumentException( "Not a managed type: " + cls );
|
throw new IllegalArgumentException( "Not a managed type: " + cls );
|
||||||
|
@ -200,7 +227,7 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> EntityDomainType<X> entity(Class<X> cls) {
|
public <X> EntityDomainType<X> entity(Class<X> cls) {
|
||||||
final ManagedType<?> type = jpaManagedTypeMap.get( cls );
|
final ManagedType<?> type = managedTypeByClass.get( cls );
|
||||||
if ( !( type instanceof EntityDomainType<?> ) ) {
|
if ( !( type instanceof EntityDomainType<?> ) ) {
|
||||||
throw new IllegalArgumentException( "Not an entity: " + cls.getName() );
|
throw new IllegalArgumentException( "Not an entity: " + cls.getName() );
|
||||||
}
|
}
|
||||||
|
@ -210,7 +237,7 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> EmbeddableDomainType<X> embeddable(Class<X> cls) {
|
public <X> EmbeddableDomainType<X> embeddable(Class<X> cls) {
|
||||||
final ManagedType<?> type = jpaManagedTypeMap.get( cls );
|
final ManagedType<?> type = managedTypeByClass.get( cls );
|
||||||
if ( !( type instanceof EmbeddableDomainType<?> ) ) {
|
if ( !( type instanceof EmbeddableDomainType<?> ) ) {
|
||||||
throw new IllegalArgumentException( "Not an embeddable: " + cls.getName() );
|
throw new IllegalArgumentException( "Not an embeddable: " + cls.getName() );
|
||||||
}
|
}
|
||||||
|
@ -218,25 +245,39 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
||||||
return (EmbeddableDomainType<X>) type;
|
return (EmbeddableDomainType<X>) type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Collection<ManagedDomainType<?>> getAllManagedTypes() {
|
||||||
|
switch ( jpaMetaModelPopulationSetting ) {
|
||||||
|
case IGNORE_UNSUPPORTED:
|
||||||
|
return managedTypeByClass.values();
|
||||||
|
case ENABLED:
|
||||||
|
return managedTypeByName.values();
|
||||||
|
case DISABLED:
|
||||||
|
return Collections.emptySet();
|
||||||
|
default:
|
||||||
|
// should never happen
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<ManagedType<?>> getManagedTypes() {
|
public Set<ManagedType<?>> getManagedTypes() {
|
||||||
return new HashSet<>( jpaManagedTypes );
|
return new HashSet<>( getAllManagedTypes() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<EntityType<?>> getEntities() {
|
public Set<EntityType<?>> getEntities() {
|
||||||
final Set<EntityType<?>> entityTypes = new HashSet<>( jpaEntityTypeMap.size() );
|
return getAllManagedTypes().stream()
|
||||||
for ( ManagedDomainType<?> value : jpaManagedTypes ) {
|
.filter( EntityType.class::isInstance )
|
||||||
if ( value instanceof EntityType<?> ) {
|
.map( t -> (EntityType<?>) t )
|
||||||
entityTypes.add( (EntityType<?>) value );
|
.collect( Collectors.toSet() );
|
||||||
}
|
|
||||||
}
|
|
||||||
return entityTypes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<EmbeddableType<?>> getEmbeddables() {
|
public Set<EmbeddableType<?>> getEmbeddables() {
|
||||||
return new HashSet<>( jpaEmbeddables );
|
return getAllManagedTypes().stream()
|
||||||
|
.filter( EmbeddableType.class::isInstance )
|
||||||
|
.map( t -> (EmbeddableType<?>) t )
|
||||||
|
.collect( Collectors.toSet() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -454,9 +495,9 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
||||||
public <T> EntityDomainType<T> resolveEntityReference(Class<T> javaType) {
|
public <T> EntityDomainType<T> resolveEntityReference(Class<T> javaType) {
|
||||||
// try the incoming Java type as a "strict" entity reference
|
// try the incoming Java type as a "strict" entity reference
|
||||||
{
|
{
|
||||||
final EntityDomainType<?> descriptor = jpaEntityTypeMap.get( javaType.getName() );
|
final ManagedDomainType<?> managedType = managedTypeByClass.get( javaType );
|
||||||
if ( descriptor != null ) {
|
if ( managedType instanceof EntityDomainType<?> ) {
|
||||||
return (EntityDomainType<T>) descriptor;
|
return (EntityDomainType<T>) managedType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -464,7 +505,7 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
||||||
{
|
{
|
||||||
final String proxyEntityName = entityProxyInterfaceMap.get( javaType );
|
final String proxyEntityName = entityProxyInterfaceMap.get( javaType );
|
||||||
if ( proxyEntityName != null ) {
|
if ( proxyEntityName != null ) {
|
||||||
return (EntityDomainType<T>) jpaEntityTypeMap.get( proxyEntityName );
|
return entity( proxyEntityName );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,9 +519,12 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
||||||
|
|
||||||
// create a set of descriptors that should be used to build the polymorphic EntityDomainType
|
// create a set of descriptors that should be used to build the polymorphic EntityDomainType
|
||||||
final Set<EntityDomainType<? extends T>> matchingDescriptors = new HashSet<>();
|
final Set<EntityDomainType<? extends T>> matchingDescriptors = new HashSet<>();
|
||||||
for ( EntityDomainType<?> entityDomainType : jpaEntityTypeMap.values() ) {
|
for ( ManagedDomainType<?> managedType : managedTypeByName.values() ) {
|
||||||
|
if ( managedType.getPersistenceType() != Type.PersistenceType.ENTITY ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// see if we should add `entityDomainType` as one of the matching-descriptors.
|
// see if we should add `entityDomainType` as one of the matching-descriptors.
|
||||||
if ( javaType.isAssignableFrom( entityDomainType.getJavaType() ) ) {
|
if ( javaType.isAssignableFrom( managedType.getJavaType() ) ) {
|
||||||
// the queried type is assignable from the type of the current entity-type
|
// the queried type is assignable from the type of the current entity-type
|
||||||
// we should add it to the collecting set of matching descriptors. it should
|
// we should add it to the collecting set of matching descriptors. it should
|
||||||
// be added aside from a few cases...
|
// be added aside from a few cases...
|
||||||
|
@ -488,7 +532,7 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
||||||
// it should not be added if its direct super (if one) is defined without
|
// it should not be added if its direct super (if one) is defined without
|
||||||
// explicit-polymorphism. The super itself will get added and the initializers
|
// explicit-polymorphism. The super itself will get added and the initializers
|
||||||
// for entity mappings already handle loading subtypes - adding it would be redundant
|
// for entity mappings already handle loading subtypes - adding it would be redundant
|
||||||
final ManagedDomainType<?> superType = entityDomainType.getSuperType();
|
final ManagedDomainType<?> superType = managedType.getSuperType();
|
||||||
if ( superType != null
|
if ( superType != null
|
||||||
&& superType.getPersistenceType() == Type.PersistenceType.ENTITY
|
&& superType.getPersistenceType() == Type.PersistenceType.ENTITY
|
||||||
&& javaType.isAssignableFrom( superType.getJavaType() ) ) {
|
&& javaType.isAssignableFrom( superType.getJavaType() ) ) {
|
||||||
|
@ -501,13 +545,13 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
||||||
|
|
||||||
// it should not be added if it is mapped with explicit polymorphism itself
|
// it should not be added if it is mapped with explicit polymorphism itself
|
||||||
final EntityMappingType entityPersister = getMappingMetamodel()
|
final EntityMappingType entityPersister = getMappingMetamodel()
|
||||||
.getEntityDescriptor( entityDomainType.getHibernateEntityName() );
|
.getEntityDescriptor( managedType.getTypeName() );
|
||||||
if ( entityPersister.isExplicitPolymorphism() ) {
|
if ( entityPersister.isExplicitPolymorphism() ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// aside from these special cases, add it
|
// aside from these special cases, add it
|
||||||
matchingDescriptors.add( (EntityDomainType<? extends T>) entityDomainType );
|
matchingDescriptors.add( (EntityDomainType<? extends T>) managedType );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,55 +602,27 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable {
|
||||||
|
|
||||||
context.wrapUp();
|
context.wrapUp();
|
||||||
|
|
||||||
for ( Map.Entry<String, IdentifiableDomainType<?>> entry : context.getIdentifiableTypesByName().entrySet() ) {
|
this.jpaMetaModelPopulationSetting = jpaMetaModelPopulationSetting;
|
||||||
if ( entry.getValue() instanceof EntityDomainType<?> ) {
|
|
||||||
this.jpaEntityTypeMap.put( entry.getKey(), (EntityDomainType<?>) entry.getValue() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.jpaManagedTypeMap.putAll( context.getEntityTypeMap() );
|
// Identifiable types (Entities and MappedSuperclasses)
|
||||||
this.jpaManagedTypeMap.putAll( context.getMappedSuperclassTypeMap() );
|
this.managedTypeByName.putAll( context.getIdentifiableTypesByName() );
|
||||||
switch ( jpaMetaModelPopulationSetting ) {
|
this.managedTypeByClass.putAll( context.getEntityTypeMap() );
|
||||||
case IGNORE_UNSUPPORTED:
|
this.managedTypeByClass.putAll( context.getMappedSuperclassTypeMap() );
|
||||||
this.jpaManagedTypes.addAll( context.getEntityTypeMap().values() );
|
|
||||||
this.jpaManagedTypes.addAll( context.getMappedSuperclassTypeMap().values() );
|
|
||||||
break;
|
|
||||||
case ENABLED:
|
|
||||||
this.jpaManagedTypes.addAll( context.getIdentifiableTypesByName().values() );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Embeddable types
|
||||||
|
int mapEmbeddables = 0;
|
||||||
for ( EmbeddableDomainType<?> embeddable : context.getEmbeddableTypeSet() ) {
|
for ( EmbeddableDomainType<?> embeddable : context.getEmbeddableTypeSet() ) {
|
||||||
// Do not register the embeddable types for id classes
|
// Do not register the embeddable types for id classes
|
||||||
if ( embeddable.getExpressibleJavaType() instanceof EntityJavaType<?> ) {
|
if ( embeddable.getExpressibleJavaType() instanceof EntityJavaType<?> ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch ( jpaMetaModelPopulationSetting ) {
|
final Class<?> embeddableClass = embeddable.getJavaType();
|
||||||
case IGNORE_UNSUPPORTED:
|
if ( embeddableClass != Map.class ) {
|
||||||
if ( embeddable.getJavaType() != null && embeddable.getJavaType() != Map.class ) {
|
this.managedTypeByClass.put( embeddable.getJavaType(), embeddable );
|
||||||
this.jpaEmbeddables.add( embeddable );
|
this.managedTypeByName.put( embeddable.getTypeName(), embeddable );
|
||||||
this.jpaManagedTypes.add( embeddable );
|
}
|
||||||
if ( !( embeddable.getExpressibleJavaType() instanceof EntityJavaType<?> ) ) {
|
else {
|
||||||
this.jpaManagedTypeMap.put( embeddable.getJavaType(), embeddable );
|
this.managedTypeByName.put( "dynamic-embeddable-" + mapEmbeddables++, embeddable );
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ENABLED:
|
|
||||||
this.jpaEmbeddables.add( embeddable );
|
|
||||||
this.jpaManagedTypes.add( embeddable );
|
|
||||||
if ( embeddable.getJavaType() != null
|
|
||||||
&& !( embeddable.getExpressibleJavaType() instanceof EntityJavaType<?> ) ) {
|
|
||||||
this.jpaManagedTypeMap.put( embeddable.getJavaType(), embeddable );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DISABLED:
|
|
||||||
if ( embeddable.getJavaType() == null ) {
|
|
||||||
throw new UnsupportedOperationException( "ANY not supported" );
|
|
||||||
}
|
|
||||||
if ( !( embeddable.getExpressibleJavaType() instanceof EntityJavaType<?> ) ) {
|
|
||||||
this.jpaManagedTypeMap.put( embeddable.getJavaType(), embeddable );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -489,11 +489,21 @@ public class MappingMetamodelImpl extends QueryParameterBindingTypeResolverImpl
|
||||||
return jpaMetamodel.getEmbeddables();
|
return jpaMetamodel.getEmbeddables();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <X> ManagedDomainType<X> managedType(String typeName) {
|
||||||
|
return jpaMetamodel.managedType( typeName );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> EntityDomainType<X> entity(String entityName) {
|
public <X> EntityDomainType<X> entity(String entityName) {
|
||||||
return jpaMetamodel.entity( entityName );
|
return jpaMetamodel.entity( entityName );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <X> EmbeddableDomainType<X> embeddable(String embeddableName) {
|
||||||
|
return jpaMetamodel.embeddable( embeddableName );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> EntityDomainType<X> getHqlEntityReference(String entityName) {
|
public <X> EntityDomainType<X> getHqlEntityReference(String entityName) {
|
||||||
return jpaMetamodel.getHqlEntityReference( entityName );
|
return jpaMetamodel.getHqlEntityReference( entityName );
|
||||||
|
|
|
@ -97,7 +97,7 @@ public class DiscriminatorHelper {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> String jdbcLiteral(
|
public static <T> String jdbcLiteral(
|
||||||
T value,
|
T value,
|
||||||
JdbcLiteralFormatter<T> formatter,
|
JdbcLiteralFormatter<T> formatter,
|
||||||
Dialect dialect) {
|
Dialect dialect) {
|
||||||
|
|
|
@ -9,7 +9,9 @@ package org.hibernate.query.hql.internal;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||||
|
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor;
|
import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor;
|
||||||
import org.hibernate.query.SemanticException;
|
import org.hibernate.query.SemanticException;
|
||||||
import org.hibernate.query.hql.HqlLogging;
|
import org.hibernate.query.hql.HqlLogging;
|
||||||
|
@ -24,6 +26,7 @@ import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralEmbeddableType;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||||
import org.hibernate.type.descriptor.java.EnumJavaType;
|
import org.hibernate.type.descriptor.java.EnumJavaType;
|
||||||
|
@ -93,9 +96,16 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void consumeTreat(String entityName, boolean isTerminal) {
|
public void consumeTreat(String importableName, boolean isTerminal) {
|
||||||
final SqmPath<?> path = (SqmPath<?>) currentPart;
|
final SqmPath<?> sqmPath = (SqmPath<?>) currentPart;
|
||||||
currentPart = path.treatAs( creationState.getCreationContext().getJpaMetamodel().entity( entityName ) );
|
currentPart = sqmPath.treatAs( treatTarget( importableName ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> Class<T> treatTarget(String typeName) {
|
||||||
|
final ManagedDomainType<T> managedType = creationState.getCreationContext()
|
||||||
|
.getJpaMetamodel()
|
||||||
|
.managedType( typeName );
|
||||||
|
return managedType.getJavaType();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void reset() {
|
protected void reset() {
|
||||||
|
@ -181,9 +191,12 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
|
||||||
final String importableName = jpaMetamodel.qualifyImportableName( path );
|
final String importableName = jpaMetamodel.qualifyImportableName( path );
|
||||||
final NodeBuilder nodeBuilder = creationContext.getNodeBuilder();
|
final NodeBuilder nodeBuilder = creationContext.getNodeBuilder();
|
||||||
if ( importableName != null ) {
|
if ( importableName != null ) {
|
||||||
final EntityDomainType<?> entityDomainType = jpaMetamodel.entity( importableName );
|
final ManagedDomainType<?> managedType = jpaMetamodel.managedType( importableName );
|
||||||
if ( entityDomainType != null ) {
|
if ( managedType instanceof EntityDomainType<?> ) {
|
||||||
return new SqmLiteralEntityType<>( entityDomainType, nodeBuilder );
|
return new SqmLiteralEntityType<>( ( (EntityDomainType<?>) managedType ), nodeBuilder );
|
||||||
|
}
|
||||||
|
else if ( managedType instanceof EmbeddableDomainType<?> ) {
|
||||||
|
return new SqmLiteralEmbeddableType<>( ( (EmbeddableDomainType<?>) managedType ), nodeBuilder );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.query.hql.internal;
|
package org.hibernate.query.hql.internal;
|
||||||
|
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.query.PathException;
|
import org.hibernate.query.PathException;
|
||||||
import org.hibernate.query.SemanticException;
|
import org.hibernate.query.SemanticException;
|
||||||
import org.hibernate.query.hql.spi.DotIdentifierConsumer;
|
import org.hibernate.query.hql.spi.DotIdentifierConsumer;
|
||||||
|
@ -239,7 +240,7 @@ public class QualifiedJoinPathConsumer implements DotIdentifierConsumer {
|
||||||
|
|
||||||
private interface ConsumerDelegate {
|
private interface ConsumerDelegate {
|
||||||
void consumeIdentifier(String identifier, boolean isTerminal, boolean allowReuse);
|
void consumeIdentifier(String identifier, boolean isTerminal, boolean allowReuse);
|
||||||
void consumeTreat(String entityName, boolean isTerminal);
|
void consumeTreat(String typeName, boolean isTerminal);
|
||||||
SemanticPathPart getConsumedPart();
|
SemanticPathPart getConsumedPart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,20 +281,23 @@ public class QualifiedJoinPathConsumer implements DotIdentifierConsumer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void consumeTreat(String entityName, boolean isTerminal) {
|
public void consumeTreat(String typeName, boolean isTerminal) {
|
||||||
if ( isTerminal ) {
|
if ( isTerminal ) {
|
||||||
currentPath = fetch
|
currentPath = fetch
|
||||||
? ( (SqmAttributeJoin<?, ?>) currentPath ).treatAs( treatTarget( entityName ), alias, true )
|
? ( (SqmAttributeJoin<?, ?>) currentPath ).treatAs( treatTarget( typeName ), alias, true )
|
||||||
: currentPath.treatAs( treatTarget( entityName ), alias );
|
: currentPath.treatAs( treatTarget( typeName ), alias );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
currentPath = currentPath.treatAs( treatTarget( entityName ) );
|
currentPath = currentPath.treatAs( treatTarget( typeName ) );
|
||||||
}
|
}
|
||||||
creationState.getCurrentProcessingState().getPathRegistry().register( currentPath );
|
creationState.getCurrentProcessingState().getPathRegistry().register( currentPath );
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> EntityDomainType<T> treatTarget(String entityName) {
|
private <T> Class<T> treatTarget(String typeName) {
|
||||||
return creationState.getCreationContext().getJpaMetamodel().entity(entityName);
|
final ManagedDomainType<T> managedType = creationState.getCreationContext()
|
||||||
|
.getJpaMetamodel()
|
||||||
|
.managedType( typeName );
|
||||||
|
return managedType.getJavaType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -364,7 +368,7 @@ public class QualifiedJoinPathConsumer implements DotIdentifierConsumer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void consumeTreat(String entityName, boolean isTerminal) {
|
public void consumeTreat(String typeName, boolean isTerminal) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5481,14 +5481,13 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
consumeManagedTypeReference( ctx.path() );
|
consumeManagedTypeReference( ctx.path() );
|
||||||
|
|
||||||
final String treatTargetName = ctx.simplePath().getText();
|
final String treatTargetName = ctx.simplePath().getText();
|
||||||
final String treatTargetEntityName =
|
final String importableName = getCreationContext().getJpaMetamodel().qualifyImportableName( treatTargetName );
|
||||||
getCreationContext().getJpaMetamodel().qualifyImportableName( treatTargetName );
|
if ( importableName == null ) {
|
||||||
if ( treatTargetEntityName == null ) {
|
|
||||||
throw new SemanticException( "Could not resolve treat target type '" + treatTargetName + "'", query );
|
throw new SemanticException( "Could not resolve treat target type '" + treatTargetName + "'", query );
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean hasContinuation = ctx.getChildCount() == 7;
|
final boolean hasContinuation = ctx.getChildCount() == 7;
|
||||||
consumer.consumeTreat( treatTargetEntityName, !hasContinuation );
|
consumer.consumeTreat( importableName, !hasContinuation );
|
||||||
SqmPath<?> result = (SqmPath<?>) consumer.getConsumedPart();
|
SqmPath<?> result = (SqmPath<?>) consumer.getConsumedPart();
|
||||||
|
|
||||||
if ( hasContinuation ) {
|
if ( hasContinuation ) {
|
||||||
|
|
|
@ -8,8 +8,8 @@ package org.hibernate.query.sqm;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.model.domain.DiscriminatorSqmPath;
|
||||||
import org.hibernate.metamodel.model.domain.internal.AnyDiscriminatorSqmPath;
|
import org.hibernate.metamodel.model.domain.internal.AnyDiscriminatorSqmPath;
|
||||||
import org.hibernate.metamodel.model.domain.internal.EntityDiscriminatorSqmPath;
|
|
||||||
import org.hibernate.query.sqm.tree.cte.SqmCteContainer;
|
import org.hibernate.query.sqm.tree.cte.SqmCteContainer;
|
||||||
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
|
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
|
||||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||||
|
@ -67,6 +67,7 @@ import org.hibernate.query.sqm.tree.expression.SqmFormat;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralEmbeddableType;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
|
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
|
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
|
||||||
|
@ -238,7 +239,7 @@ public interface SemanticQueryWalker<T> {
|
||||||
|
|
||||||
T visitFkExpression(SqmFkExpression<?> fkExpression);
|
T visitFkExpression(SqmFkExpression<?> fkExpression);
|
||||||
|
|
||||||
T visitDiscriminatorPath(EntityDiscriminatorSqmPath sqmPath);
|
T visitDiscriminatorPath(DiscriminatorSqmPath<?> sqmPath);
|
||||||
|
|
||||||
T visitIndexedPluralAccessPath(SqmIndexedCollectionAccessPath<?> path);
|
T visitIndexedPluralAccessPath(SqmIndexedCollectionAccessPath<?> path);
|
||||||
|
|
||||||
|
@ -320,6 +321,8 @@ public interface SemanticQueryWalker<T> {
|
||||||
|
|
||||||
T visitEntityTypeLiteralExpression(SqmLiteralEntityType<?> expression);
|
T visitEntityTypeLiteralExpression(SqmLiteralEntityType<?> expression);
|
||||||
|
|
||||||
|
T visitEmbeddableTypeLiteralExpression(SqmLiteralEmbeddableType<?> expression);
|
||||||
|
|
||||||
T visitAnyDiscriminatorTypeExpression(AnyDiscriminatorSqmPath<?> expression);
|
T visitAnyDiscriminatorTypeExpression(AnyDiscriminatorSqmPath<?> expression);
|
||||||
|
|
||||||
T visitAnyDiscriminatorTypeValueExpression(SqmAnyDiscriminatorValue<?> expression);
|
T visitAnyDiscriminatorTypeValueExpression(SqmAnyDiscriminatorValue<?> expression);
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.DomainType;
|
import org.hibernate.metamodel.model.domain.DomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType;
|
import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.internal.AnyMappingSqmPathSource;
|
import org.hibernate.metamodel.model.domain.internal.AnyMappingSqmPathSource;
|
||||||
import org.hibernate.metamodel.model.domain.internal.BasicSqmPathSource;
|
import org.hibernate.metamodel.model.domain.internal.BasicSqmPathSource;
|
||||||
|
@ -35,7 +36,6 @@ import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||||
import org.hibernate.query.sqm.tree.cte.SqmCteTable;
|
import org.hibernate.query.sqm.tree.cte.SqmCteTable;
|
||||||
import org.hibernate.query.sqm.tree.domain.AbstractSqmSpecificPluralPartPath;
|
import org.hibernate.query.sqm.tree.domain.AbstractSqmSpecificPluralPartPath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor;
|
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
|
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
|
||||||
import org.hibernate.spi.NavigablePath;
|
import org.hibernate.spi.NavigablePath;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
|
@ -43,6 +43,7 @@ import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.descriptor.java.JavaType;
|
import org.hibernate.type.descriptor.java.JavaType;
|
||||||
|
|
||||||
import jakarta.persistence.metamodel.Bindable;
|
import jakarta.persistence.metamodel.Bindable;
|
||||||
|
import jakarta.persistence.metamodel.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper for dealing with Hibernate's "mapping model" while processing an SQM which is defined
|
* Helper for dealing with Hibernate's "mapping model" while processing an SQM which is defined
|
||||||
|
@ -180,17 +181,21 @@ public class SqmMappingModelHelper {
|
||||||
|
|
||||||
if ( sqmPath instanceof SqmTreatedPath<?, ?> ) {
|
if ( sqmPath instanceof SqmTreatedPath<?, ?> ) {
|
||||||
final SqmTreatedPath<?, ?> treatedPath = (SqmTreatedPath<?, ?>) sqmPath;
|
final SqmTreatedPath<?, ?> treatedPath = (SqmTreatedPath<?, ?>) sqmPath;
|
||||||
final EntityDomainType<?> treatTargetType = treatedPath.getTreatTarget();
|
final ManagedDomainType<?> treatTarget = treatedPath.getTreatTarget();
|
||||||
return domainModel.findEntityDescriptor( treatTargetType.getHibernateEntityName() );
|
if ( treatTarget.getPersistenceType() == Type.PersistenceType.ENTITY ) {
|
||||||
|
final EntityDomainType<?> treatTargetType = (EntityDomainType<?>) treatTarget;
|
||||||
|
return domainModel.findEntityDescriptor( treatTargetType.getHibernateEntityName() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// see if the LHS is treated
|
// see if the LHS is treated
|
||||||
if ( sqmPath.getLhs() instanceof SqmTreatedPath<?, ?> ) {
|
if ( sqmPath.getLhs() instanceof SqmTreatedPath<?, ?> ) {
|
||||||
final SqmTreatedPath<?, ?> treatedPath = (SqmTreatedPath<?, ?>) sqmPath.getLhs();
|
final SqmTreatedPath<?, ?> treatedPath = (SqmTreatedPath<?, ?>) sqmPath.getLhs();
|
||||||
final EntityDomainType<?> treatTargetType = treatedPath.getTreatTarget();
|
final ManagedDomainType<?> treatTarget = treatedPath.getTreatTarget();
|
||||||
final EntityPersister container = domainModel.findEntityDescriptor( treatTargetType.getHibernateEntityName() );
|
if ( treatTarget.getPersistenceType() == Type.PersistenceType.ENTITY ) {
|
||||||
|
final EntityPersister container = domainModel.findEntityDescriptor( treatTarget.getTypeName() );
|
||||||
return container.findSubPart( sqmPath.getNavigablePath().getLocalName(), container );
|
return container.findSubPart( sqmPath.getNavigablePath().getLocalName(), container );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plural path parts are not joined and thus also have no table group
|
// Plural path parts are not joined and thus also have no table group
|
||||||
|
@ -253,9 +258,15 @@ public class SqmMappingModelHelper {
|
||||||
SqmPath<?> sqmPath,
|
SqmPath<?> sqmPath,
|
||||||
SqmToSqlAstConverter converter) {
|
SqmToSqlAstConverter converter) {
|
||||||
final SqmPath<?> parentPath = sqmPath.getLhs();
|
final SqmPath<?> parentPath = sqmPath.getLhs();
|
||||||
if ( parentPath instanceof SqmTreatedPath ) {
|
if ( parentPath instanceof SqmTreatedPath<?, ?> ) {
|
||||||
final SqmTreatedPath<?, ?> treatedPath = (SqmTreatedPath<?, ?>) parentPath;
|
final SqmTreatedPath<?, ?> treatedPath = (SqmTreatedPath<?, ?>) parentPath;
|
||||||
return resolveEntityPersister( treatedPath.getTreatTarget(), converter.getCreationContext().getSessionFactory() );
|
final ManagedDomainType<?> treatTarget = treatedPath.getTreatTarget();
|
||||||
|
if ( treatTarget.getPersistenceType() == Type.PersistenceType.ENTITY ) {
|
||||||
|
return resolveEntityPersister(
|
||||||
|
( (EntityDomainType<?>) treatTarget ),
|
||||||
|
converter.getCreationContext().getSessionFactory()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -9,8 +9,8 @@ package org.hibernate.query.sqm.internal;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.model.domain.DiscriminatorSqmPath;
|
||||||
import org.hibernate.metamodel.model.domain.internal.AnyDiscriminatorSqmPath;
|
import org.hibernate.metamodel.model.domain.internal.AnyDiscriminatorSqmPath;
|
||||||
import org.hibernate.metamodel.model.domain.internal.EntityDiscriminatorSqmPath;
|
|
||||||
import org.hibernate.query.QueryLogging;
|
import org.hibernate.query.QueryLogging;
|
||||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||||
|
@ -56,6 +56,7 @@ import org.hibernate.query.sqm.tree.expression.SqmFormat;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralEmbeddableType;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
|
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
|
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
|
||||||
|
@ -723,7 +724,7 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitDiscriminatorPath(EntityDiscriminatorSqmPath sqmPath) {
|
public Object visitDiscriminatorPath(DiscriminatorSqmPath<?> sqmPath) {
|
||||||
logWithIndentation( "-> [discriminator-path] - `%s`", sqmPath.getNavigablePath() );
|
logWithIndentation( "-> [discriminator-path] - `%s`", sqmPath.getNavigablePath() );
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -807,6 +808,11 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object visitEmbeddableTypeLiteralExpression(SqmLiteralEmbeddableType<?> expression) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitParameterizedEntityTypeExpression(SqmParameterizedEntityType expression) {
|
public Object visitParameterizedEntityTypeExpression(SqmParameterizedEntityType expression) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -7,13 +7,14 @@
|
||||||
package org.hibernate.query.sqm.internal;
|
package org.hibernate.query.sqm.internal;
|
||||||
|
|
||||||
import jakarta.persistence.criteria.Expression;
|
import jakarta.persistence.criteria.Expression;
|
||||||
import jakarta.persistence.metamodel.EmbeddableType;
|
|
||||||
import jakarta.persistence.metamodel.EntityType;
|
import jakarta.persistence.metamodel.EntityType;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
import org.hibernate.metamodel.model.domain.DomainType;
|
import org.hibernate.metamodel.model.domain.DomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.TupleType;
|
import org.hibernate.metamodel.model.domain.TupleType;
|
||||||
import org.hibernate.metamodel.model.domain.internal.DiscriminatorSqmPathSource;
|
import org.hibernate.metamodel.model.domain.internal.EntityDiscriminatorSqmPathSource;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.query.SemanticException;
|
import org.hibernate.query.SemanticException;
|
||||||
import org.hibernate.query.sqm.BinaryArithmeticOperator;
|
import org.hibernate.query.sqm.BinaryArithmeticOperator;
|
||||||
|
@ -128,8 +129,8 @@ public class TypecheckUtil {
|
||||||
|
|
||||||
// for embeddables, the embeddable class must match exactly
|
// for embeddables, the embeddable class must match exactly
|
||||||
|
|
||||||
final EmbeddableType<?> lhsEmbeddable = getEmbeddableType( lhsDomainType );
|
final EmbeddableDomainType<?> lhsEmbeddable = getEmbeddableType( lhsDomainType );
|
||||||
final EmbeddableType<?> rhsEmbeddable = getEmbeddableType( rhsDomainType );
|
final EmbeddableDomainType<?> rhsEmbeddable = getEmbeddableType( rhsDomainType );
|
||||||
if ( lhsEmbeddable != null && rhsEmbeddable != null ) {
|
if ( lhsEmbeddable != null && rhsEmbeddable != null ) {
|
||||||
return areEmbeddableTypesComparable( lhsEmbeddable, rhsEmbeddable );
|
return areEmbeddableTypesComparable( lhsEmbeddable, rhsEmbeddable );
|
||||||
}
|
}
|
||||||
|
@ -157,11 +158,11 @@ public class TypecheckUtil {
|
||||||
// entities can be compared to discriminators if they belong to
|
// entities can be compared to discriminators if they belong to
|
||||||
// the same inheritance hierarchy
|
// the same inheritance hierarchy
|
||||||
|
|
||||||
if ( lhsDomainType instanceof DiscriminatorSqmPathSource ) {
|
if ( lhsDomainType instanceof EntityDiscriminatorSqmPathSource ) {
|
||||||
return isDiscriminatorTypeComparable( (DiscriminatorSqmPathSource<?>) lhsDomainType, rhsDomainType, factory );
|
return isDiscriminatorTypeComparable( (EntityDiscriminatorSqmPathSource<?>) lhsDomainType, rhsDomainType, factory );
|
||||||
}
|
}
|
||||||
if ( rhsDomainType instanceof DiscriminatorSqmPathSource ) {
|
if ( rhsDomainType instanceof EntityDiscriminatorSqmPathSource ) {
|
||||||
return isDiscriminatorTypeComparable( (DiscriminatorSqmPathSource<?>) rhsDomainType, lhsDomainType, factory );
|
return isDiscriminatorTypeComparable( (EntityDiscriminatorSqmPathSource<?>) rhsDomainType, lhsDomainType, factory );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Treat the expressions as comparable if they belong to the same
|
// Treat the expressions as comparable if they belong to the same
|
||||||
|
@ -197,15 +198,26 @@ public class TypecheckUtil {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static EmbeddableType<?> getEmbeddableType(SqmExpressible<?> expressible) {
|
private static EmbeddableDomainType<?> getEmbeddableType(SqmExpressible<?> expressible) {
|
||||||
return expressible instanceof EmbeddableType<?> ? (EmbeddableType<?>) expressible : null;
|
return expressible instanceof EmbeddableDomainType<?> ? (EmbeddableDomainType<?>) expressible : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean areEmbeddableTypesComparable(
|
private static boolean areEmbeddableTypesComparable(
|
||||||
EmbeddableType<?> lhsType,
|
EmbeddableDomainType<?> lhsType,
|
||||||
EmbeddableType<?> rhsType) {
|
EmbeddableDomainType<?> rhsType) {
|
||||||
// no polymorphism for embeddable types
|
if ( rhsType.getJavaType() == lhsType.getJavaType() ) {
|
||||||
return rhsType.getJavaType() == lhsType.getJavaType();
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lhsType.isPolymorphic() && getRootEmbeddableType( lhsType ) == getRootEmbeddableType( rhsType );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ManagedDomainType<?> getRootEmbeddableType(EmbeddableDomainType<?> embeddableType) {
|
||||||
|
ManagedDomainType<?> rootType = embeddableType;
|
||||||
|
while ( rootType.getSuperType() != null ) {
|
||||||
|
rootType = rootType.getSuperType();
|
||||||
|
}
|
||||||
|
return rootType;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean areTupleTypesComparable(
|
private static boolean areTupleTypesComparable(
|
||||||
|
@ -234,7 +246,7 @@ public class TypecheckUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isDiscriminatorTypeComparable(
|
private static boolean isDiscriminatorTypeComparable(
|
||||||
DiscriminatorSqmPathSource<?> lhsDiscriminator, SqmExpressible<?> rhsType,
|
EntityDiscriminatorSqmPathSource<?> lhsDiscriminator, SqmExpressible<?> rhsType,
|
||||||
SessionFactoryImplementor factory) {
|
SessionFactoryImplementor factory) {
|
||||||
String entityName = lhsDiscriminator.getEntityDomainType().getHibernateEntityName();
|
String entityName = lhsDiscriminator.getEntityDomainType().getHibernateEntityName();
|
||||||
EntityPersister lhsEntity = factory.getMappingMetamodel().getEntityDescriptor( entityName );
|
EntityPersister lhsEntity = factory.getMappingMetamodel().getEntityDescriptor( entityName );
|
||||||
|
@ -243,8 +255,8 @@ public class TypecheckUtil {
|
||||||
EntityPersister rhsEntity = getEntityDescriptor( factory, rhsEntityName );
|
EntityPersister rhsEntity = getEntityDescriptor( factory, rhsEntityName );
|
||||||
return lhsEntity.getRootEntityName().equals( rhsEntity.getRootEntityName() );
|
return lhsEntity.getRootEntityName().equals( rhsEntity.getRootEntityName() );
|
||||||
}
|
}
|
||||||
else if ( rhsType instanceof DiscriminatorSqmPathSource ) {
|
else if ( rhsType instanceof EntityDiscriminatorSqmPathSource ) {
|
||||||
DiscriminatorSqmPathSource<?> discriminator = (DiscriminatorSqmPathSource<?>) rhsType;
|
EntityDiscriminatorSqmPathSource<?> discriminator = (EntityDiscriminatorSqmPathSource<?>) rhsType;
|
||||||
String rhsEntityName = discriminator.getEntityDomainType().getHibernateEntityName();
|
String rhsEntityName = discriminator.getEntityDomainType().getHibernateEntityName();
|
||||||
EntityPersister rhsEntity = factory.getMappingMetamodel().getEntityDescriptor( rhsEntityName );
|
EntityPersister rhsEntity = factory.getMappingMetamodel().getEntityDescriptor( rhsEntityName );
|
||||||
return rhsEntity.getRootEntityName().equals( lhsEntity.getRootEntityName() );
|
return rhsEntity.getRootEntityName().equals( lhsEntity.getRootEntityName() );
|
||||||
|
|
|
@ -8,8 +8,8 @@ package org.hibernate.query.sqm.spi;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.model.domain.DiscriminatorSqmPath;
|
||||||
import org.hibernate.metamodel.model.domain.internal.AnyDiscriminatorSqmPath;
|
import org.hibernate.metamodel.model.domain.internal.AnyDiscriminatorSqmPath;
|
||||||
import org.hibernate.metamodel.model.domain.internal.EntityDiscriminatorSqmPath;
|
|
||||||
import org.hibernate.query.sqm.InterpretationException;
|
import org.hibernate.query.sqm.InterpretationException;
|
||||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||||
|
@ -57,6 +57,7 @@ import org.hibernate.query.sqm.tree.expression.SqmFormat;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralEmbeddableType;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
|
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
|
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
|
||||||
|
@ -468,7 +469,7 @@ public abstract class BaseSemanticQueryWalker implements SemanticQueryWalker<Obj
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitDiscriminatorPath(EntityDiscriminatorSqmPath path) {
|
public Object visitDiscriminatorPath(DiscriminatorSqmPath<?> path) {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -719,6 +720,11 @@ public abstract class BaseSemanticQueryWalker implements SemanticQueryWalker<Obj
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object visitEmbeddableTypeLiteralExpression(SqmLiteralEmbeddableType<?> expression) {
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitAnyDiscriminatorTypeExpression(AnyDiscriminatorSqmPath<?> expression) {
|
public Object visitAnyDiscriminatorTypeExpression(AnyDiscriminatorSqmPath<?> expression) {
|
||||||
return expression;
|
return expression;
|
||||||
|
|
|
@ -74,8 +74,10 @@ import org.hibernate.metamodel.mapping.internal.SqlTypedMappingImpl;
|
||||||
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.ordering.OrderByFragment;
|
import org.hibernate.metamodel.mapping.ordering.OrderByFragment;
|
||||||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.DiscriminatorSqmPath;
|
||||||
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
||||||
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
||||||
import org.hibernate.metamodel.model.domain.internal.AnyDiscriminatorSqmPath;
|
import org.hibernate.metamodel.model.domain.internal.AnyDiscriminatorSqmPath;
|
||||||
|
@ -198,6 +200,7 @@ import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
|
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralEmbeddableType;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralNull;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralNull;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
|
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
|
||||||
|
@ -301,6 +304,7 @@ import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
import org.hibernate.sql.ast.tree.expression.Distinct;
|
import org.hibernate.sql.ast.tree.expression.Distinct;
|
||||||
import org.hibernate.sql.ast.tree.expression.Duration;
|
import org.hibernate.sql.ast.tree.expression.Duration;
|
||||||
import org.hibernate.sql.ast.tree.expression.DurationUnit;
|
import org.hibernate.sql.ast.tree.expression.DurationUnit;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.EmbeddableTypeLiteral;
|
||||||
import org.hibernate.sql.ast.tree.expression.EntityTypeLiteral;
|
import org.hibernate.sql.ast.tree.expression.EntityTypeLiteral;
|
||||||
import org.hibernate.sql.ast.tree.expression.Every;
|
import org.hibernate.sql.ast.tree.expression.Every;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
|
@ -424,6 +428,7 @@ import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import static jakarta.persistence.metamodel.Type.PersistenceType.ENTITY;
|
||||||
import static java.util.Collections.singletonList;
|
import static java.util.Collections.singletonList;
|
||||||
import static org.hibernate.boot.model.internal.SoftDeleteHelper.createNonSoftDeletedRestriction;
|
import static org.hibernate.boot.model.internal.SoftDeleteHelper.createNonSoftDeletedRestriction;
|
||||||
import static org.hibernate.generator.EventType.INSERT;
|
import static org.hibernate.generator.EventType.INSERT;
|
||||||
|
@ -2475,14 +2480,11 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
private Predicate visitWhereClause(SqmPredicate sqmPredicate) {
|
private Predicate visitWhereClause(SqmPredicate sqmPredicate) {
|
||||||
if ( sqmPredicate == null ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
currentClauseStack.push( Clause.WHERE );
|
currentClauseStack.push( Clause.WHERE );
|
||||||
inferrableTypeAccessStack.push( () -> null );
|
inferrableTypeAccessStack.push( () -> null );
|
||||||
try {
|
try {
|
||||||
return combinePredicates(
|
return combinePredicates(
|
||||||
(Predicate) sqmPredicate.accept( this ),
|
sqmPredicate != null ? (Predicate) sqmPredicate.accept( this ) : null,
|
||||||
consumeConjunctTreatTypeRestrictions()
|
consumeConjunctTreatTypeRestrictions()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2494,14 +2496,11 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Predicate visitHavingClause(SqmPredicate sqmPredicate) {
|
public Predicate visitHavingClause(SqmPredicate sqmPredicate) {
|
||||||
if ( sqmPredicate == null ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
currentClauseStack.push( Clause.HAVING );
|
currentClauseStack.push( Clause.HAVING );
|
||||||
inferrableTypeAccessStack.push( () -> null );
|
inferrableTypeAccessStack.push( () -> null );
|
||||||
try {
|
try {
|
||||||
return combinePredicates(
|
return combinePredicates(
|
||||||
(Predicate) sqmPredicate.accept( this ),
|
sqmPredicate != null ? (Predicate) sqmPredicate.accept( this ) : null,
|
||||||
consumeConjunctTreatTypeRestrictions()
|
consumeConjunctTreatTypeRestrictions()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2911,10 +2910,10 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
* If the path is a treat, registers {@link EntityNameUse#TREAT} for all treated subtypes instead.
|
* If the path is a treat, registers {@link EntityNameUse#TREAT} for all treated subtypes instead.
|
||||||
*/
|
*/
|
||||||
private void registerEntityNameProjectionUsage(SqmPath<?> projectedPath, TableGroup tableGroup) {
|
private void registerEntityNameProjectionUsage(SqmPath<?> projectedPath, TableGroup tableGroup) {
|
||||||
final EntityDomainType<?> treatedType;
|
final ManagedDomainType<?> treatedType;
|
||||||
if ( projectedPath instanceof SqmTreatedPath<?, ?> ) {
|
if ( projectedPath instanceof SqmTreatedPath<?, ?> ) {
|
||||||
treatedType = ( (SqmTreatedPath<?, ?>) projectedPath ).getTreatTarget();
|
treatedType = ( (SqmTreatedPath<?, ?>) projectedPath ).getTreatTarget();
|
||||||
registerEntityNameUsage( tableGroup, EntityNameUse.TREAT, treatedType.getHibernateEntityName(), true );
|
registerEntityNameUsage( tableGroup, EntityNameUse.TREAT, treatedType.getTypeName(), true );
|
||||||
|
|
||||||
if ( projectedPath instanceof SqmFrom<?, ?> ) {
|
if ( projectedPath instanceof SqmFrom<?, ?> ) {
|
||||||
// Register that the TREAT uses for the SqmFrom node may not be downgraded
|
// Register that the TREAT uses for the SqmFrom node may not be downgraded
|
||||||
|
@ -2926,7 +2925,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
}
|
}
|
||||||
else if ( projectedPath.getNodeType().getSqmPathType() instanceof EntityDomainType<?> ) {
|
else if ( projectedPath.getNodeType().getSqmPathType() instanceof EntityDomainType<?> ) {
|
||||||
treatedType = (EntityDomainType<?>) projectedPath.getNodeType().getSqmPathType();
|
treatedType = (EntityDomainType<?>) projectedPath.getNodeType().getSqmPathType();
|
||||||
registerEntityNameUsage( tableGroup, EntityNameUse.PROJECTION, treatedType.getHibernateEntityName(), true );
|
registerEntityNameUsage( tableGroup, EntityNameUse.PROJECTION, treatedType.getTypeName(), true );
|
||||||
|
|
||||||
if ( projectedPath instanceof SqmFrom<?, ?> ) {
|
if ( projectedPath instanceof SqmFrom<?, ?> ) {
|
||||||
// Register that the TREAT uses for the SqmFrom node may not be downgraded
|
// Register that the TREAT uses for the SqmFrom node may not be downgraded
|
||||||
|
@ -2970,31 +2969,33 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
final EntityMappingType parentType;
|
final EntityMappingType parentType;
|
||||||
if ( parentPath instanceof SqmTreatedPath<?, ?> ) {
|
if ( parentPath instanceof SqmTreatedPath<?, ?> ) {
|
||||||
// A treated attribute usage i.e. `treat(alias as Subtype).attribute = 1`
|
// A treated attribute usage i.e. `treat(alias as Subtype).attribute = 1`
|
||||||
|
final ManagedDomainType<?> treatTarget = ( (SqmTreatedPath<?, ?>) parentPath ).getTreatTarget();
|
||||||
|
if ( treatTarget.getPersistenceType() == ENTITY ) {
|
||||||
|
parentType = creationContext.getMappingMetamodel().getEntityDescriptor( treatTarget.getTypeName() );
|
||||||
|
|
||||||
final EntityDomainType<?> treatTarget = ( (SqmTreatedPath<?, ?>) parentPath ).getTreatTarget();
|
// The following is an optimization to avoid rendering treat conditions into predicates.
|
||||||
|
// Imagine an HQL predicate like `treat(alias as Subtype).attribute is null or alias.name = '...'`.
|
||||||
|
// If the `attribute` is basic, we will render a case wrapper around the column expression
|
||||||
|
// and hence we can safely skip adding the `type(alias) = Subtype and ...` condition to the SQL.
|
||||||
|
|
||||||
parentType = creationContext.getMappingMetamodel()
|
final ModelPart subPart = parentType.findSubPart( attributeName );
|
||||||
.getEntityDescriptor( treatTarget.getHibernateEntityName() );
|
final EntityNameUse entityNameUse;
|
||||||
|
// We only apply this optimization for basic valued model parts for now
|
||||||
// The following is an optimization to avoid rendering treat conditions into predicates.
|
if ( subPart.asBasicValuedModelPart() != null ) {
|
||||||
// Imagine an HQL predicate like `treat(alias as Subtype).attribute is null or alias.name = '...'`.
|
entityNameUse = EntityNameUse.OPTIONAL_TREAT;
|
||||||
// If the `attribute` is basic, we will render a case wrapper around the column expression
|
}
|
||||||
// and hence we can safely skip adding the `type(alias) = Subtype and ...` condition to the SQL.
|
else {
|
||||||
|
entityNameUse = EntityNameUse.BASE_TREAT;
|
||||||
final ModelPart subPart = parentType.findSubPart( attributeName );
|
}
|
||||||
final EntityNameUse entityNameUse;
|
registerEntityNameUsage(
|
||||||
// We only apply this optimization for basic valued model parts for now
|
tableGroup,
|
||||||
if ( subPart.asBasicValuedModelPart() != null ) {
|
entityNameUse,
|
||||||
entityNameUse = EntityNameUse.OPTIONAL_TREAT;
|
treatTarget.getTypeName()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
entityNameUse = EntityNameUse.BASE_TREAT;
|
parentType = entityType;
|
||||||
}
|
}
|
||||||
registerEntityNameUsage(
|
|
||||||
tableGroup,
|
|
||||||
entityNameUse,
|
|
||||||
treatTarget.getHibernateEntityName()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// A simple attribute usage e.g. `alias.attribute = 1`
|
// A simple attribute usage e.g. `alias.attribute = 1`
|
||||||
|
@ -3047,11 +3048,11 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
public void registerEntityNameUsage(
|
public void registerEntityNameUsage(
|
||||||
TableGroup tableGroup,
|
TableGroup tableGroup,
|
||||||
EntityNameUse entityNameUse,
|
EntityNameUse entityNameUse,
|
||||||
String hibernateEntityName) {
|
String treatTargetTypeName) {
|
||||||
registerEntityNameUsage(
|
registerEntityNameUsage(
|
||||||
tableGroup,
|
tableGroup,
|
||||||
entityNameUse,
|
entityNameUse,
|
||||||
hibernateEntityName,
|
treatTargetTypeName,
|
||||||
entityNameUse.getKind() == EntityNameUse.UseKind.PROJECTION
|
entityNameUse.getKind() == EntityNameUse.UseKind.PROJECTION
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -3059,14 +3060,27 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
private void registerEntityNameUsage(
|
private void registerEntityNameUsage(
|
||||||
TableGroup tableGroup,
|
TableGroup tableGroup,
|
||||||
EntityNameUse entityNameUse,
|
EntityNameUse entityNameUse,
|
||||||
String hibernateEntityName,
|
String treatTargetTypeName,
|
||||||
boolean projection) {
|
boolean projection) {
|
||||||
final AbstractEntityPersister persister = (AbstractEntityPersister) creationContext.getSessionFactory()
|
final AbstractEntityPersister persister;
|
||||||
.getRuntimeMetamodels()
|
if ( tableGroup.getModelPart() instanceof EmbeddableValuedModelPart ) {
|
||||||
.getMappingMetamodel()
|
persister = null;
|
||||||
.findEntityDescriptor( hibernateEntityName );
|
final EmbeddableDomainType<?> embeddableDomainType = creationContext.getSessionFactory()
|
||||||
if ( persister == null || !persister.isPolymorphic() ) {
|
.getRuntimeMetamodels()
|
||||||
return;
|
.getJpaMetamodel()
|
||||||
|
.embeddable( treatTargetTypeName );
|
||||||
|
if ( embeddableDomainType == null || !embeddableDomainType.isPolymorphic() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
persister = (AbstractEntityPersister) creationContext.getSessionFactory()
|
||||||
|
.getRuntimeMetamodels()
|
||||||
|
.getMappingMetamodel()
|
||||||
|
.findEntityDescriptor( treatTargetTypeName );
|
||||||
|
if ( persister == null || !persister.isPolymorphic() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
final TableGroup actualTableGroup;
|
final TableGroup actualTableGroup;
|
||||||
final EntityNameUse finalEntityNameUse;
|
final EntityNameUse finalEntityNameUse;
|
||||||
|
@ -3094,10 +3108,15 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
tg -> new HashMap<>( 1 )
|
tg -> new HashMap<>( 1 )
|
||||||
);
|
);
|
||||||
entityNameUses.compute(
|
entityNameUses.compute(
|
||||||
hibernateEntityName,
|
treatTargetTypeName,
|
||||||
(s, existingUse) -> finalEntityNameUse.stronger( existingUse )
|
(s, existingUse) -> finalEntityNameUse.stronger( existingUse )
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ( persister == null ) {
|
||||||
|
// No need to do anything else for embeddables
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Resolve the table reference for all types which we register an entity name use for.
|
// Resolve the table reference for all types which we register an entity name use for.
|
||||||
// Also, force table group initialization for treats when needed to ensure correct cardinality
|
// Also, force table group initialization for treats when needed to ensure correct cardinality
|
||||||
final EntityNameUse.UseKind useKind = finalEntityNameUse.getKind();
|
final EntityNameUse.UseKind useKind = finalEntityNameUse.getKind();
|
||||||
|
@ -3156,7 +3175,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void registerTypeUsage(EntityDiscriminatorSqmPath path) {
|
protected void registerTypeUsage(DiscriminatorSqmPath<?> path) {
|
||||||
registerTypeUsage( getFromClauseAccess().getTableGroup( path.getNavigablePath().getParent() ) );
|
registerTypeUsage( getFromClauseAccess().getTableGroup( path.getNavigablePath().getParent() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3172,20 +3191,23 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
// but for `a = 1 and type(..) = A or type(..) = B` we can infer `A, B`
|
// but for `a = 1 and type(..) = A or type(..) = B` we can infer `A, B`
|
||||||
// The OR junction allows to create a union of entity name lists of all sub-predicates
|
// The OR junction allows to create a union of entity name lists of all sub-predicates
|
||||||
// The AND junction allows to create an intersection of entity name lists of all sub-predicates
|
// The AND junction allows to create an intersection of entity name lists of all sub-predicates
|
||||||
final EntityMappingType mappingType = (EntityMappingType) tableGroup.getModelPart().getPartMappingType();
|
final MappingType partMappingType = tableGroup.getModelPart().getPartMappingType();
|
||||||
final AbstractEntityPersister persister = (AbstractEntityPersister) mappingType.getEntityPersister();
|
if ( partMappingType instanceof EntityMappingType ) {
|
||||||
// Avoid resolving subclass tables for persisters with physical discriminators as we won't need them
|
final EntityMappingType mappingType = (EntityMappingType) partMappingType;
|
||||||
if ( persister.getDiscriminatorMapping().hasPhysicalColumn() ) {
|
final AbstractEntityPersister persister = (AbstractEntityPersister) mappingType.getEntityPersister();
|
||||||
return;
|
// Avoid resolving subclass tables for persisters with physical discriminators as we won't need them
|
||||||
}
|
if ( persister.getDiscriminatorMapping().hasPhysicalColumn() ) {
|
||||||
if ( getCurrentClauseStack().getCurrent() != Clause.WHERE && getCurrentClauseStack().getCurrent() != Clause.HAVING ) {
|
return;
|
||||||
// Where and having clauses are handled specially with EntityNameUse.FILTER and pruning
|
}
|
||||||
registerEntityNameUsage( tableGroup, EntityNameUse.PROJECTION, persister.getEntityName(), true );
|
if ( getCurrentClauseStack().getCurrent() != Clause.WHERE && getCurrentClauseStack().getCurrent() != Clause.HAVING ) {
|
||||||
}
|
// Where and having clauses are handled specially with EntityNameUse.FILTER and pruning
|
||||||
else {
|
registerEntityNameUsage( tableGroup, EntityNameUse.PROJECTION, persister.getEntityName(), true );
|
||||||
final int subclassTableSpan = persister.getSubclassTableSpan();
|
}
|
||||||
for ( int i = 0; i < subclassTableSpan; i++ ) {
|
else {
|
||||||
tableGroup.resolveTableReference( null, persister.getSubclassTableName( i ) );
|
final int subclassTableSpan = persister.getSubclassTableSpan();
|
||||||
|
for ( int i = 0; i < subclassTableSpan; i++ ) {
|
||||||
|
tableGroup.resolveTableReference( null, persister.getSubclassTableName( i ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3196,16 +3218,19 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
if ( tableGroup.isInitialized() ) {
|
if ( tableGroup.isInitialized() ) {
|
||||||
final Map<String, EntityNameUse> entityNameUses = entry.getValue();
|
final Map<String, EntityNameUse> entityNameUses = entry.getValue();
|
||||||
final ModelPartContainer modelPart = tableGroup.getModelPart();
|
final ModelPartContainer modelPart = tableGroup.getModelPart();
|
||||||
final EntityPersister tableGroupPersister;
|
final MappingType partMappingType;
|
||||||
if ( modelPart instanceof PluralAttributeMapping ) {
|
if ( modelPart instanceof PluralAttributeMapping ) {
|
||||||
tableGroupPersister = (EntityPersister) ( (PluralAttributeMapping) modelPart )
|
partMappingType = ( (PluralAttributeMapping) modelPart )
|
||||||
.getElementDescriptor()
|
.getElementDescriptor()
|
||||||
.getPartMappingType();
|
.getPartMappingType();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tableGroupPersister = (EntityPersister) modelPart.getPartMappingType();
|
partMappingType = modelPart.getPartMappingType();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( partMappingType instanceof EntityPersister ) {
|
||||||
|
( (EntityPersister) partMappingType ).pruneForSubclasses( tableGroup, entityNameUses );
|
||||||
}
|
}
|
||||||
tableGroupPersister.pruneForSubclasses( tableGroup, entityNameUses );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3235,7 +3260,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
for ( SqmFrom<?, ?> sqmTreat : sqmTreats ) {
|
for ( SqmFrom<?, ?> sqmTreat : sqmTreats ) {
|
||||||
final TableGroup actualTableGroup = getActualTableGroup( lhsTableGroup, sqmTreat );
|
final TableGroup actualTableGroup = getActualTableGroup( lhsTableGroup, sqmTreat );
|
||||||
// We don't know the context yet in which a treat is used, so we have to register base treats and track the usage
|
// We don't know the context yet in which a treat is used, so we have to register base treats and track the usage
|
||||||
registerEntityNameUsage( actualTableGroup, EntityNameUse.BASE_TREAT, ( (SqmTreatedPath<?, ?>) sqmTreat ).getTreatTarget().getHibernateEntityName() );
|
registerEntityNameUsage( actualTableGroup, EntityNameUse.BASE_TREAT, ( (SqmTreatedPath<?, ?>) sqmTreat ).getTreatTarget().getTypeName() );
|
||||||
consumeExplicitJoins( sqmTreat, actualTableGroup );
|
consumeExplicitJoins( sqmTreat, actualTableGroup );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3408,12 +3433,15 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
// Since joins on treated paths will never cause table pruning, we need to add a join condition for the treat
|
// Since joins on treated paths will never cause table pruning, we need to add a join condition for the treat
|
||||||
if ( sqmJoin.getLhs() instanceof SqmTreatedPath<?, ?> ) {
|
if ( sqmJoin.getLhs() instanceof SqmTreatedPath<?, ?> ) {
|
||||||
final SqmTreatedPath<?, ?> treatedPath = (SqmTreatedPath<?, ?>) sqmJoin.getLhs();
|
final SqmTreatedPath<?, ?> treatedPath = (SqmTreatedPath<?, ?>) sqmJoin.getLhs();
|
||||||
joinForPredicate.applyPredicate(
|
final ManagedDomainType<?> treatTarget = treatedPath.getTreatTarget();
|
||||||
createTreatTypeRestriction(
|
if ( treatTarget.getPersistenceType() == ENTITY ) {
|
||||||
treatedPath.getWrappedPath(),
|
joinForPredicate.applyPredicate(
|
||||||
treatedPath.getTreatTarget()
|
createTreatTypeRestriction(
|
||||||
)
|
treatedPath.getWrappedPath(),
|
||||||
);
|
(EntityDomainType<?>) treatTarget
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( transitive ) {
|
if ( transitive ) {
|
||||||
|
@ -3681,11 +3709,14 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
Consumer<TableGroup> implicitJoinChecker) {
|
Consumer<TableGroup> implicitJoinChecker) {
|
||||||
final SqmPath<?> sqmPath = (SqmPath<?>) path;
|
final SqmPath<?> sqmPath = (SqmPath<?>) path;
|
||||||
final SqmPath<?> parentPath;
|
final SqmPath<?> parentPath;
|
||||||
|
final boolean treated;
|
||||||
if ( sqmPath instanceof SqmTreatedPath<?, ?> ) {
|
if ( sqmPath instanceof SqmTreatedPath<?, ?> ) {
|
||||||
parentPath = ( (SqmTreatedPath<?, ?>) sqmPath ).getWrappedPath();
|
parentPath = ( (SqmTreatedPath<?, ?>) sqmPath ).getWrappedPath();
|
||||||
|
treated = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
parentPath = sqmPath.getLhs();
|
parentPath = sqmPath.getLhs();
|
||||||
|
treated = false;
|
||||||
}
|
}
|
||||||
if ( parentPath == null ) {
|
if ( parentPath == null ) {
|
||||||
if ( sqmPath instanceof SqmFunctionPath<?> ) {
|
if ( sqmPath instanceof SqmFunctionPath<?> ) {
|
||||||
|
@ -3730,10 +3761,13 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
if ( newTableGroup != null ) {
|
if ( newTableGroup != null ) {
|
||||||
implicitJoinChecker.accept( newTableGroup );
|
implicitJoinChecker.accept( newTableGroup );
|
||||||
registerPathAttributeEntityNameUsage( sqmPath, newTableGroup );
|
registerPathAttributeEntityNameUsage( sqmPath, newTableGroup );
|
||||||
|
if ( treated ) {
|
||||||
|
fromClauseIndex.register( sqmPath, newTableGroup );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return newTableGroup;
|
return newTableGroup;
|
||||||
}
|
}
|
||||||
else if ( sqmPath instanceof SqmTreatedPath<?, ?> ) {
|
else if ( treated ) {
|
||||||
fromClauseIndex.register( sqmPath, parentTableGroup );
|
fromClauseIndex.register( sqmPath, parentTableGroup );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3827,8 +3861,8 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
final FromClauseIndex fromClauseIndex = getFromClauseIndex();
|
final FromClauseIndex fromClauseIndex = getFromClauseIndex();
|
||||||
final ModelPart subPart = parentTableGroup.getModelPart().findSubPart(
|
final ModelPart subPart = parentTableGroup.getModelPart().findSubPart(
|
||||||
joinedPath.getReferencedPathSource().getPathName(),
|
joinedPath.getReferencedPathSource().getPathName(),
|
||||||
lhsPath instanceof SqmTreatedPath
|
lhsPath instanceof SqmTreatedPath<?, ?> && ( (SqmTreatedPath<?, ?>) lhsPath ).getTreatTarget().getPersistenceType() == ENTITY
|
||||||
? resolveEntityPersister( ( (SqmTreatedPath<?, ?>) lhsPath ).getTreatTarget() )
|
? resolveEntityPersister( (EntityDomainType<?>) ( (SqmTreatedPath<?, ?>) lhsPath ).getTreatTarget() )
|
||||||
: null
|
: null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -4059,7 +4093,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
throw new InterpretationException( "SqmEntityJoin not yet resolved to TableGroup" );
|
throw new InterpretationException( "SqmEntityJoin not yet resolved to TableGroup" );
|
||||||
}
|
}
|
||||||
|
|
||||||
private Expression visitTableGroup(TableGroup tableGroup, SqmFrom<?, ?> path) {
|
private Expression visitTableGroup(TableGroup tableGroup, SqmPath<?> path) {
|
||||||
final ModelPartContainer tableGroupModelPart = tableGroup.getModelPart();
|
final ModelPartContainer tableGroupModelPart = tableGroup.getModelPart();
|
||||||
|
|
||||||
final ModelPart actualModelPart;
|
final ModelPart actualModelPart;
|
||||||
|
@ -4213,11 +4247,12 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
final EntityMappingType treatedMapping;
|
final EntityMappingType treatedMapping;
|
||||||
if ( path instanceof SqmTreatedPath ) {
|
if ( path instanceof SqmTreatedPath<?, ?> && ( (SqmTreatedPath<?, ?>) path ).getTreatTarget().getPersistenceType() == ENTITY ) {
|
||||||
|
final ManagedDomainType<?> treatTarget = ( (SqmTreatedPath<?, ?>) path ).getTreatTarget();
|
||||||
treatedMapping = creationContext.getSessionFactory()
|
treatedMapping = creationContext.getSessionFactory()
|
||||||
.getRuntimeMetamodels()
|
.getRuntimeMetamodels()
|
||||||
.getMappingMetamodel()
|
.getMappingMetamodel()
|
||||||
.findEntityDescriptor( ( (SqmTreatedPath<?,?>) path ).getTreatTarget().getHibernateEntityName() );
|
.findEntityDescriptor( treatTarget.getTypeName() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
treatedMapping = interpretationModelPart.getEntityMappingType();
|
treatedMapping = interpretationModelPart.getEntityMappingType();
|
||||||
|
@ -4501,7 +4536,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitDiscriminatorPath(EntityDiscriminatorSqmPath sqmPath) {
|
public Object visitDiscriminatorPath(DiscriminatorSqmPath<?> sqmPath) {
|
||||||
return prepareReusablePath(
|
return prepareReusablePath(
|
||||||
sqmPath,
|
sqmPath,
|
||||||
() -> {
|
() -> {
|
||||||
|
@ -4574,7 +4609,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
final TableGroup resolved = getFromClauseAccess().findTableGroup( sqmTreatedPath.getNavigablePath() );
|
final TableGroup resolved = getFromClauseAccess().findTableGroup( sqmTreatedPath.getNavigablePath() );
|
||||||
if ( resolved != null ) {
|
if ( resolved != null ) {
|
||||||
log.tracef( "SqmTreatedPath [%s] resolved to existing TableGroup [%s]", sqmTreatedPath, resolved );
|
log.tracef( "SqmTreatedPath [%s] resolved to existing TableGroup [%s]", sqmTreatedPath, resolved );
|
||||||
return visitTableGroup( resolved, (SqmFrom<?, ?>) sqmTreatedPath );
|
return visitTableGroup( resolved, sqmTreatedPath );
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new InterpretationException( "SqmTreatedPath not yet resolved to TableGroup" );
|
throw new InterpretationException( "SqmTreatedPath not yet resolved to TableGroup" );
|
||||||
|
@ -5152,13 +5187,20 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
}
|
}
|
||||||
if ( lhs instanceof SqmTreatedPath<?, ?> ) {
|
if ( lhs instanceof SqmTreatedPath<?, ?> ) {
|
||||||
final SqmTreatedPath<?, ?> treatedPath = (SqmTreatedPath<?, ?>) lhs;
|
final SqmTreatedPath<?, ?> treatedPath = (SqmTreatedPath<?, ?>) lhs;
|
||||||
final Class<?> treatTargetJavaType = treatedPath.getTreatTarget().getJavaType();
|
final ManagedDomainType<?> treatTarget = treatedPath.getTreatTarget();
|
||||||
|
final Class<?> treatTargetJavaType = treatTarget.getJavaType();
|
||||||
final SqmPath<?> wrappedPath = treatedPath.getWrappedPath();
|
final SqmPath<?> wrappedPath = treatedPath.getWrappedPath();
|
||||||
final Class<?> originalJavaType = wrappedPath.getJavaType();
|
final Class<?> originalJavaType = wrappedPath.getJavaType();
|
||||||
if ( treatTargetJavaType.isAssignableFrom( originalJavaType ) ) {
|
if ( treatTargetJavaType.isAssignableFrom( originalJavaType ) ) {
|
||||||
// Treating a node to a super type can be ignored
|
// Treating a node to a super type can be ignored
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
|
if ( treatTarget instanceof EmbeddableDomainType<?> ) {
|
||||||
|
// For embedded treats we simply register a TREAT use
|
||||||
|
final TableGroup tableGroup = getFromClauseIndex().findTableGroup( wrappedPath.getNavigablePath() );
|
||||||
|
registerEntityNameUsage( tableGroup, EntityNameUse.TREAT, treatTarget.getTypeName(), false );
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
if ( !( expression.getExpressionType() instanceof BasicValuedMapping ) ) {
|
if ( !( expression.getExpressionType() instanceof BasicValuedMapping ) ) {
|
||||||
// A case wrapper for non-basic paths is not possible,
|
// A case wrapper for non-basic paths is not possible,
|
||||||
// because a case expression must return a scalar value.
|
// because a case expression must return a scalar value.
|
||||||
|
@ -5167,9 +5209,8 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
// by registering the treat into tableGroupEntityNameUses.
|
// by registering the treat into tableGroupEntityNameUses.
|
||||||
// Joins don't need the restriction as it will be embedded into
|
// Joins don't need the restriction as it will be embedded into
|
||||||
// the joined table group itself by #pruneTableGroupJoins
|
// the joined table group itself by #pruneTableGroupJoins
|
||||||
final String treatedName = treatedPath.getTreatTarget().getHibernateEntityName();
|
|
||||||
final TableGroup tableGroup = getFromClauseIndex().findTableGroup( wrappedPath.getNavigablePath() );
|
final TableGroup tableGroup = getFromClauseIndex().findTableGroup( wrappedPath.getNavigablePath() );
|
||||||
registerEntityNameUsage( tableGroup, EntityNameUse.TREAT, treatedName );
|
registerEntityNameUsage( tableGroup, EntityNameUse.TREAT, treatTarget.getTypeName(), false );
|
||||||
}
|
}
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
|
@ -5182,7 +5223,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
// Only need a case expression around the basic valued path for the parent treat expression
|
// 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 the column of the basic valued path is shared between subclasses
|
||||||
if ( persister.isSharedColumn( basicPath.getColumnReference().getColumnExpression() ) ) {
|
if ( persister.isSharedColumn( basicPath.getColumnReference().getColumnExpression() ) ) {
|
||||||
return createCaseExpression( wrappedPath, treatedPath.getTreatTarget(), expression );
|
return createCaseExpression( wrappedPath, (EntityDomainType<?>) treatTarget, expression );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return expression;
|
return expression;
|
||||||
|
@ -5219,40 +5260,67 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
Predicate predicate = null;
|
Predicate predicate = null;
|
||||||
for ( Map.Entry<TableGroup, Map<String, EntityNameUse>> entry : conjunctTreatUsages.entrySet() ) {
|
for ( Map.Entry<TableGroup, Map<String, EntityNameUse>> entry : conjunctTreatUsages.entrySet() ) {
|
||||||
final TableGroup tableGroup = entry.getKey();
|
final TableGroup tableGroup = entry.getKey();
|
||||||
final Set<String> entityNames = determineEntityNamesForTreatTypeRestriction(
|
|
||||||
(EntityMappingType) tableGroup.getModelPart().getPartMappingType(),
|
|
||||||
entry.getValue()
|
|
||||||
);
|
|
||||||
if ( entityNames.isEmpty() ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final ModelPartContainer modelPart = tableGroup.getModelPart();
|
final ModelPartContainer modelPart = tableGroup.getModelPart();
|
||||||
|
|
||||||
|
final Set<String> typeNames;
|
||||||
final EntityMappingType entityMapping;
|
final EntityMappingType entityMapping;
|
||||||
if ( modelPart instanceof EntityValuedModelPart ) {
|
final EmbeddableMappingType embeddableMapping;
|
||||||
|
if ( modelPart instanceof PluralAttributeMapping ) {
|
||||||
|
entityMapping = (EntityMappingType) ( (PluralAttributeMapping) modelPart ).getElementDescriptor()
|
||||||
|
.getPartMappingType();
|
||||||
|
embeddableMapping = null;
|
||||||
|
}
|
||||||
|
else if ( modelPart instanceof EntityValuedModelPart ) {
|
||||||
entityMapping = ( (EntityValuedModelPart) modelPart ).getEntityMappingType();
|
entityMapping = ( (EntityValuedModelPart) modelPart ).getEntityMappingType();
|
||||||
|
embeddableMapping = null;
|
||||||
|
}
|
||||||
|
else if ( modelPart instanceof EmbeddableValuedModelPart ) {
|
||||||
|
embeddableMapping = ( (EmbeddableValuedModelPart) modelPart ).getEmbeddableTypeDescriptor();
|
||||||
|
entityMapping = null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
entityMapping = (EntityMappingType) ( (PluralAttributeMapping) modelPart ).getElementDescriptor().getPartMappingType();
|
throw new IllegalStateException( "Unrecognized model part for treated table group: " + tableGroup );
|
||||||
|
}
|
||||||
|
|
||||||
|
final DiscriminatorPathInterpretation<?> typeExpression;
|
||||||
|
if ( entityMapping != null ) {
|
||||||
|
typeNames = determineEntityNamesForTreatTypeRestriction( entityMapping, entry.getValue() );
|
||||||
|
if ( typeNames.isEmpty() ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
typeExpression = new DiscriminatorPathInterpretation<>(
|
||||||
|
tableGroup.getNavigablePath().append( EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME ),
|
||||||
|
entityMapping,
|
||||||
|
tableGroup,
|
||||||
|
this
|
||||||
|
);
|
||||||
|
registerTypeUsage( tableGroup );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert embeddableMapping != null;
|
||||||
|
typeNames = determineEmbeddableNamesForTreatTypeRestriction( embeddableMapping, entry.getValue() );
|
||||||
|
if ( typeNames.isEmpty() ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
typeExpression = new DiscriminatorPathInterpretation<>(
|
||||||
|
tableGroup.getNavigablePath().append( EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME ),
|
||||||
|
embeddableMapping.getDiscriminatorMapping(),
|
||||||
|
tableGroup,
|
||||||
|
this
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final DiscriminatorPathInterpretation<?> typeExpression = new DiscriminatorPathInterpretation<>(
|
|
||||||
tableGroup.getNavigablePath().append( EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME ),
|
|
||||||
entityMapping,
|
|
||||||
tableGroup,
|
|
||||||
this
|
|
||||||
);
|
|
||||||
// We need to check if this is a treated left or full join, which case we should
|
// We need to check if this is a treated left or full join, which case we should
|
||||||
// allow null discriminator values to maintain correct semantics
|
// allow null discriminator values to maintain correct semantics
|
||||||
final TableGroupJoin join = getParentTableGroupJoin( tableGroup );
|
final TableGroupJoin join = getParentTableGroupJoin( tableGroup );
|
||||||
final boolean allowNulls = join != null && ( join.getJoinType() == SqlAstJoinType.LEFT || join.getJoinType() == SqlAstJoinType.FULL );
|
final boolean allowNulls = join != null && ( join.getJoinType() == SqlAstJoinType.LEFT || join.getJoinType() == SqlAstJoinType.FULL );
|
||||||
registerTypeUsage( tableGroup );
|
|
||||||
predicate = combinePredicates(
|
predicate = combinePredicates(
|
||||||
predicate,
|
predicate,
|
||||||
createTreatTypeRestriction(
|
createTreatTypeRestriction(
|
||||||
typeExpression,
|
typeExpression,
|
||||||
entityNames,
|
typeNames,
|
||||||
allowNulls
|
allowNulls,
|
||||||
|
entityMapping != null
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -5334,6 +5402,22 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
return entityNames;
|
return entityNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Set<String> determineEmbeddableNamesForTreatTypeRestriction(
|
||||||
|
EmbeddableMappingType embeddableMappingType,
|
||||||
|
Map<String, EntityNameUse> entityNameUses) {
|
||||||
|
final EmbeddableDomainType<?> embeddableDomainType = creationContext.getSessionFactory()
|
||||||
|
.getRuntimeMetamodels()
|
||||||
|
.getJpaMetamodel()
|
||||||
|
.embeddable( embeddableMappingType.getJavaType().getJavaTypeClass() );
|
||||||
|
final Set<String> entityNameUsesSet = new HashSet<>( entityNameUses.keySet() );
|
||||||
|
ManagedDomainType<?> superType = embeddableDomainType;
|
||||||
|
while ( superType != null ) {
|
||||||
|
entityNameUsesSet.remove( superType.getTypeName() );
|
||||||
|
superType = superType.getSuperType();
|
||||||
|
}
|
||||||
|
return entityNameUsesSet;
|
||||||
|
}
|
||||||
|
|
||||||
private Predicate createTreatTypeRestriction(SqmPath<?> lhs, EntityDomainType<?> treatTarget) {
|
private Predicate createTreatTypeRestriction(SqmPath<?> lhs, EntityDomainType<?> treatTarget) {
|
||||||
final AbstractEntityPersister entityDescriptor = (AbstractEntityPersister) domainModel.findEntityDescriptor( treatTarget.getHibernateEntityName() );
|
final AbstractEntityPersister entityDescriptor = (AbstractEntityPersister) domainModel.findEntityDescriptor( treatTarget.getHibernateEntityName() );
|
||||||
if ( entityDescriptor.isPolymorphic() && lhs.getNodeType() != treatTarget ) {
|
if ( entityDescriptor.isPolymorphic() && lhs.getNodeType() != treatTarget ) {
|
||||||
|
@ -5351,26 +5435,28 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
return createTreatTypeRestriction(
|
return createTreatTypeRestriction(
|
||||||
DiscriminatorPathInterpretation.from( discriminatorSqmPath, this ),
|
DiscriminatorPathInterpretation.from( discriminatorSqmPath, this ),
|
||||||
subclassEntityNames,
|
subclassEntityNames,
|
||||||
false
|
false,
|
||||||
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Predicate createTreatTypeRestriction(
|
private Predicate createTreatTypeRestriction(
|
||||||
Expression typeExpression,
|
SqmPathInterpretation<?> typeExpression,
|
||||||
Set<String> subclassEntityNames,
|
Set<String> subtypeNames,
|
||||||
boolean allowNulls) {
|
boolean allowNulls,
|
||||||
|
boolean entity) {
|
||||||
final Predicate discriminatorPredicate;
|
final Predicate discriminatorPredicate;
|
||||||
if ( subclassEntityNames.size() == 1 ) {
|
if ( subtypeNames.size() == 1 ) {
|
||||||
discriminatorPredicate = new ComparisonPredicate(
|
discriminatorPredicate = new ComparisonPredicate(
|
||||||
typeExpression,
|
typeExpression,
|
||||||
ComparisonOperator.EQUAL,
|
ComparisonOperator.EQUAL,
|
||||||
new EntityTypeLiteral( domainModel.findEntityDescriptor( subclassEntityNames.iterator().next() ) )
|
getTypeLiteral( typeExpression, subtypeNames.iterator().next(), entity )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
final List<Expression> typeLiterals = new ArrayList<>( subclassEntityNames.size() );
|
final List<Expression> typeLiterals = new ArrayList<>( subtypeNames.size() );
|
||||||
for ( String subclassEntityName : subclassEntityNames ) {
|
for ( String subtypeName : subtypeNames ) {
|
||||||
typeLiterals.add( new EntityTypeLiteral( domainModel.findEntityDescriptor( subclassEntityName ) ) );
|
typeLiterals.add( getTypeLiteral( typeExpression, subtypeName, entity ) );
|
||||||
}
|
}
|
||||||
discriminatorPredicate = new InListPredicate( typeExpression, typeLiterals );
|
discriminatorPredicate = new InListPredicate( typeExpression, typeLiterals );
|
||||||
}
|
}
|
||||||
|
@ -5384,6 +5470,22 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
return discriminatorPredicate;
|
return discriminatorPredicate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Expression getTypeLiteral(SqmPathInterpretation<?> typeExpression, String typeName, boolean entity) {
|
||||||
|
if ( entity ) {
|
||||||
|
return new EntityTypeLiteral( domainModel.findEntityDescriptor( typeName ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final EmbeddableDomainType<?> embeddable = creationContext.getSessionFactory()
|
||||||
|
.getRuntimeMetamodels()
|
||||||
|
.getJpaMetamodel()
|
||||||
|
.embeddable( typeName );
|
||||||
|
return new EmbeddableTypeLiteral(
|
||||||
|
embeddable,
|
||||||
|
(BasicType<?>) typeExpression.getExpressionType().getSingleJdbcMapping()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private MappingModelExpressible<?> resolveInferredType() {
|
private MappingModelExpressible<?> resolveInferredType() {
|
||||||
final Supplier<MappingModelExpressible<?>> inferableTypeAccess = inferrableTypeAccessStack.getCurrent();
|
final Supplier<MappingModelExpressible<?>> inferableTypeAccess = inferrableTypeAccessStack.getCurrent();
|
||||||
if ( inTypeInference || inferableTypeAccess == null ) {
|
if ( inTypeInference || inferableTypeAccess == null ) {
|
||||||
|
@ -7130,6 +7232,16 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
return new EntityTypeLiteral( mappingDescriptor );
|
return new EntityTypeLiteral( mappingDescriptor );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object visitEmbeddableTypeLiteralExpression(SqmLiteralEmbeddableType<?> expression) {
|
||||||
|
final MappingModelExpressible<?> inferredValueMapping = getInferredValueMapping();
|
||||||
|
// The inferred value mapping for literal embeddable types will either be the
|
||||||
|
// discriminator mapping for polymorphic embeddables or the Class<?> basic type
|
||||||
|
final BasicType<?> basicType = inferredValueMapping != null ?
|
||||||
|
(BasicType<?>) inferredValueMapping.getSingleJdbcMapping() :
|
||||||
|
expression.getNodeType();
|
||||||
|
return new EmbeddableTypeLiteral( expression.getExpressible(), basicType );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Expression visitAnyDiscriminatorTypeValueExpression(SqmAnyDiscriminatorValue<?> expression) {
|
public Expression visitAnyDiscriminatorTypeValueExpression(SqmAnyDiscriminatorValue<?> expression) {
|
||||||
|
@ -7278,7 +7390,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
disjunctEntityNameUsesArray = new Map[predicate.getPredicates().size()];
|
disjunctEntityNameUsesArray = new Map[predicate.getPredicates().size()];
|
||||||
entityNameUsesToPropagate = previousTableGroupEntityNameUses == null
|
entityNameUsesToPropagate = previousTableGroupEntityNameUses == null
|
||||||
? new IdentityHashMap<>()
|
? new IdentityHashMap<>()
|
||||||
: previousTableGroupEntityNameUses;
|
: new IdentityHashMap<>( previousTableGroupEntityNameUses );
|
||||||
}
|
}
|
||||||
if ( i == 0 ) {
|
if ( i == 0 ) {
|
||||||
// Collect the table groups for which filters are registered
|
// Collect the table groups for which filters are registered
|
||||||
|
@ -7420,48 +7532,56 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
return disjunction;
|
return disjunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the intersection of the conjunct treat usages,
|
if ( !tableGroupEntityNameUses.isEmpty() ) {
|
||||||
// so that we can push that up and infer during pruning, which entity subclasses can be omitted
|
// Build the intersection of the conjunct treat usages,
|
||||||
final Iterator<Map.Entry<TableGroup, Map<String, EntityNameUse>>> iterator = tableGroupEntityNameUses.entrySet().iterator();
|
// so that we can push that up and infer during pruning, which entity subclasses can be omitted
|
||||||
while ( iterator.hasNext() ) {
|
final Iterator<Map.Entry<TableGroup, Map<String, EntityNameUse>>> iterator = tableGroupEntityNameUses.entrySet().iterator();
|
||||||
final Map.Entry<TableGroup, Map<String, EntityNameUse>> entry = iterator.next();
|
while ( iterator.hasNext() ) {
|
||||||
final Map<String, EntityNameUse> intersected = new HashMap<>( entry.getValue() );
|
final Map.Entry<TableGroup, Map<String, EntityNameUse>> entry = iterator.next();
|
||||||
entry.setValue( intersected );
|
final Map<String, EntityNameUse> intersected = new HashMap<>( entry.getValue() );
|
||||||
boolean remove = false;
|
entry.setValue( intersected );
|
||||||
for ( Map<TableGroup, Map<String, EntityNameUse>> conjunctTreatUsages : disjunctEntityNameUsesArray ) {
|
boolean remove = false;
|
||||||
final Map<String, EntityNameUse> entityNames;
|
for ( Map<TableGroup, Map<String, EntityNameUse>> conjunctTreatUsages : disjunctEntityNameUsesArray ) {
|
||||||
if ( conjunctTreatUsages == null || ( entityNames = conjunctTreatUsages.get( entry.getKey() ) ) == null ) {
|
final Map<String, EntityNameUse> entityNames;
|
||||||
remove = true;
|
if ( conjunctTreatUsages == null || ( entityNames = conjunctTreatUsages.get( entry.getKey() ) ) == null ) {
|
||||||
continue;
|
remove = true;
|
||||||
}
|
break;
|
||||||
// Intersect the two sets and transfer the common elements to the intersection
|
|
||||||
final Iterator<Map.Entry<String, EntityNameUse>> intersectedIter = intersected.entrySet().iterator();
|
|
||||||
while ( intersectedIter.hasNext() ) {
|
|
||||||
final Map.Entry<String, EntityNameUse> intersectedEntry = intersectedIter.next();
|
|
||||||
final EntityNameUse intersectedUseKind = intersectedEntry.getValue();
|
|
||||||
final EntityNameUse useKind = entityNames.get( intersectedEntry.getKey() );
|
|
||||||
if ( useKind == null ) {
|
|
||||||
intersectedIter.remove();
|
|
||||||
}
|
}
|
||||||
else {
|
// Intersect the two sets and transfer the common elements to the intersection
|
||||||
// Possibly downgrade a FILTER use to EXPRESSION if one of the disjunctions does not use FILTER
|
final Iterator<Map.Entry<String, EntityNameUse>> intersectedIter = intersected.entrySet()
|
||||||
intersectedEntry.setValue( intersectedUseKind.weaker( useKind ) );
|
.iterator();
|
||||||
|
while ( intersectedIter.hasNext() ) {
|
||||||
|
final Map.Entry<String, EntityNameUse> intersectedEntry = intersectedIter.next();
|
||||||
|
final EntityNameUse intersectedUseKind = intersectedEntry.getValue();
|
||||||
|
final EntityNameUse useKind = entityNames.get( intersectedEntry.getKey() );
|
||||||
|
if ( useKind == null ) {
|
||||||
|
intersectedIter.remove();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Possibly downgrade a FILTER use to EXPRESSION if one of the disjunctions does not use FILTER
|
||||||
|
intersectedEntry.setValue( intersectedUseKind.weaker( useKind ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( intersected.isEmpty() ) {
|
||||||
|
remove = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
entityNames.keySet().removeAll( intersected.keySet() );
|
||||||
|
if ( entityNames.isEmpty() ) {
|
||||||
|
conjunctTreatUsages.remove( entry.getKey() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( intersected.isEmpty() ) {
|
|
||||||
remove = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
entityNames.keySet().removeAll( intersected.keySet() );
|
|
||||||
if ( entityNames.isEmpty() ) {
|
|
||||||
conjunctTreatUsages.remove( entry.getKey() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( remove ) {
|
if ( remove ) {
|
||||||
iterator.remove();
|
entityNameUsesToPropagate.remove( entry.getKey() );
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// If there's no baseline to construct the intersection from don't propagate
|
||||||
|
entityNameUsesToPropagate.clear();
|
||||||
|
}
|
||||||
|
|
||||||
// Prepend the treat type usages to the respective conjuncts
|
// Prepend the treat type usages to the respective conjuncts
|
||||||
for ( int i = 0; i < disjunctEntityNameUsesArray.length; i++ ) {
|
for ( int i = 0; i < disjunctEntityNameUsesArray.length; i++ ) {
|
||||||
|
@ -7476,6 +7596,12 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restore the parent context entity name uses state
|
||||||
|
tableGroupEntityNameUses.clear();
|
||||||
|
if ( previousTableGroupEntityNameUses != null ) {
|
||||||
|
tableGroupEntityNameUses.putAll( previousTableGroupEntityNameUses );
|
||||||
|
}
|
||||||
// Propagate the union of the entity name uses upwards
|
// Propagate the union of the entity name uses upwards
|
||||||
for ( Map.Entry<TableGroup, Map<String, EntityNameUse>> entry : entityNameUsesToPropagate.entrySet() ) {
|
for ( Map.Entry<TableGroup, Map<String, EntityNameUse>> entry : entityNameUsesToPropagate.entrySet() ) {
|
||||||
final Map<String, EntityNameUse> entityNameUses = tableGroupEntityNameUses.putIfAbsent(
|
final Map<String, EntityNameUse> entityNameUses = tableGroupEntityNameUses.putIfAbsent(
|
||||||
|
@ -7638,7 +7764,11 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
List<EntityTypeLiteral> literalExpressions,
|
List<EntityTypeLiteral> literalExpressions,
|
||||||
boolean inclusive) {
|
boolean inclusive) {
|
||||||
final TableGroup tableGroup = getFromClauseIndex().getTableGroup( typeExpression.getNavigablePath().getParent() );
|
final TableGroup tableGroup = getFromClauseIndex().getTableGroup( typeExpression.getNavigablePath().getParent() );
|
||||||
final EntityMappingType entityMappingType = (EntityMappingType) tableGroup.getModelPart().getPartMappingType();
|
final MappingType partMappingType = tableGroup.getModelPart().getPartMappingType();
|
||||||
|
if ( !( partMappingType instanceof EntityMappingType ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final EntityMappingType entityMappingType = (EntityMappingType) partMappingType;
|
||||||
if ( entityMappingType.getDiscriminatorMapping().hasPhysicalColumn() ) {
|
if ( entityMappingType.getDiscriminatorMapping().hasPhysicalColumn() ) {
|
||||||
// If the entity has a physical discriminator column we don't need to register any FILTER usages.
|
// If the entity has a physical discriminator column we don't need to register any FILTER usages.
|
||||||
// Register only an EXPRESSION usage to prevent pruning of the root type's table reference which
|
// Register only an EXPRESSION usage to prevent pruning of the root type's table reference which
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
import org.hibernate.sql.ast.tree.update.Assignable;
|
import org.hibernate.sql.ast.tree.update.Assignable;
|
||||||
|
|
||||||
|
import static jakarta.persistence.metamodel.Type.PersistenceType.ENTITY;
|
||||||
import static org.hibernate.internal.util.NullnessUtil.castNonNull;
|
import static org.hibernate.internal.util.NullnessUtil.castNonNull;
|
||||||
import static org.hibernate.query.sqm.internal.SqmUtil.getTargetMappingIfNeeded;
|
import static org.hibernate.query.sqm.internal.SqmUtil.getTargetMappingIfNeeded;
|
||||||
|
|
||||||
|
@ -51,8 +52,8 @@ public class BasicValuedPathInterpretation<T> extends AbstractSqmPathInterpretat
|
||||||
final TableGroup tableGroup = sqlAstCreationState.getFromClauseAccess().getTableGroup( lhs.getNavigablePath() );
|
final TableGroup tableGroup = sqlAstCreationState.getFromClauseAccess().getTableGroup( lhs.getNavigablePath() );
|
||||||
EntityMappingType treatTarget = null;
|
EntityMappingType treatTarget = null;
|
||||||
final ModelPartContainer modelPartContainer;
|
final ModelPartContainer modelPartContainer;
|
||||||
if ( lhs instanceof SqmTreatedPath<?, ?> ) {
|
if ( lhs instanceof SqmTreatedPath<?, ?> && ( (SqmTreatedPath<?, ?>) lhs ).getTreatTarget().getPersistenceType() == ENTITY ) {
|
||||||
final EntityDomainType<?> treatTargetDomainType = ( (SqmTreatedPath<?, ?>) lhs ).getTreatTarget();
|
final EntityDomainType<?> treatTargetDomainType = (EntityDomainType<?>) ( (SqmTreatedPath<?, ?>) lhs ).getTreatTarget();
|
||||||
|
|
||||||
final MappingMetamodel mappingMetamodel = sqlAstCreationState.getCreationContext()
|
final MappingMetamodel mappingMetamodel = sqlAstCreationState.getCreationContext()
|
||||||
.getSessionFactory()
|
.getSessionFactory()
|
||||||
|
|
|
@ -13,6 +13,8 @@ import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
||||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
|
import org.hibernate.metamodel.model.domain.DiscriminatorSqmPath;
|
||||||
|
import org.hibernate.metamodel.model.domain.internal.EmbeddedDiscriminatorSqmPath;
|
||||||
import org.hibernate.metamodel.model.domain.internal.EntityDiscriminatorSqmPath;
|
import org.hibernate.metamodel.model.domain.internal.EntityDiscriminatorSqmPath;
|
||||||
import org.hibernate.query.results.ResultSetMappingSqlSelection;
|
import org.hibernate.query.results.ResultSetMappingSqlSelection;
|
||||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||||
|
@ -27,6 +29,8 @@ import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
import org.hibernate.type.descriptor.java.JavaType;
|
import org.hibernate.type.descriptor.java.JavaType;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
import static org.hibernate.query.sqm.internal.SqmMappingModelHelper.resolveMappingModelExpressible;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SqmPathInterpretation and DomainResultProducer implementation for entity discriminator
|
* SqmPathInterpretation and DomainResultProducer implementation for entity discriminator
|
||||||
*
|
*
|
||||||
|
@ -58,22 +62,38 @@ public class DiscriminatorPathInterpretation<T> extends AbstractSqmPathInterpret
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SqmPathInterpretation<?> from(
|
public static SqmPathInterpretation<?> from(
|
||||||
EntityDiscriminatorSqmPath path,
|
DiscriminatorSqmPath<?> path,
|
||||||
SqmToSqlAstConverter converter) {
|
SqmToSqlAstConverter converter) {
|
||||||
assert path.getEntityDescriptor().hasSubclasses();
|
|
||||||
|
|
||||||
final NavigablePath navigablePath = path.getNavigablePath();
|
final NavigablePath navigablePath = path.getNavigablePath();
|
||||||
final TableGroup tableGroup = converter.getFromClauseAccess().getTableGroup( navigablePath.getParent() );
|
final TableGroup tableGroup = converter.getFromClauseAccess().getTableGroup( navigablePath.getParent() );
|
||||||
final ModelPartContainer modelPart = tableGroup.getModelPart();
|
final ModelPartContainer modelPart = tableGroup.getModelPart();
|
||||||
final EntityMappingType entityMapping;
|
|
||||||
if ( modelPart instanceof EntityValuedModelPart ) {
|
if ( path instanceof EntityDiscriminatorSqmPath<?> ) {
|
||||||
entityMapping = ( (EntityValuedModelPart) modelPart ).getEntityMappingType();
|
assert ((EntityDiscriminatorSqmPath<?>) path).getEntityDescriptor().hasSubclasses();
|
||||||
|
final EntityMappingType entityMapping;
|
||||||
|
if ( modelPart instanceof EntityValuedModelPart ) {
|
||||||
|
entityMapping = ( (EntityValuedModelPart) modelPart ).getEntityMappingType();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
entityMapping = (EntityMappingType) ( (PluralAttributeMapping) modelPart ).getElementDescriptor().getPartMappingType();
|
||||||
|
}
|
||||||
|
return new DiscriminatorPathInterpretation<>( navigablePath, entityMapping, tableGroup, converter );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
entityMapping = (EntityMappingType) ( (PluralAttributeMapping) modelPart ).getElementDescriptor().getPartMappingType();
|
final EmbeddedDiscriminatorSqmPath<?> embeddableDiscriminator = (EmbeddedDiscriminatorSqmPath<?>) path;
|
||||||
|
final DiscriminatorMapping discriminator = (DiscriminatorMapping) resolveMappingModelExpressible(
|
||||||
|
embeddableDiscriminator,
|
||||||
|
converter.getCreationContext().getMappingMetamodel(),
|
||||||
|
converter.getFromClauseAccess()::findTableGroup
|
||||||
|
);
|
||||||
|
return new DiscriminatorPathInterpretation<>(
|
||||||
|
navigablePath,
|
||||||
|
discriminator,
|
||||||
|
tableGroup,
|
||||||
|
converter
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DiscriminatorPathInterpretation<>( navigablePath, entityMapping, tableGroup, converter );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntityDiscriminatorMapping getDiscriminatorMapping() {
|
public EntityDiscriminatorMapping getDiscriminatorMapping() {
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.hibernate.sql.ast.tree.expression.SqlTupleContainer;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.update.Assignable;
|
import org.hibernate.sql.ast.tree.update.Assignable;
|
||||||
|
|
||||||
|
import static jakarta.persistence.metamodel.Type.PersistenceType.ENTITY;
|
||||||
import static org.hibernate.query.sqm.internal.SqmUtil.getTargetMappingIfNeeded;
|
import static org.hibernate.query.sqm.internal.SqmUtil.getTargetMappingIfNeeded;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,16 +51,14 @@ public class EmbeddableValuedPathInterpretation<T> extends AbstractSqmPathInterp
|
||||||
.getSessionFactory()
|
.getSessionFactory()
|
||||||
.getRuntimeMetamodels()
|
.getRuntimeMetamodels()
|
||||||
.getMappingMetamodel();
|
.getMappingMetamodel();
|
||||||
if ( lhs instanceof SqmTreatedPath ) {
|
if ( lhs instanceof SqmTreatedPath<?, ?> && ( (SqmTreatedPath<?, ?>) lhs ).getTreatTarget().getPersistenceType() == ENTITY ) {
|
||||||
//noinspection rawtypes
|
final EntityDomainType<?> treatTargetDomainType = (EntityDomainType<?>) ( (SqmTreatedPath<?, ?>) lhs ).getTreatTarget();
|
||||||
final EntityDomainType<?> treatTargetDomainType = ( (SqmTreatedPath) lhs ).getTreatTarget();
|
|
||||||
treatTarget = mappingMetamodel.findEntityDescriptor( treatTargetDomainType.getHibernateEntityName() );
|
treatTarget = mappingMetamodel.findEntityDescriptor( treatTargetDomainType.getHibernateEntityName() );
|
||||||
}
|
}
|
||||||
else if ( lhs.getNodeType() instanceof EntityDomainType ) {
|
else if ( lhs.getNodeType() instanceof EntityDomainType ) {
|
||||||
//noinspection rawtypes
|
//noinspection rawtypes
|
||||||
final EntityDomainType<?> entityDomainType = (EntityDomainType) lhs.getNodeType();
|
final EntityDomainType<?> entityDomainType = (EntityDomainType) lhs.getNodeType();
|
||||||
treatTarget = mappingMetamodel.findEntityDescriptor( entityDomainType.getHibernateEntityName() );
|
treatTarget = mappingMetamodel.findEntityDescriptor( entityDomainType.getHibernateEntityName() );
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -286,22 +286,16 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasTreats() {
|
|
||||||
return treats != null && !treats.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<SqmFrom<?, ?>> getSqmTreats() {
|
public List<SqmFrom<?, ?>> getSqmTreats() {
|
||||||
return treats == null ? Collections.emptyList() : treats;
|
return treats == null ? Collections.emptyList() : treats;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <S, X extends SqmFrom<?, S>> X findTreat(EntityDomainType<S> targetType, String alias) {
|
protected <S, X extends SqmFrom<?, S>> X findTreat(ManagedDomainType<S> targetType, String alias) {
|
||||||
if ( treats != null ) {
|
if ( treats != null ) {
|
||||||
for ( SqmFrom<?, ?> treat : treats ) {
|
for ( SqmFrom<?, ?> treat : treats ) {
|
||||||
if ( treat.getModel() == targetType ) {
|
if ( treat.getModel() == targetType ) {
|
||||||
if ( treat.getExplicitAlias() == null && alias == null
|
if ( Objects.equals( treat.getExplicitAlias(), alias ) ) {
|
||||||
|| Objects.equals( treat.getExplicitAlias(), alias ) ) {
|
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return (X) treat;
|
return (X) treat;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import org.hibernate.internal.util.NullnessUtil;
|
||||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||||
import org.hibernate.metamodel.model.domain.DomainType;
|
import org.hibernate.metamodel.model.domain.DomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
||||||
|
@ -219,12 +220,17 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <S extends T> SqmTreatedPath<T, S> getTreatedPath(EntityDomainType<S> treatTarget) {
|
protected <S extends T> SqmTreatedPath<T, S> getTreatedPath(ManagedDomainType<S> treatTarget) {
|
||||||
final NavigablePath treat = getNavigablePath().treatAs( treatTarget.getHibernateEntityName() );
|
final NavigablePath treat = getNavigablePath().treatAs( treatTarget.getTypeName() );
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
SqmTreatedPath<T, S> path = (SqmTreatedPath<T, S>) getLhs().getReusablePath( treat.getLocalName() );
|
SqmTreatedPath<T, S> path = (SqmTreatedPath<T, S>) getLhs().getReusablePath( treat.getLocalName() );
|
||||||
if ( path == null ) {
|
if ( path == null ) {
|
||||||
path = new SqmTreatedSimplePath<>( this, treatTarget, nodeBuilder() );
|
if ( treatTarget instanceof EntityDomainType<?> ) {
|
||||||
|
path = new SqmTreatedEntityValuedSimplePath<>( this, (EntityDomainType<S>) treatTarget, nodeBuilder() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
path = new SqmTreatedEmbeddedValuedSimplePath<>( this, (EmbeddableDomainType<S>) treatTarget );
|
||||||
|
}
|
||||||
getLhs().registerReusablePath( path );
|
getLhs().registerReusablePath( path );
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
|
|
|
@ -10,6 +10,8 @@ import java.util.Collection;
|
||||||
|
|
||||||
import org.hibernate.metamodel.model.domain.BagPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.BagPersistentAttribute;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.TreatableDomainType;
|
||||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
import org.hibernate.spi.NavigablePath;
|
import org.hibernate.spi.NavigablePath;
|
||||||
import org.hibernate.query.criteria.JpaCollectionJoin;
|
import org.hibernate.query.criteria.JpaCollectionJoin;
|
||||||
|
@ -116,8 +118,8 @@ public class SqmBagJoin<O, E> extends AbstractSqmPluralJoin<O,Collection<E>, E>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends E> SqmTreatedBagJoin<O, E, S> treatAs(Class<S> treatAsType) {
|
public <S extends E> SqmTreatedBagJoin<O, E, S> treatAs(Class<S> treatJavaType) {
|
||||||
return treatAs( nodeBuilder().getDomainModel().entity( treatAsType ) );
|
return treatAs( treatJavaType, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -127,7 +129,7 @@ public class SqmBagJoin<O, E> extends AbstractSqmPluralJoin<O,Collection<E>, E>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends E> SqmTreatedBagJoin<O,E,S> treatAs(Class<S> treatJavaType, String alias) {
|
public <S extends E> SqmTreatedBagJoin<O,E,S> treatAs(Class<S> treatJavaType, String alias) {
|
||||||
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ), alias );
|
return treatAs( treatJavaType, alias, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -136,8 +138,18 @@ public class SqmBagJoin<O, E> extends AbstractSqmPluralJoin<O,Collection<E>, E>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends E> SqmTreatedBagJoin<O,E,S> treatAs(Class<S> treatJavaType, String alias, boolean fetch) {
|
public <S extends E> SqmTreatedBagJoin<O, E, S> treatAs(Class<S> treatJavaType, String alias, boolean fetch) {
|
||||||
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ), alias, fetch );
|
final ManagedDomainType<S> treatTarget = nodeBuilder().getDomainModel().managedType( treatJavaType );
|
||||||
|
final SqmTreatedBagJoin<O, E, S> treat = findTreat( treatTarget, alias );
|
||||||
|
if ( treat == null ) {
|
||||||
|
if ( treatTarget instanceof TreatableDomainType<?> ) {
|
||||||
|
return addTreat( new SqmTreatedBagJoin<>( this, (TreatableDomainType<S>) treatTarget, alias, fetch ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalArgumentException( "Not a treatable type: " + treatJavaType.getName() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return treat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -99,12 +99,12 @@ public class SqmEmbeddedValuedSimplePath<T>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends T> SqmTreatedPath<T, S> treatAs(Class<S> treatJavaType) throws PathException {
|
public <S extends T> SqmTreatedPath<T, S> treatAs(Class<S> treatJavaType) throws PathException {
|
||||||
throw new FunctionArgumentException( "Embeddable paths cannot be TREAT-ed" );
|
return getTreatedPath( nodeBuilder().getDomainModel().embeddable( treatJavaType ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends T> SqmTreatedPath<T, S> treatAs(EntityDomainType<S> treatTarget) throws PathException {
|
public <S extends T> SqmTreatedPath<T, S> treatAs(EntityDomainType<S> treatTarget) throws PathException {
|
||||||
throw new FunctionArgumentException( "Embeddable paths cannot be TREAT-ed" );
|
throw new FunctionArgumentException( "Embeddable paths cannot be TREAT-ed to an entity type" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -78,8 +78,8 @@ public class SqmEntityValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends T> SqmTreatedSimplePath<T,S> treatAs(Class<S> treatJavaType) throws PathException {
|
public <S extends T> SqmTreatedEntityValuedSimplePath<T,S> treatAs(Class<S> treatJavaType) throws PathException {
|
||||||
return (SqmTreatedSimplePath<T, S>) treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ) );
|
return (SqmTreatedEntityValuedSimplePath<T, S>) treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -10,6 +10,8 @@ import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.ListPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.ListPersistentAttribute;
|
||||||
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.TreatableDomainType;
|
||||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
import org.hibernate.spi.NavigablePath;
|
import org.hibernate.spi.NavigablePath;
|
||||||
import org.hibernate.query.criteria.JpaExpression;
|
import org.hibernate.query.criteria.JpaExpression;
|
||||||
|
@ -123,8 +125,8 @@ public class SqmListJoin<O,E>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends E> SqmTreatedListJoin<O,E,S> treatAs(Class<S> treatAsType) {
|
public <S extends E> SqmTreatedListJoin<O,E,S> treatAs(Class<S> treatJavaType) {
|
||||||
return treatAs( nodeBuilder().getDomainModel().entity( treatAsType ), null );
|
return treatAs( treatJavaType, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -134,7 +136,7 @@ public class SqmListJoin<O,E>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends E> SqmTreatedListJoin<O,E,S> treatAs(Class<S> treatJavaType, String alias) {
|
public <S extends E> SqmTreatedListJoin<O,E,S> treatAs(Class<S> treatJavaType, String alias) {
|
||||||
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ), alias );
|
return treatAs( treatJavaType, alias, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -143,8 +145,18 @@ public class SqmListJoin<O,E>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends E> SqmTreatedListJoin<O,E,S> treatAs(Class<S> treatJavaType, String alias, boolean fetch) {
|
public <S extends E> SqmTreatedListJoin<O, E, S> treatAs(Class<S> treatJavaType, String alias, boolean fetch) {
|
||||||
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ), alias, fetch );
|
final ManagedDomainType<S> treatTarget = nodeBuilder().getDomainModel().managedType( treatJavaType );
|
||||||
|
final SqmTreatedListJoin<O, E, S> treat = findTreat( treatTarget, alias );
|
||||||
|
if ( treat == null ) {
|
||||||
|
if ( treatTarget instanceof TreatableDomainType<?> ) {
|
||||||
|
return addTreat( new SqmTreatedListJoin<>( this, (TreatableDomainType<S>) treatTarget, alias, fetch ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalArgumentException( "Not a treatable type: " + treatJavaType.getName() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return treat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -11,7 +11,9 @@ import jakarta.persistence.criteria.Expression;
|
||||||
import jakarta.persistence.criteria.Predicate;
|
import jakarta.persistence.criteria.Predicate;
|
||||||
|
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.MapPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.MapPersistentAttribute;
|
||||||
|
import org.hibernate.metamodel.model.domain.TreatableDomainType;
|
||||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
import org.hibernate.spi.NavigablePath;
|
import org.hibernate.spi.NavigablePath;
|
||||||
import org.hibernate.query.criteria.JpaExpression;
|
import org.hibernate.query.criteria.JpaExpression;
|
||||||
|
@ -136,7 +138,7 @@ public class SqmMapJoin<O, K, V>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends V> SqmTreatedMapJoin<O, K, V, S> treatAs(Class<S> treatJavaType) {
|
public <S extends V> SqmTreatedMapJoin<O, K, V, S> treatAs(Class<S> treatJavaType) {
|
||||||
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ) );
|
return treatAs( treatJavaType, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -146,7 +148,7 @@ public class SqmMapJoin<O, K, V>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends V> SqmTreatedMapJoin<O, K, V, S> treatAs(Class<S> treatJavaType, String alias) {
|
public <S extends V> SqmTreatedMapJoin<O, K, V, S> treatAs(Class<S> treatJavaType, String alias) {
|
||||||
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ), alias );
|
return treatAs( treatJavaType, alias, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -156,7 +158,17 @@ public class SqmMapJoin<O, K, V>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends V> SqmTreatedMapJoin<O, K, V, S> treatAs(Class<S> treatJavaType, String alias, boolean fetch) {
|
public <S extends V> SqmTreatedMapJoin<O, K, V, S> treatAs(Class<S> treatJavaType, String alias, boolean fetch) {
|
||||||
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ), alias, fetch );
|
final ManagedDomainType<S> treatTarget = nodeBuilder().getDomainModel().managedType( treatJavaType );
|
||||||
|
final SqmTreatedMapJoin<O, K, V, S> treat = findTreat( treatTarget, alias );
|
||||||
|
if ( treat == null ) {
|
||||||
|
if ( treatTarget instanceof TreatableDomainType<?> ) {
|
||||||
|
return addTreat( new SqmTreatedMapJoin<>( this, (TreatableDomainType<S>) treatTarget, alias, fetch ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalArgumentException( "Not a treatable type: " + treatJavaType.getName() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return treat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -171,13 +171,13 @@ public class SqmPluralValuedSimplePath<E> extends AbstractSqmSimplePath<E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends E> SqmTreatedSimplePath<E,S> treatAs(Class<S> treatJavaType) throws PathException {
|
public <S extends E> SqmTreatedPath<E, S> treatAs(Class<S> treatJavaType) throws PathException {
|
||||||
return (SqmTreatedSimplePath<E, S>) treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ) );
|
throw new UnsupportedOperationException( "Cannot treat plural valued simple paths" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends E> SqmTreatedPath<E, S> treatAs(EntityDomainType<S> treatTarget) throws PathException {
|
public <S extends E> SqmTreatedEntityValuedSimplePath<E, S> treatAs(EntityDomainType<S> treatTarget) throws PathException {
|
||||||
return getTreatedPath( treatTarget );
|
throw new UnsupportedOperationException( "Cannot treat plural valued simple paths" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
// @Override
|
||||||
|
|
|
@ -9,7 +9,9 @@ package org.hibernate.query.sqm.tree.domain;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.SetPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.SetPersistentAttribute;
|
||||||
|
import org.hibernate.metamodel.model.domain.TreatableDomainType;
|
||||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
import org.hibernate.spi.NavigablePath;
|
import org.hibernate.spi.NavigablePath;
|
||||||
import org.hibernate.query.criteria.JpaExpression;
|
import org.hibernate.query.criteria.JpaExpression;
|
||||||
|
@ -116,8 +118,8 @@ public class SqmSetJoin<O, E>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends E> SqmTreatedSetJoin<O,E,S> treatAs(Class<S> treatAsType) {
|
public <S extends E> SqmTreatedSetJoin<O,E,S> treatAs(Class<S> treatJavaType) {
|
||||||
return treatAs( nodeBuilder().getDomainModel().entity( treatAsType ) );
|
return treatAs( treatJavaType, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -127,7 +129,7 @@ public class SqmSetJoin<O, E>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends E> SqmTreatedSetJoin<O,E,S> treatAs(Class<S> treatJavaType, String alias) {
|
public <S extends E> SqmTreatedSetJoin<O,E,S> treatAs(Class<S> treatJavaType, String alias) {
|
||||||
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ), alias );
|
return treatAs( treatJavaType, alias, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -136,8 +138,18 @@ public class SqmSetJoin<O, E>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends E> SqmTreatedSetJoin<O,E,S> treatAs(Class<S> treatJavaType, String alias, boolean fetch) {
|
public <S extends E> SqmTreatedSetJoin<O, E, S> treatAs(Class<S> treatJavaType, String alias, boolean fetch) {
|
||||||
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ), alias, fetch );
|
final ManagedDomainType<S> treatTarget = nodeBuilder().getDomainModel().managedType( treatJavaType );
|
||||||
|
final SqmTreatedSetJoin<O, E, S> treat = findTreat( treatTarget, alias );
|
||||||
|
if ( treat == null ) {
|
||||||
|
if ( treatTarget instanceof TreatableDomainType<?> ) {
|
||||||
|
return addTreat( new SqmTreatedSetJoin<>( this, (TreatableDomainType<S>) treatTarget, alias, fetch ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalArgumentException( "Not a treatable type: " + treatJavaType.getName() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return treat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -8,8 +8,11 @@ package org.hibernate.query.sqm.tree.domain;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
||||||
|
import org.hibernate.metamodel.model.domain.TreatableDomainType;
|
||||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
import org.hibernate.spi.NavigablePath;
|
import org.hibernate.spi.NavigablePath;
|
||||||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||||
|
@ -95,7 +98,7 @@ public class SqmSingularJoin<O,T> extends AbstractSqmAttributeJoin<O,T> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends T> SqmTreatedSingularJoin<O,T,S> treatAs(Class<S> treatJavaType) {
|
public <S extends T> SqmTreatedSingularJoin<O,T,S> treatAs(Class<S> treatJavaType) {
|
||||||
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ) );
|
return treatAs( treatJavaType, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -105,7 +108,7 @@ public class SqmSingularJoin<O,T> extends AbstractSqmAttributeJoin<O,T> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends T> SqmTreatedSingularJoin<O,T,S> treatAs(Class<S> treatJavaType, String alias) {
|
public <S extends T> SqmTreatedSingularJoin<O,T,S> treatAs(Class<S> treatJavaType, String alias) {
|
||||||
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ), alias );
|
return treatAs( treatJavaType, alias, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -115,7 +118,17 @@ public class SqmSingularJoin<O,T> extends AbstractSqmAttributeJoin<O,T> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S extends T> SqmTreatedSingularJoin<O,T,S> treatAs(Class<S> treatJavaType, String alias, boolean fetch) {
|
public <S extends T> SqmTreatedSingularJoin<O,T,S> treatAs(Class<S> treatJavaType, String alias, boolean fetch) {
|
||||||
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ), alias, fetch );
|
final ManagedDomainType<S> treatTarget = nodeBuilder().getDomainModel().managedType( treatJavaType );
|
||||||
|
final SqmTreatedSingularJoin<O, T, S> treat = findTreat( treatTarget, alias );
|
||||||
|
if ( treat == null ) {
|
||||||
|
if ( treatTarget instanceof TreatableDomainType<?> ) {
|
||||||
|
return addTreat( new SqmTreatedSingularJoin<>( this, (TreatableDomainType<S>) treatTarget, alias, fetch ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalArgumentException( "Not a treatable type: " + treatJavaType.getName() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return treat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -8,7 +8,7 @@ package org.hibernate.query.sqm.tree.domain;
|
||||||
|
|
||||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
import org.hibernate.metamodel.model.domain.BagPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.BagPersistentAttribute;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.TreatableDomainType;
|
||||||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||||
import org.hibernate.query.sqm.SqmPathSource;
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||||
|
@ -20,18 +20,18 @@ import org.hibernate.spi.NavigablePath;
|
||||||
*/
|
*/
|
||||||
public class SqmTreatedBagJoin<O,T, S extends T> extends SqmBagJoin<O,S> implements SqmTreatedPath<T,S> {
|
public class SqmTreatedBagJoin<O,T, S extends T> extends SqmBagJoin<O,S> implements SqmTreatedPath<T,S> {
|
||||||
private final SqmBagJoin<O, T> wrappedPath;
|
private final SqmBagJoin<O, T> wrappedPath;
|
||||||
private final EntityDomainType<S> treatTarget;
|
private final TreatableDomainType<S> treatTarget;
|
||||||
|
|
||||||
public SqmTreatedBagJoin(
|
public SqmTreatedBagJoin(
|
||||||
SqmBagJoin<O, T> wrappedPath,
|
SqmBagJoin<O, T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
TreatableDomainType<S> treatTarget,
|
||||||
String alias) {
|
String alias) {
|
||||||
this( wrappedPath, treatTarget, alias, false );
|
this( wrappedPath, treatTarget, alias, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
public SqmTreatedBagJoin(
|
public SqmTreatedBagJoin(
|
||||||
SqmBagJoin<O, T> wrappedPath,
|
SqmBagJoin<O, T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
TreatableDomainType<S> treatTarget,
|
||||||
String alias,
|
String alias,
|
||||||
boolean fetched) {
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
|
@ -39,7 +39,7 @@ public class SqmTreatedBagJoin<O,T, S extends T> extends SqmBagJoin<O,S> impleme
|
||||||
wrappedPath.getLhs(),
|
wrappedPath.getLhs(),
|
||||||
wrappedPath.getNavigablePath()
|
wrappedPath.getNavigablePath()
|
||||||
.append( CollectionPart.Nature.ELEMENT.getName() )
|
.append( CollectionPart.Nature.ELEMENT.getName() )
|
||||||
.treatAs( treatTarget.getHibernateEntityName(), alias ),
|
.treatAs( treatTarget.getTypeName(), alias ),
|
||||||
(BagPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
(BagPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
||||||
alias,
|
alias,
|
||||||
wrappedPath.getSqmJoinType(),
|
wrappedPath.getSqmJoinType(),
|
||||||
|
@ -53,16 +53,13 @@ public class SqmTreatedBagJoin<O,T, S extends T> extends SqmBagJoin<O,S> impleme
|
||||||
private SqmTreatedBagJoin(
|
private SqmTreatedBagJoin(
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
SqmBagJoin<O, T> wrappedPath,
|
SqmBagJoin<O, T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
TreatableDomainType<S> treatTarget,
|
||||||
String alias,
|
String alias,
|
||||||
boolean fetched) {
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
super(
|
super(
|
||||||
wrappedPath.getLhs(),
|
wrappedPath.getLhs(),
|
||||||
wrappedPath.getNavigablePath().treatAs(
|
navigablePath,
|
||||||
treatTarget.getHibernateEntityName(),
|
|
||||||
alias
|
|
||||||
),
|
|
||||||
(BagPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
(BagPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
||||||
alias,
|
alias,
|
||||||
wrappedPath.getSqmJoinType(),
|
wrappedPath.getSqmJoinType(),
|
||||||
|
@ -99,7 +96,7 @@ public class SqmTreatedBagJoin<O,T, S extends T> extends SqmBagJoin<O,S> impleme
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityDomainType<S> getTreatTarget() {
|
public TreatableDomainType<S> getTreatTarget() {
|
||||||
return treatTarget;
|
return treatTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +106,7 @@ public class SqmTreatedBagJoin<O,T, S extends T> extends SqmBagJoin<O,S> impleme
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityDomainType<S> getReferencedPathSource() {
|
public TreatableDomainType<S> getReferencedPathSource() {
|
||||||
return treatTarget;
|
return treatTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +125,7 @@ public class SqmTreatedBagJoin<O,T, S extends T> extends SqmBagJoin<O,S> impleme
|
||||||
sb.append( "treat(" );
|
sb.append( "treat(" );
|
||||||
wrappedPath.appendHqlString( sb );
|
wrappedPath.appendHqlString( sb );
|
||||||
sb.append( " as " );
|
sb.append( " as " );
|
||||||
sb.append( treatTarget.getName() );
|
sb.append( treatTarget.getTypeName() );
|
||||||
sb.append( ')' );
|
sb.append( ')' );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
* 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.query.sqm.tree.domain;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
|
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||||
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
|
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||||
|
import org.hibernate.spi.NavigablePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class SqmTreatedEmbeddedValuedSimplePath<T, S extends T> extends SqmEmbeddedValuedSimplePath<S>
|
||||||
|
implements SqmTreatedPath<T, S> {
|
||||||
|
private final SqmPath<T> wrappedPath;
|
||||||
|
private final EmbeddableDomainType<S> treatTarget;
|
||||||
|
|
||||||
|
@SuppressWarnings( { "unchecked" } )
|
||||||
|
public SqmTreatedEmbeddedValuedSimplePath(
|
||||||
|
SqmPath<T> wrappedPath,
|
||||||
|
EmbeddableDomainType<S> treatTarget) {
|
||||||
|
super(
|
||||||
|
wrappedPath.getNavigablePath().treatAs( treatTarget.getTypeName() ),
|
||||||
|
(SqmPathSource<S>) wrappedPath.getReferencedPathSource(),
|
||||||
|
null,
|
||||||
|
wrappedPath.nodeBuilder()
|
||||||
|
);
|
||||||
|
this.wrappedPath = wrappedPath;
|
||||||
|
this.treatTarget = treatTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings( { "unchecked" } )
|
||||||
|
private SqmTreatedEmbeddedValuedSimplePath(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
SqmPath<T> wrappedPath,
|
||||||
|
EmbeddableDomainType<S> treatTarget) {
|
||||||
|
super(
|
||||||
|
navigablePath,
|
||||||
|
(SqmPathSource<S>) wrappedPath.getReferencedPathSource(),
|
||||||
|
null,
|
||||||
|
wrappedPath.nodeBuilder()
|
||||||
|
);
|
||||||
|
this.wrappedPath = wrappedPath;
|
||||||
|
this.treatTarget = treatTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmTreatedEmbeddedValuedSimplePath<T, S> copy(SqmCopyContext context) {
|
||||||
|
final SqmTreatedEmbeddedValuedSimplePath<T, S> existing = context.getCopy( this );
|
||||||
|
if ( existing != null ) {
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
final SqmTreatedEmbeddedValuedSimplePath<T, S> path = context.registerCopy(
|
||||||
|
this,
|
||||||
|
new SqmTreatedEmbeddedValuedSimplePath<>(
|
||||||
|
getNavigablePath(),
|
||||||
|
wrappedPath.copy( context ),
|
||||||
|
treatTarget
|
||||||
|
)
|
||||||
|
);
|
||||||
|
copyTo( path, context );
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EmbeddableDomainType<S> getTreatTarget() {
|
||||||
|
return treatTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPath<T> getWrappedPath() {
|
||||||
|
return wrappedPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPathSource<S> getNodeType() {
|
||||||
|
return treatTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPathSource<?> getResolvedModel() {
|
||||||
|
return treatTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EmbeddableDomainType<S> getReferencedPathSource() {
|
||||||
|
return getTreatTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPath<?> getLhs() {
|
||||||
|
return wrappedPath.getLhs();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||||
|
return walker.visitTreatedPath( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPath<?> resolvePathPart(String name, boolean isTerminal, SqmCreationState creationState) {
|
||||||
|
final SqmPath<?> sqmPath = get( name );
|
||||||
|
creationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );
|
||||||
|
return sqmPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void appendHqlString(StringBuilder sb) {
|
||||||
|
sb.append( "treat(" );
|
||||||
|
wrappedPath.appendHqlString( sb );
|
||||||
|
sb.append( " as " );
|
||||||
|
sb.append( treatTarget.getTypeName() );
|
||||||
|
sb.append( ')' );
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,14 +17,14 @@ import org.hibernate.spi.NavigablePath;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class SqmTreatedSimplePath<T, S extends T>
|
public class SqmTreatedEntityValuedSimplePath<T, S extends T>
|
||||||
extends SqmEntityValuedSimplePath<S>
|
extends SqmEntityValuedSimplePath<S>
|
||||||
implements SqmSimplePath<S>, SqmTreatedPath<T,S> {
|
implements SqmSimplePath<S>, SqmTreatedPath<T,S> {
|
||||||
|
|
||||||
private final EntityDomainType<S> treatTarget;
|
private final EntityDomainType<S> treatTarget;
|
||||||
private final SqmPath<T> wrappedPath;
|
private final SqmPath<T> wrappedPath;
|
||||||
|
|
||||||
public SqmTreatedSimplePath(
|
public SqmTreatedEntityValuedSimplePath(
|
||||||
SqmPluralValuedSimplePath<T> wrappedPath,
|
SqmPluralValuedSimplePath<T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
EntityDomainType<S> treatTarget,
|
||||||
NodeBuilder nodeBuilder) {
|
NodeBuilder nodeBuilder) {
|
||||||
|
@ -41,7 +41,7 @@ public class SqmTreatedSimplePath<T, S extends T>
|
||||||
this.wrappedPath = wrappedPath;
|
this.wrappedPath = wrappedPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SqmTreatedSimplePath(
|
public SqmTreatedEntityValuedSimplePath(
|
||||||
SqmPath<T> wrappedPath,
|
SqmPath<T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
EntityDomainType<S> treatTarget,
|
||||||
NodeBuilder nodeBuilder) {
|
NodeBuilder nodeBuilder) {
|
||||||
|
@ -58,7 +58,7 @@ public class SqmTreatedSimplePath<T, S extends T>
|
||||||
this.wrappedPath = wrappedPath;
|
this.wrappedPath = wrappedPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SqmTreatedSimplePath(
|
private SqmTreatedEntityValuedSimplePath(
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
SqmPath<T> wrappedPath,
|
SqmPath<T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
EntityDomainType<S> treatTarget,
|
||||||
|
@ -75,15 +75,15 @@ public class SqmTreatedSimplePath<T, S extends T>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmTreatedSimplePath<T, S> copy(SqmCopyContext context) {
|
public SqmTreatedEntityValuedSimplePath<T, S> copy(SqmCopyContext context) {
|
||||||
final SqmTreatedSimplePath<T, S> existing = context.getCopy( this );
|
final SqmTreatedEntityValuedSimplePath<T, S> existing = context.getCopy( this );
|
||||||
if ( existing != null ) {
|
if ( existing != null ) {
|
||||||
return existing;
|
return existing;
|
||||||
}
|
}
|
||||||
|
|
||||||
final SqmTreatedSimplePath<T, S> path = context.registerCopy(
|
final SqmTreatedEntityValuedSimplePath<T, S> path = context.registerCopy(
|
||||||
this,
|
this,
|
||||||
new SqmTreatedSimplePath<>(
|
new SqmTreatedEntityValuedSimplePath<>(
|
||||||
getNavigablePath(),
|
getNavigablePath(),
|
||||||
wrappedPath.copy( context ),
|
wrappedPath.copy( context ),
|
||||||
getTreatTarget(),
|
getTreatTarget(),
|
||||||
|
@ -120,7 +120,7 @@ public class SqmTreatedSimplePath<T, S extends T>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S1 extends S> SqmTreatedSimplePath<S,S1> treatAs(Class<S1> treatJavaType) throws PathException {
|
public <S1 extends S> SqmTreatedEntityValuedSimplePath<S,S1> treatAs(Class<S1> treatJavaType) throws PathException {
|
||||||
return super.treatAs( treatJavaType );
|
return super.treatAs( treatJavaType );
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
package org.hibernate.query.sqm.tree.domain;
|
package org.hibernate.query.sqm.tree.domain;
|
||||||
|
|
||||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
|
||||||
import org.hibernate.metamodel.model.domain.ListPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.ListPersistentAttribute;
|
||||||
|
import org.hibernate.metamodel.model.domain.TreatableDomainType;
|
||||||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||||
import org.hibernate.query.sqm.SqmPathSource;
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
|
@ -22,18 +22,18 @@ import org.hibernate.spi.NavigablePath;
|
||||||
*/
|
*/
|
||||||
public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> implements SqmTreatedPath<T,S> {
|
public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> implements SqmTreatedPath<T,S> {
|
||||||
private final SqmListJoin<O,T> wrappedPath;
|
private final SqmListJoin<O,T> wrappedPath;
|
||||||
private final EntityDomainType<S> treatTarget;
|
private final TreatableDomainType<S> treatTarget;
|
||||||
|
|
||||||
public SqmTreatedListJoin(
|
public SqmTreatedListJoin(
|
||||||
SqmListJoin<O, T> wrappedPath,
|
SqmListJoin<O, T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
TreatableDomainType<S> treatTarget,
|
||||||
String alias) {
|
String alias) {
|
||||||
this( wrappedPath, treatTarget, alias, false );
|
this( wrappedPath, treatTarget, alias, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
public SqmTreatedListJoin(
|
public SqmTreatedListJoin(
|
||||||
SqmListJoin<O, T> wrappedPath,
|
SqmListJoin<O, T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
TreatableDomainType<S> treatTarget,
|
||||||
String alias,
|
String alias,
|
||||||
boolean fetched) {
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
|
@ -41,7 +41,7 @@ public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> imple
|
||||||
wrappedPath.getLhs(),
|
wrappedPath.getLhs(),
|
||||||
wrappedPath.getNavigablePath()
|
wrappedPath.getNavigablePath()
|
||||||
.append( CollectionPart.Nature.ELEMENT.getName() )
|
.append( CollectionPart.Nature.ELEMENT.getName() )
|
||||||
.treatAs( treatTarget.getHibernateEntityName(), alias ),
|
.treatAs( treatTarget.getTypeName(), alias ),
|
||||||
(ListPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
(ListPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
||||||
alias,
|
alias,
|
||||||
wrappedPath.getSqmJoinType(),
|
wrappedPath.getSqmJoinType(),
|
||||||
|
@ -55,7 +55,7 @@ public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> imple
|
||||||
private SqmTreatedListJoin(
|
private SqmTreatedListJoin(
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
SqmListJoin<O, T> wrappedPath,
|
SqmListJoin<O, T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
TreatableDomainType<S> treatTarget,
|
||||||
String alias,
|
String alias,
|
||||||
boolean fetched) {
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
|
@ -98,7 +98,7 @@ public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> imple
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityDomainType<S> getTreatTarget() {
|
public TreatableDomainType<S> getTreatTarget() {
|
||||||
return treatTarget;
|
return treatTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> imple
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityDomainType<S> getReferencedPathSource() {
|
public TreatableDomainType<S> getReferencedPathSource() {
|
||||||
return treatTarget;
|
return treatTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> imple
|
||||||
sb.append( "treat(" );
|
sb.append( "treat(" );
|
||||||
wrappedPath.appendHqlString( sb );
|
wrappedPath.appendHqlString( sb );
|
||||||
sb.append( " as " );
|
sb.append( " as " );
|
||||||
sb.append( treatTarget.getName() );
|
sb.append( treatTarget.getTypeName() );
|
||||||
sb.append( ')' );
|
sb.append( ')' );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
package org.hibernate.query.sqm.tree.domain;
|
package org.hibernate.query.sqm.tree.domain;
|
||||||
|
|
||||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.TreatableDomainType;
|
||||||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||||
import org.hibernate.query.sqm.SqmPathSource;
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||||
|
@ -18,18 +18,18 @@ import org.hibernate.spi.NavigablePath;
|
||||||
*/
|
*/
|
||||||
public class SqmTreatedMapJoin<O, K, V, S extends V> extends SqmMapJoin<O, K, S> implements SqmTreatedPath<V, S> {
|
public class SqmTreatedMapJoin<O, K, V, S extends V> extends SqmMapJoin<O, K, S> implements SqmTreatedPath<V, S> {
|
||||||
private final SqmMapJoin<O, K, V> wrappedPath;
|
private final SqmMapJoin<O, K, V> wrappedPath;
|
||||||
private final EntityDomainType<S> treatTarget;
|
private final TreatableDomainType<S> treatTarget;
|
||||||
|
|
||||||
public SqmTreatedMapJoin(
|
public SqmTreatedMapJoin(
|
||||||
SqmMapJoin<O, K, V> wrappedPath,
|
SqmMapJoin<O, K, V> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
TreatableDomainType<S> treatTarget,
|
||||||
String alias) {
|
String alias) {
|
||||||
this( wrappedPath, treatTarget, alias, false );
|
this( wrappedPath, treatTarget, alias, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
public SqmTreatedMapJoin(
|
public SqmTreatedMapJoin(
|
||||||
SqmMapJoin<O, K, V> wrappedPath,
|
SqmMapJoin<O, K, V> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
TreatableDomainType<S> treatTarget,
|
||||||
String alias,
|
String alias,
|
||||||
boolean fetched) {
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
|
@ -37,7 +37,7 @@ public class SqmTreatedMapJoin<O, K, V, S extends V> extends SqmMapJoin<O, K, S>
|
||||||
wrappedPath.getLhs(),
|
wrappedPath.getLhs(),
|
||||||
wrappedPath.getNavigablePath()
|
wrappedPath.getNavigablePath()
|
||||||
.append( CollectionPart.Nature.ELEMENT.getName() )
|
.append( CollectionPart.Nature.ELEMENT.getName() )
|
||||||
.treatAs( treatTarget.getHibernateEntityName(), alias ),
|
.treatAs( treatTarget.getTypeName(), alias ),
|
||||||
( (SqmMapJoin<O, K, S>) wrappedPath ).getModel(),
|
( (SqmMapJoin<O, K, S>) wrappedPath ).getModel(),
|
||||||
alias,
|
alias,
|
||||||
wrappedPath.getSqmJoinType(),
|
wrappedPath.getSqmJoinType(),
|
||||||
|
@ -51,7 +51,7 @@ public class SqmTreatedMapJoin<O, K, V, S extends V> extends SqmMapJoin<O, K, S>
|
||||||
private SqmTreatedMapJoin(
|
private SqmTreatedMapJoin(
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
SqmMapJoin<O, K, V> wrappedPath,
|
SqmMapJoin<O, K, V> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
TreatableDomainType<S> treatTarget,
|
||||||
String alias,
|
String alias,
|
||||||
boolean fetched) {
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
|
@ -94,7 +94,7 @@ public class SqmTreatedMapJoin<O, K, V, S extends V> extends SqmMapJoin<O, K, S>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityDomainType<S> getTreatTarget() {
|
public TreatableDomainType<S> getTreatTarget() {
|
||||||
return treatTarget;
|
return treatTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ public class SqmTreatedMapJoin<O, K, V, S extends V> extends SqmMapJoin<O, K, S>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityDomainType<S> getReferencedPathSource() {
|
public TreatableDomainType<S> getReferencedPathSource() {
|
||||||
return treatTarget;
|
return treatTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ public class SqmTreatedMapJoin<O, K, V, S extends V> extends SqmMapJoin<O, K, S>
|
||||||
sb.append( "treat(" );
|
sb.append( "treat(" );
|
||||||
wrappedPath.appendHqlString( sb );
|
wrappedPath.appendHqlString( sb );
|
||||||
sb.append( " as " );
|
sb.append( " as " );
|
||||||
sb.append( treatTarget.getName() );
|
sb.append( treatTarget.getTypeName() );
|
||||||
sb.append( ')' );
|
sb.append( ')' );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,13 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.query.sqm.tree.domain;
|
package org.hibernate.query.sqm.tree.domain;
|
||||||
|
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.query.sqm.SqmPathSource;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface SqmTreatedPath<T, S extends T> extends SqmPathWrapper<T, S> {
|
public interface SqmTreatedPath<T, S extends T> extends SqmPathWrapper<T, S> {
|
||||||
EntityDomainType<S> getTreatTarget();
|
ManagedDomainType<S> getTreatTarget();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
SqmPath<T> getWrappedPath();
|
SqmPath<T> getWrappedPath();
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
package org.hibernate.query.sqm.tree.domain;
|
package org.hibernate.query.sqm.tree.domain;
|
||||||
|
|
||||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.TreatableDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.SetPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.SetPersistentAttribute;
|
||||||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||||
import org.hibernate.query.sqm.SqmPathSource;
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
|
@ -20,18 +20,18 @@ import org.hibernate.spi.NavigablePath;
|
||||||
*/
|
*/
|
||||||
public class SqmTreatedSetJoin<O,T, S extends T> extends SqmSetJoin<O,S> implements SqmTreatedPath<T,S> {
|
public class SqmTreatedSetJoin<O,T, S extends T> extends SqmSetJoin<O,S> implements SqmTreatedPath<T,S> {
|
||||||
private final SqmSetJoin<O,T> wrappedPath;
|
private final SqmSetJoin<O,T> wrappedPath;
|
||||||
private final EntityDomainType<S> treatTarget;
|
private final TreatableDomainType<S> treatTarget;
|
||||||
|
|
||||||
public SqmTreatedSetJoin(
|
public SqmTreatedSetJoin(
|
||||||
SqmSetJoin<O, T> wrappedPath,
|
SqmSetJoin<O, T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
TreatableDomainType<S> treatTarget,
|
||||||
String alias) {
|
String alias) {
|
||||||
this( wrappedPath, treatTarget, alias, false );
|
this( wrappedPath, treatTarget, alias, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
public SqmTreatedSetJoin(
|
public SqmTreatedSetJoin(
|
||||||
SqmSetJoin<O, T> wrappedPath,
|
SqmSetJoin<O, T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
TreatableDomainType<S> treatTarget,
|
||||||
String alias,
|
String alias,
|
||||||
boolean fetched) {
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
|
@ -39,7 +39,7 @@ public class SqmTreatedSetJoin<O,T, S extends T> extends SqmSetJoin<O,S> impleme
|
||||||
wrappedPath.getLhs(),
|
wrappedPath.getLhs(),
|
||||||
wrappedPath.getNavigablePath()
|
wrappedPath.getNavigablePath()
|
||||||
.append( CollectionPart.Nature.ELEMENT.getName() )
|
.append( CollectionPart.Nature.ELEMENT.getName() )
|
||||||
.treatAs( treatTarget.getHibernateEntityName(), alias ),
|
.treatAs( treatTarget.getTypeName(), alias ),
|
||||||
(SetPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
(SetPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
||||||
alias,
|
alias,
|
||||||
wrappedPath.getSqmJoinType(),
|
wrappedPath.getSqmJoinType(),
|
||||||
|
@ -53,7 +53,7 @@ public class SqmTreatedSetJoin<O,T, S extends T> extends SqmSetJoin<O,S> impleme
|
||||||
private SqmTreatedSetJoin(
|
private SqmTreatedSetJoin(
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
SqmSetJoin<O, T> wrappedPath,
|
SqmSetJoin<O, T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
TreatableDomainType<S> treatTarget,
|
||||||
String alias,
|
String alias,
|
||||||
boolean fetched) {
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
|
@ -96,7 +96,7 @@ public class SqmTreatedSetJoin<O,T, S extends T> extends SqmSetJoin<O,S> impleme
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityDomainType<S> getTreatTarget() {
|
public TreatableDomainType<S> getTreatTarget() {
|
||||||
return treatTarget;
|
return treatTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ public class SqmTreatedSetJoin<O,T, S extends T> extends SqmSetJoin<O,S> impleme
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityDomainType<S> getReferencedPathSource() {
|
public TreatableDomainType<S> getReferencedPathSource() {
|
||||||
return treatTarget;
|
return treatTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ public class SqmTreatedSetJoin<O,T, S extends T> extends SqmSetJoin<O,S> impleme
|
||||||
sb.append( "treat(" );
|
sb.append( "treat(" );
|
||||||
wrappedPath.appendHqlString( sb );
|
wrappedPath.appendHqlString( sb );
|
||||||
sb.append( " as " );
|
sb.append( " as " );
|
||||||
sb.append( treatTarget.getName() );
|
sb.append( treatTarget.getTypeName() );
|
||||||
sb.append( ')' );
|
sb.append( ')' );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.query.sqm.tree.domain;
|
package org.hibernate.query.sqm.tree.domain;
|
||||||
|
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
|
||||||
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
||||||
|
import org.hibernate.metamodel.model.domain.TreatableDomainType;
|
||||||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||||
import org.hibernate.query.sqm.SqmPathSource;
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||||
|
@ -19,25 +19,25 @@ import org.hibernate.spi.NavigablePath;
|
||||||
*/
|
*/
|
||||||
public class SqmTreatedSingularJoin<O,T, S extends T> extends SqmSingularJoin<O,S> implements SqmTreatedPath<T,S> {
|
public class SqmTreatedSingularJoin<O,T, S extends T> extends SqmSingularJoin<O,S> implements SqmTreatedPath<T,S> {
|
||||||
private final SqmSingularJoin<O,T> wrappedPath;
|
private final SqmSingularJoin<O,T> wrappedPath;
|
||||||
private final EntityDomainType<S> treatTarget;
|
private final TreatableDomainType<S> treatTarget;
|
||||||
|
|
||||||
public SqmTreatedSingularJoin(
|
public SqmTreatedSingularJoin(
|
||||||
SqmSingularJoin<O,T> wrappedPath,
|
SqmSingularJoin<O,T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
TreatableDomainType<S> treatTarget,
|
||||||
String alias) {
|
String alias) {
|
||||||
this( wrappedPath, treatTarget, alias, false );
|
this( wrappedPath, treatTarget, alias, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
public SqmTreatedSingularJoin(
|
public SqmTreatedSingularJoin(
|
||||||
SqmSingularJoin<O,T> wrappedPath,
|
SqmSingularJoin<O,T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
TreatableDomainType<S> treatTarget,
|
||||||
String alias,
|
String alias,
|
||||||
boolean fetched) {
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
super(
|
super(
|
||||||
wrappedPath.getLhs(),
|
wrappedPath.getLhs(),
|
||||||
wrappedPath.getNavigablePath().treatAs(
|
wrappedPath.getNavigablePath().treatAs(
|
||||||
treatTarget.getHibernateEntityName(),
|
treatTarget.getTypeName(),
|
||||||
alias
|
alias
|
||||||
),
|
),
|
||||||
(SingularPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
(SingularPersistentAttribute<O, S>) wrappedPath.getAttribute(),
|
||||||
|
@ -53,7 +53,7 @@ public class SqmTreatedSingularJoin<O,T, S extends T> extends SqmSingularJoin<O,
|
||||||
private SqmTreatedSingularJoin(
|
private SqmTreatedSingularJoin(
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
SqmSingularJoin<O,T> wrappedPath,
|
SqmSingularJoin<O,T> wrappedPath,
|
||||||
EntityDomainType<S> treatTarget,
|
TreatableDomainType<S> treatTarget,
|
||||||
String alias,
|
String alias,
|
||||||
boolean fetched) {
|
boolean fetched) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
|
@ -96,7 +96,7 @@ public class SqmTreatedSingularJoin<O,T, S extends T> extends SqmSingularJoin<O,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityDomainType<S> getTreatTarget() {
|
public TreatableDomainType<S> getTreatTarget() {
|
||||||
return treatTarget;
|
return treatTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ public class SqmTreatedSingularJoin<O,T, S extends T> extends SqmSingularJoin<O,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityDomainType<S> getReferencedPathSource() {
|
public TreatableDomainType<S> getReferencedPathSource() {
|
||||||
return treatTarget;
|
return treatTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ public class SqmTreatedSingularJoin<O,T, S extends T> extends SqmSingularJoin<O,
|
||||||
sb.append( "treat(" );
|
sb.append( "treat(" );
|
||||||
wrappedPath.appendHqlString( sb );
|
wrappedPath.appendHqlString( sb );
|
||||||
sb.append( " as " );
|
sb.append( " as " );
|
||||||
sb.append( treatTarget.getName() );
|
sb.append( treatTarget.getTypeName() );
|
||||||
sb.append( ')' );
|
sb.append( ')' );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
* 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.query.sqm.tree.expression;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||||
|
import org.hibernate.query.hql.HqlInterpretationException;
|
||||||
|
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||||
|
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||||
|
import org.hibernate.query.sqm.NodeBuilder;
|
||||||
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
|
import org.hibernate.query.sqm.SqmExpressible;
|
||||||
|
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||||
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
|
import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
|
||||||
|
import org.hibernate.type.BasicType;
|
||||||
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a reference to an embeddable type as a literal.
|
||||||
|
*
|
||||||
|
* @author Marco Belladelli
|
||||||
|
*/
|
||||||
|
public class SqmLiteralEmbeddableType<T>
|
||||||
|
extends AbstractSqmExpression<T>
|
||||||
|
implements SqmSelectableNode<T>, SemanticPathPart {
|
||||||
|
final EmbeddableDomainType<T> embeddableDomainType;
|
||||||
|
|
||||||
|
public SqmLiteralEmbeddableType(
|
||||||
|
EmbeddableDomainType<T> embeddableDomainType,
|
||||||
|
NodeBuilder nodeBuilder) {
|
||||||
|
//noinspection unchecked
|
||||||
|
super(
|
||||||
|
(SqmExpressible<? super T>) nodeBuilder.getTypeConfiguration()
|
||||||
|
.getBasicTypeRegistry()
|
||||||
|
.resolve( StandardBasicTypes.CLASS ),
|
||||||
|
nodeBuilder
|
||||||
|
);
|
||||||
|
this.embeddableDomainType = embeddableDomainType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmbeddableDomainType<T> getEmbeddableDomainType() {
|
||||||
|
return embeddableDomainType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BasicType<T> getNodeType() {
|
||||||
|
return (BasicType<T>) super.getNodeType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EmbeddableDomainType<T> getExpressible() {
|
||||||
|
return embeddableDomainType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmLiteralEmbeddableType<T> copy(SqmCopyContext context) {
|
||||||
|
final SqmLiteralEmbeddableType<T> existing = context.getCopy( this );
|
||||||
|
if ( existing != null ) {
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
final SqmLiteralEmbeddableType<T> expression = context.registerCopy(
|
||||||
|
this,
|
||||||
|
new SqmLiteralEmbeddableType<>(
|
||||||
|
embeddableDomainType,
|
||||||
|
nodeBuilder()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
copyTo( expression, context );
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void internalApplyInferableType(SqmExpressible<?> type) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||||
|
return walker.visitEmbeddableTypeLiteralExpression( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String asLoggableText() {
|
||||||
|
return "TYPE(" + embeddableDomainType + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SemanticPathPart resolvePathPart(
|
||||||
|
String name,
|
||||||
|
boolean isTerminal,
|
||||||
|
SqmCreationState creationState) {
|
||||||
|
throw new HqlInterpretationException( "Cannot dereference an embeddable name" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPath<?> resolveIndexedAccess(
|
||||||
|
SqmExpression<?> selector,
|
||||||
|
boolean isTerminal,
|
||||||
|
SqmCreationState creationState) {
|
||||||
|
throw new HqlInterpretationException( "Cannot dereference an embeddable name" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void appendHqlString(StringBuilder sb) {
|
||||||
|
sb.append( embeddableDomainType.getTypeName() );
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,11 +8,8 @@ package org.hibernate.query.sqm.tree.from;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import jakarta.persistence.criteria.CollectionJoin;
|
|
||||||
import jakarta.persistence.criteria.JoinType;
|
import jakarta.persistence.criteria.JoinType;
|
||||||
import jakarta.persistence.criteria.ListJoin;
|
|
||||||
import jakarta.persistence.criteria.MapJoin;
|
|
||||||
import jakarta.persistence.criteria.SetJoin;
|
|
||||||
import jakarta.persistence.metamodel.CollectionAttribute;
|
import jakarta.persistence.metamodel.CollectionAttribute;
|
||||||
import jakarta.persistence.metamodel.ListAttribute;
|
import jakarta.persistence.metamodel.ListAttribute;
|
||||||
import jakarta.persistence.metamodel.MapAttribute;
|
import jakarta.persistence.metamodel.MapAttribute;
|
||||||
|
@ -20,11 +17,7 @@ import jakarta.persistence.metamodel.SetAttribute;
|
||||||
import jakarta.persistence.metamodel.SingularAttribute;
|
import jakarta.persistence.metamodel.SingularAttribute;
|
||||||
|
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
import org.hibernate.query.PathException;
|
|
||||||
import org.hibernate.query.criteria.JpaFrom;
|
import org.hibernate.query.criteria.JpaFrom;
|
||||||
import org.hibernate.query.criteria.JpaJoin;
|
|
||||||
import org.hibernate.query.criteria.JpaPath;
|
|
||||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
|
||||||
import org.hibernate.query.sqm.SqmPathSource;
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||||
|
@ -35,6 +28,8 @@ import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmSetJoin;
|
import org.hibernate.query.sqm.tree.domain.SqmSetJoin;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmSingularJoin;
|
import org.hibernate.query.sqm.tree.domain.SqmSingularJoin;
|
||||||
|
|
||||||
|
import static org.hibernate.internal.util.collections.CollectionHelper.isEmpty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Models a Bindable's inclusion in the {@code FROM} clause.
|
* Models a Bindable's inclusion in the {@code FROM} clause.
|
||||||
*
|
*
|
||||||
|
@ -67,6 +62,15 @@ public interface SqmFrom<O,T> extends SqmVisitableNode, SqmPath<T>, JpaFrom<O, T
|
||||||
*/
|
*/
|
||||||
void visitSqmJoins(Consumer<SqmJoin<T, ?>> consumer);
|
void visitSqmJoins(Consumer<SqmJoin<T, ?>> consumer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The treats associated with this SqmFrom
|
||||||
|
*/
|
||||||
|
List<SqmFrom<?, ?>> getSqmTreats();
|
||||||
|
|
||||||
|
default boolean hasTreats() {
|
||||||
|
return !isEmpty( getSqmTreats() );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
<S extends T> SqmFrom<?, S> treatAs(Class<S> treatAsType);
|
<S extends T> SqmFrom<?, S> treatAs(Class<S> treatAsType);
|
||||||
|
|
||||||
|
@ -77,14 +81,6 @@ public interface SqmFrom<O,T> extends SqmVisitableNode, SqmPath<T>, JpaFrom<O, T
|
||||||
|
|
||||||
<S extends T> SqmFrom<?, S> treatAs(EntityDomainType<S> treatTarget, String alias);
|
<S extends T> SqmFrom<?, S> treatAs(EntityDomainType<S> treatTarget, String alias);
|
||||||
|
|
||||||
boolean hasTreats();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The treats associated with this SqmFrom
|
|
||||||
*/
|
|
||||||
List<SqmFrom<?,?>> getSqmTreats();
|
|
||||||
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// JPA
|
// JPA
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ public class SqmFromClause implements Serializable {
|
||||||
final SqmTreatedPath<?, ?> treatedPath = (SqmTreatedPath<?, ?>) sqmFrom;
|
final SqmTreatedPath<?, ?> treatedPath = (SqmTreatedPath<?, ?>) sqmFrom;
|
||||||
sb.append( "treat(" );
|
sb.append( "treat(" );
|
||||||
sb.append( treatedPath.getWrappedPath().resolveAlias() );
|
sb.append( treatedPath.getWrappedPath().resolveAlias() );
|
||||||
sb.append( " as " ).append( treatedPath.getTreatTarget().getName() ).append( ')' );
|
sb.append( " as " ).append( treatedPath.getTreatTarget().getTypeName() ).append( ')' );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sb.append( sqmFrom.resolveAlias() );
|
sb.append( sqmFrom.resolveAlias() );
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.hibernate.sql.ast.tree.expression.AggregateColumnWriteExpression;
|
||||||
import org.hibernate.sql.ast.tree.expression.Distinct;
|
import org.hibernate.sql.ast.tree.expression.Distinct;
|
||||||
import org.hibernate.sql.ast.tree.expression.Duration;
|
import org.hibernate.sql.ast.tree.expression.Duration;
|
||||||
import org.hibernate.sql.ast.tree.expression.DurationUnit;
|
import org.hibernate.sql.ast.tree.expression.DurationUnit;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.EmbeddableTypeLiteral;
|
||||||
import org.hibernate.sql.ast.tree.expression.EntityTypeLiteral;
|
import org.hibernate.sql.ast.tree.expression.EntityTypeLiteral;
|
||||||
import org.hibernate.sql.ast.tree.expression.Every;
|
import org.hibernate.sql.ast.tree.expression.Every;
|
||||||
import org.hibernate.sql.ast.tree.expression.ExtractUnit;
|
import org.hibernate.sql.ast.tree.expression.ExtractUnit;
|
||||||
|
@ -167,6 +168,8 @@ public interface SqlAstWalker {
|
||||||
|
|
||||||
void visitEntityTypeLiteral(EntityTypeLiteral expression);
|
void visitEntityTypeLiteral(EntityTypeLiteral expression);
|
||||||
|
|
||||||
|
void visitEmbeddableTypeLiteral(EmbeddableTypeLiteral expression);
|
||||||
|
|
||||||
void visitTuple(SqlTuple tuple);
|
void visitTuple(SqlTuple tuple);
|
||||||
|
|
||||||
void visitCollation(Collation collation);
|
void visitCollation(Collation collation);
|
||||||
|
|
|
@ -115,6 +115,7 @@ import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
import org.hibernate.sql.ast.tree.expression.Distinct;
|
import org.hibernate.sql.ast.tree.expression.Distinct;
|
||||||
import org.hibernate.sql.ast.tree.expression.Duration;
|
import org.hibernate.sql.ast.tree.expression.Duration;
|
||||||
import org.hibernate.sql.ast.tree.expression.DurationUnit;
|
import org.hibernate.sql.ast.tree.expression.DurationUnit;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.EmbeddableTypeLiteral;
|
||||||
import org.hibernate.sql.ast.tree.expression.EntityTypeLiteral;
|
import org.hibernate.sql.ast.tree.expression.EntityTypeLiteral;
|
||||||
import org.hibernate.sql.ast.tree.expression.Every;
|
import org.hibernate.sql.ast.tree.expression.Every;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
|
@ -218,6 +219,7 @@ import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.SqlTypes;
|
import org.hibernate.type.SqlTypes;
|
||||||
import org.hibernate.type.StandardBasicTypes;
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||||
import org.hibernate.type.descriptor.java.JavaType;
|
import org.hibernate.type.descriptor.java.JavaType;
|
||||||
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
|
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
|
||||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||||
|
@ -225,6 +227,7 @@ import org.hibernate.type.descriptor.sql.DdlType;
|
||||||
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
import static org.hibernate.persister.entity.DiscriminatorHelper.jdbcLiteral;
|
||||||
import static org.hibernate.query.sqm.BinaryArithmeticOperator.DIVIDE_PORTABLE;
|
import static org.hibernate.query.sqm.BinaryArithmeticOperator.DIVIDE_PORTABLE;
|
||||||
import static org.hibernate.query.sqm.TemporalUnit.NANOSECOND;
|
import static org.hibernate.query.sqm.TemporalUnit.NANOSECOND;
|
||||||
import static org.hibernate.sql.ast.SqlTreePrinter.logSqlAst;
|
import static org.hibernate.sql.ast.SqlTreePrinter.logSqlAst;
|
||||||
|
@ -7203,6 +7206,19 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
||||||
appendSql( expression.getEntityTypeDescriptor().getDiscriminatorSQLValue() );
|
appendSql( expression.getEntityTypeDescriptor().getDiscriminatorSQLValue() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings( { "rawtypes", "unchecked" } )
|
||||||
|
@Override
|
||||||
|
public void visitEmbeddableTypeLiteral(EmbeddableTypeLiteral expression) {
|
||||||
|
final BasicValueConverter valueConverter = expression.getJdbcMapping().getValueConverter();
|
||||||
|
appendSql( jdbcLiteral(
|
||||||
|
valueConverter != null ?
|
||||||
|
valueConverter.toRelationalValue( expression.getEmbeddableClass() ) :
|
||||||
|
expression.getEmbeddableClass(),
|
||||||
|
expression.getExpressionType().getSingleJdbcMapping().getJdbcLiteralFormatter(),
|
||||||
|
getDialect()
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitBinaryArithmeticExpression(BinaryArithmeticExpression arithmeticExpression) {
|
public void visitBinaryArithmeticExpression(BinaryArithmeticExpression arithmeticExpression) {
|
||||||
final BinaryArithmeticOperator operator = arithmeticExpression.getOperator();
|
final BinaryArithmeticOperator operator = arithmeticExpression.getOperator();
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
import org.hibernate.sql.ast.tree.expression.Distinct;
|
import org.hibernate.sql.ast.tree.expression.Distinct;
|
||||||
import org.hibernate.sql.ast.tree.expression.Duration;
|
import org.hibernate.sql.ast.tree.expression.Duration;
|
||||||
import org.hibernate.sql.ast.tree.expression.DurationUnit;
|
import org.hibernate.sql.ast.tree.expression.DurationUnit;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.EmbeddableTypeLiteral;
|
||||||
import org.hibernate.sql.ast.tree.expression.EntityTypeLiteral;
|
import org.hibernate.sql.ast.tree.expression.EntityTypeLiteral;
|
||||||
import org.hibernate.sql.ast.tree.expression.Every;
|
import org.hibernate.sql.ast.tree.expression.Every;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
|
@ -529,6 +530,10 @@ public class AbstractSqlAstWalker implements SqlAstWalker {
|
||||||
public void visitEntityTypeLiteral(EntityTypeLiteral expression) {
|
public void visitEntityTypeLiteral(EntityTypeLiteral expression) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitEmbeddableTypeLiteral(EmbeddableTypeLiteral expression) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitNamedTableReference(NamedTableReference tableReference) {
|
public void visitNamedTableReference(NamedTableReference tableReference) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
import org.hibernate.sql.ast.tree.expression.Distinct;
|
import org.hibernate.sql.ast.tree.expression.Distinct;
|
||||||
import org.hibernate.sql.ast.tree.expression.Duration;
|
import org.hibernate.sql.ast.tree.expression.Duration;
|
||||||
import org.hibernate.sql.ast.tree.expression.DurationUnit;
|
import org.hibernate.sql.ast.tree.expression.DurationUnit;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.EmbeddableTypeLiteral;
|
||||||
import org.hibernate.sql.ast.tree.expression.EntityTypeLiteral;
|
import org.hibernate.sql.ast.tree.expression.EntityTypeLiteral;
|
||||||
import org.hibernate.sql.ast.tree.expression.Every;
|
import org.hibernate.sql.ast.tree.expression.Every;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
|
@ -249,6 +250,10 @@ public class AggregateFunctionChecker extends AbstractSqlAstWalker {
|
||||||
public void visitEntityTypeLiteral(EntityTypeLiteral expression) {
|
public void visitEntityTypeLiteral(EntityTypeLiteral expression) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitEmbeddableTypeLiteral(EmbeddableTypeLiteral expression) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitSqlSelectionExpression(SqlSelectionExpression expression) {
|
public void visitSqlSelectionExpression(SqlSelectionExpression expression) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.hibernate.sql.ast.tree.expression.AggregateColumnWriteExpression;
|
||||||
import org.hibernate.sql.ast.tree.expression.Distinct;
|
import org.hibernate.sql.ast.tree.expression.Distinct;
|
||||||
import org.hibernate.sql.ast.tree.expression.Duration;
|
import org.hibernate.sql.ast.tree.expression.Duration;
|
||||||
import org.hibernate.sql.ast.tree.expression.DurationUnit;
|
import org.hibernate.sql.ast.tree.expression.DurationUnit;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.EmbeddableTypeLiteral;
|
||||||
import org.hibernate.sql.ast.tree.expression.EntityTypeLiteral;
|
import org.hibernate.sql.ast.tree.expression.EntityTypeLiteral;
|
||||||
import org.hibernate.sql.ast.tree.expression.Every;
|
import org.hibernate.sql.ast.tree.expression.Every;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
|
@ -215,6 +216,11 @@ public class ExpressionReplacementWalker implements SqlAstWalker {
|
||||||
doReplaceExpression( expression );
|
doReplaceExpression( expression );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitEmbeddableTypeLiteral(EmbeddableTypeLiteral expression) {
|
||||||
|
doReplaceExpression( expression );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitTuple(SqlTuple tuple) {
|
public void visitTuple(SqlTuple tuple) {
|
||||||
doReplaceExpression( tuple );
|
doReplaceExpression( tuple );
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
/*
|
||||||
|
* 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.sql.ast.tree.expression;
|
||||||
|
|
||||||
|
import org.hibernate.cache.MutableCacheKeyBuilder;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.internal.util.IndexedConsumer;
|
||||||
|
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.MappingModelExpressible;
|
||||||
|
import org.hibernate.metamodel.mapping.MappingType;
|
||||||
|
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||||
|
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||||
|
import org.hibernate.sql.ast.SqlAstWalker;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
|
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||||
|
import org.hibernate.type.BasicType;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class EmbeddableTypeLiteral
|
||||||
|
implements Expression, DomainResultProducer<Object>, BasicValuedMapping {
|
||||||
|
private final Class<?> embeddableClass;
|
||||||
|
private final BasicType<?> basicType;
|
||||||
|
|
||||||
|
public EmbeddableTypeLiteral(
|
||||||
|
EmbeddableDomainType<?> embeddableDomainType,
|
||||||
|
BasicType<?> basicType) {
|
||||||
|
this.embeddableClass = embeddableDomainType.getJavaType();
|
||||||
|
this.basicType = basicType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getEmbeddableClass() {
|
||||||
|
return embeddableClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// BasicValuedMapping
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MappingModelExpressible<?> getExpressionType() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JdbcMapping getJdbcMapping() {
|
||||||
|
return basicType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MappingType getMappedType() {
|
||||||
|
return basicType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getJdbcTypeCount() {
|
||||||
|
return basicType.getJdbcTypeCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JdbcMapping getJdbcMapping(int index) {
|
||||||
|
return basicType.getJdbcMapping( index );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JdbcMapping getSingleJdbcMapping() {
|
||||||
|
return basicType.getSingleJdbcMapping();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action) {
|
||||||
|
return basicType.forEachJdbcType( offset, action );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object disassemble(Object value, SharedSessionContractImplementor session) {
|
||||||
|
return basicType.disassemble( value, session );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addToCacheKey(MutableCacheKeyBuilder cacheKey, Object value, SharedSessionContractImplementor session) {
|
||||||
|
basicType.addToCacheKey( cacheKey, value, session );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <X, Y> int forEachDisassembledJdbcValue(
|
||||||
|
Object value,
|
||||||
|
int offset,
|
||||||
|
X x,
|
||||||
|
Y y,
|
||||||
|
JdbcValuesBiConsumer<X, Y> valuesConsumer,
|
||||||
|
SharedSessionContractImplementor session) {
|
||||||
|
return basicType.forEachDisassembledJdbcValue( value, offset, x, y, valuesConsumer, session );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <X, Y> int forEachJdbcValue(
|
||||||
|
Object value,
|
||||||
|
int offset,
|
||||||
|
X x,
|
||||||
|
Y y,
|
||||||
|
JdbcValuesBiConsumer<X, Y> valuesConsumer,
|
||||||
|
SharedSessionContractImplementor session) {
|
||||||
|
return basicType.forEachJdbcValue( value, offset, x, y, valuesConsumer, session );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// DomainResultProducer
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applySqlSelections(DomainResultCreationState creationState) {
|
||||||
|
createSqlSelection( creationState );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainResult<Object> createDomainResult(String resultVariable, DomainResultCreationState creationState) {
|
||||||
|
return new BasicResult<>(
|
||||||
|
createSqlSelection( creationState ).getValuesArrayPosition(),
|
||||||
|
resultVariable,
|
||||||
|
basicType
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqlSelection createSqlSelection(DomainResultCreationState creationState) {
|
||||||
|
return creationState.getSqlAstCreationState().getSqlExpressionResolver().resolveSqlSelection(
|
||||||
|
this,
|
||||||
|
basicType.getJdbcJavaType(),
|
||||||
|
null,
|
||||||
|
creationState.getSqlAstCreationState().getCreationContext().getMappingMetamodel().getTypeConfiguration()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(SqlAstWalker sqlTreeWalker) {
|
||||||
|
sqlTreeWalker.visitEmbeddableTypeLiteral( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JavaType getExpressibleJavaType() {
|
||||||
|
return basicType.getExpressibleJavaType();
|
||||||
|
}
|
||||||
|
}
|
|
@ -800,8 +800,8 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
|
||||||
final EmbeddableRepresentationStrategy representationStrategy = embeddableTypeDescriptor().getRepresentationStrategy();
|
final EmbeddableRepresentationStrategy representationStrategy = embeddableTypeDescriptor().getRepresentationStrategy();
|
||||||
final EmbeddableInstantiator instantiator;
|
final EmbeddableInstantiator instantiator;
|
||||||
if ( embeddableTypeDescriptor().isPolymorphic() ) {
|
if ( embeddableTypeDescriptor().isPolymorphic() ) {
|
||||||
// the discriminator here is the composite class name because it gets converted to the domain type when extracted
|
// the discriminator here is the composite class because it gets converted to the domain type when extracted
|
||||||
instantiator = representationStrategy.getInstantiatorForClass( (String) value[value.length - 1] );
|
instantiator = representationStrategy.getInstantiatorForClass( ( (Class<?>) value[value.length - 1] ).getName() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
instantiator = representationStrategy.getInstantiator();
|
instantiator = representationStrategy.getInstantiator();
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.inheritance.embeddable;
|
package org.hibernate.orm.test.inheritance.embeddable;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.Imported;
|
||||||
|
|
||||||
import jakarta.persistence.DiscriminatorValue;
|
import jakarta.persistence.DiscriminatorValue;
|
||||||
import jakarta.persistence.Embeddable;
|
import jakarta.persistence.Embeddable;
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.inheritance.embeddable;
|
package org.hibernate.orm.test.inheritance.embeddable;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.Imported;
|
||||||
|
|
||||||
import jakarta.persistence.Embeddable;
|
import jakarta.persistence.Embeddable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -106,6 +106,46 @@ public class ElementCollectionEmbeddableInheritanceTest {
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testType(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select type(t.embeddables) from TestEntity t where id = 2",
|
||||||
|
Class.class
|
||||||
|
).getSingleResult() ).isEqualTo( SubChildOneEmbeddable.class );
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select t.id from TestEntity t where type(t.embeddables) = SubChildOneEmbeddable",
|
||||||
|
Long.class
|
||||||
|
).getSingleResult() ).isEqualTo( 2L );
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select type(e) from TestEntity t join t.embeddables e where id = 2",
|
||||||
|
Class.class
|
||||||
|
).getSingleResult() ).isEqualTo( SubChildOneEmbeddable.class );
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select t.id from TestEntity t join t.embeddables e where type(e) = SubChildOneEmbeddable",
|
||||||
|
Long.class
|
||||||
|
).getSingleResult() ).isEqualTo( 2L );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTreat(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select treat(e as SubChildOneEmbeddable) from TestEntity t join t.embeddables e",
|
||||||
|
SubChildOneEmbeddable.class
|
||||||
|
).getSingleResult().getSubChildOneProp() ).isEqualTo( 2.0 );
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select t.id from TestEntity t join t.embeddables e where treat(e as SubChildOneEmbeddable).subChildOneProp = 2.0",
|
||||||
|
Long.class
|
||||||
|
).getSingleResult() ).isEqualTo( 2L );
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select t.id from TestEntity t join treat(t.embeddables as SubChildOneEmbeddable) e where e.subChildOneProp = 2.0",
|
||||||
|
Long.class
|
||||||
|
).getSingleResult() ).isEqualTo( 2L );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public void setUp(SessionFactoryScope scope) {
|
public void setUp(SessionFactoryScope scope) {
|
||||||
scope.inTransaction( session -> {
|
scope.inTransaction( session -> {
|
||||||
|
|
|
@ -0,0 +1,219 @@
|
||||||
|
/*
|
||||||
|
* 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.orm.test.inheritance.embeddable;
|
||||||
|
|
||||||
|
import org.hibernate.testing.jdbc.SQLStatementInspector;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import jakarta.persistence.Embedded;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Marco Belladelli
|
||||||
|
*/
|
||||||
|
@DomainModel( annotatedClasses = {
|
||||||
|
EmbeddableTypeAndTreatTest.TestEntity.class,
|
||||||
|
SimpleEmbeddable.class,
|
||||||
|
ParentEmbeddable.class,
|
||||||
|
ChildOneEmbeddable.class,
|
||||||
|
SubChildOneEmbeddable.class,
|
||||||
|
ChildTwoEmbeddable.class,
|
||||||
|
} )
|
||||||
|
@SessionFactory( useCollectingStatementInspector = true )
|
||||||
|
public class EmbeddableTypeAndTreatTest {
|
||||||
|
@Test
|
||||||
|
public void testType(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select type(t.embeddable) from TestEntity t where t.id = 1",
|
||||||
|
Class.class
|
||||||
|
).getSingleResult() ).isEqualTo( ChildTwoEmbeddable.class );
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select type(e) from TestEntity t join t.embeddable e where t.id = 2",
|
||||||
|
Class.class
|
||||||
|
).getSingleResult() ).isEqualTo( SubChildOneEmbeddable.class );
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select t.id from TestEntity t where type(t.embeddable) = SubChildOneEmbeddable",
|
||||||
|
Long.class
|
||||||
|
).getSingleResult() ).isEqualTo( 2L );
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select t.id from TestEntity t join t.embeddable e where type(e) = ChildTwoEmbeddable",
|
||||||
|
Long.class
|
||||||
|
).getSingleResult() ).isEqualTo( 1L );
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select t.id from TestEntity t where type(t.embeddable) = SubChildOneEmbeddable or t.id = 1",
|
||||||
|
Long.class
|
||||||
|
).getResultList() ).hasSize( 2 );
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select t.id from TestEntity t where type(t.embeddable) = SubChildOneEmbeddable and type(t.embeddable) = ChildTwoEmbeddable",
|
||||||
|
Long.class
|
||||||
|
).getResultList() ).hasSize( 0 );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTreat(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select treat(t.embeddable as SubChildOneEmbeddable) from TestEntity t",
|
||||||
|
SubChildOneEmbeddable.class
|
||||||
|
).getSingleResult().getSubChildOneProp() ).isEqualTo( 2.0 );
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select treat(e as SubChildOneEmbeddable) from TestEntity t join t.embeddable e",
|
||||||
|
SubChildOneEmbeddable.class
|
||||||
|
).getSingleResult().getSubChildOneProp() ).isEqualTo( 2.0 );
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select e from TestEntity t join treat(t.embeddable as SubChildOneEmbeddable) e",
|
||||||
|
SubChildOneEmbeddable.class
|
||||||
|
).getSingleResult().getSubChildOneProp() ).isEqualTo( 2.0 );
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select t.id from TestEntity t where treat(t.embeddable as ChildTwoEmbeddable).childTwoProp = 1",
|
||||||
|
Long.class
|
||||||
|
).getSingleResult() ).isEqualTo( 1L );
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select t.id from TestEntity t join t.embeddable e where treat(e as ChildTwoEmbeddable).childTwoProp = 1",
|
||||||
|
Long.class
|
||||||
|
).getSingleResult() ).isEqualTo( 1L );
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select t.id from TestEntity t join treat(t.embeddable as ChildTwoEmbeddable) e where e.childTwoProp = 1",
|
||||||
|
Long.class
|
||||||
|
).getSingleResult() ).isEqualTo( 1L );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTreatJunctions(SessionFactoryScope scope) {
|
||||||
|
final SQLStatementInspector inspector = scope.getCollectingStatementInspector();
|
||||||
|
inspector.clear();
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select t.id from TestEntity t where treat(t.embeddable as SubChildOneEmbeddable).subChildOneProp = 2.0 and id = 2",
|
||||||
|
Long.class
|
||||||
|
).getSingleResult() ).isEqualTo( 2L );
|
||||||
|
inspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "embeddable_type", 1 );
|
||||||
|
inspector.clear();
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select t.id from TestEntity t where treat(t.embeddable as SubChildOneEmbeddable).subChildOneProp = 2.0 or id = 1",
|
||||||
|
Long.class
|
||||||
|
).getResultList() ).hasSize( 2 );
|
||||||
|
inspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "embeddable_type", 1 );
|
||||||
|
inspector.clear();
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select t.id from TestEntity t where treat(t.embeddable as SubChildOneEmbeddable).subChildOneProp = 2.0 and treat(t.embeddable as SubChildOneEmbeddable).childOneProp = 2",
|
||||||
|
Long.class
|
||||||
|
).getSingleResult() ).isEqualTo( 2L );
|
||||||
|
inspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "embeddable_type", 1 );
|
||||||
|
inspector.clear();
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select t.id from TestEntity t where treat(t.embeddable as SubChildOneEmbeddable).subChildOneProp = 2.0 and id = 1",
|
||||||
|
Long.class
|
||||||
|
).getResultList() ).hasSize( 0 );
|
||||||
|
inspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "embeddable_type", 1 );
|
||||||
|
inspector.clear();
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select t.id from TestEntity t where id = 1 or treat(t.embeddable as SubChildOneEmbeddable).subChildOneProp = 2.0",
|
||||||
|
Long.class
|
||||||
|
).getResultList() ).hasSize( 2 );
|
||||||
|
inspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "embeddable_type", 1 );
|
||||||
|
inspector.clear();
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select t.id from TestEntity t where treat(t.embeddable as ChildTwoEmbeddable).childTwoProp = 1 or treat(t.embeddable as SubChildOneEmbeddable).subChildOneProp = 2.0",
|
||||||
|
Long.class
|
||||||
|
).getResultList() ).hasSize( 2 );
|
||||||
|
inspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "embeddable_type", 2 );
|
||||||
|
inspector.clear();
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select t.id from TestEntity t where treat(t.embeddable as SubChildOneEmbeddable).childOneProp = 2 or treat(t.embeddable as SubChildOneEmbeddable).subChildOneProp = 2.0",
|
||||||
|
Long.class
|
||||||
|
).getSingleResult() ).isEqualTo( 2L );
|
||||||
|
inspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "embeddable_type", 1 );
|
||||||
|
inspector.clear();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNonInheritedEmbeddable(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select type(t.simpleEmbeddable) from TestEntity t where t.id = 1",
|
||||||
|
Class.class
|
||||||
|
).getSingleResult() ).isEqualTo( SimpleEmbeddable.class );
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select t.id from TestEntity t where type(t.simpleEmbeddable) = SimpleEmbeddable",
|
||||||
|
Long.class
|
||||||
|
).getResultList() ).hasSize( 3 );
|
||||||
|
assertThat( session.createQuery(
|
||||||
|
"select treat(t.simpleEmbeddable as SimpleEmbeddable) from TestEntity t where t.simpleEmbeddable is not null",
|
||||||
|
SimpleEmbeddable.class
|
||||||
|
).getSingleResult().getData() ).isEqualTo( "simple_embeddable_1" );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
public void setUp(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
final TestEntity testEntity = new TestEntity( 1L, new ChildTwoEmbeddable( "embeddable_1", 1L ) );
|
||||||
|
testEntity.setSimpleEmbeddable( new SimpleEmbeddable( "simple_embeddable_1" ) );
|
||||||
|
session.persist( testEntity );
|
||||||
|
session.persist( new TestEntity( 2L, new SubChildOneEmbeddable( "embeddable_2", 2, 2.0 ) ) );
|
||||||
|
session.persist( new TestEntity( 3L, new ChildOneEmbeddable( "embeddable_3", 3 ) ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public void tearDown(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction( session -> session.createMutationQuery( "delete from TestEntity" ).executeUpdate() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "TestEntity" )
|
||||||
|
static class TestEntity {
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
private ParentEmbeddable embeddable;
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
private SimpleEmbeddable simpleEmbeddable;
|
||||||
|
|
||||||
|
public TestEntity() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestEntity(Long id, ParentEmbeddable embeddable) {
|
||||||
|
this.id = id;
|
||||||
|
this.embeddable = embeddable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParentEmbeddable getEmbeddable() {
|
||||||
|
return embeddable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmbeddable(ParentEmbeddable embeddable) {
|
||||||
|
this.embeddable = embeddable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleEmbeddable getSimpleEmbeddable() {
|
||||||
|
return simpleEmbeddable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSimpleEmbeddable(SimpleEmbeddable simpleEmbeddable) {
|
||||||
|
this.simpleEmbeddable = simpleEmbeddable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* 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.orm.test.inheritance.embeddable;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.Imported;
|
||||||
|
|
||||||
|
import jakarta.persistence.Embeddable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Marco Belladelli
|
||||||
|
*/
|
||||||
|
@Embeddable
|
||||||
|
public class SimpleEmbeddable {
|
||||||
|
private String data;
|
||||||
|
|
||||||
|
public SimpleEmbeddable() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleEmbeddable(String data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,8 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.inheritance.embeddable;
|
package org.hibernate.orm.test.inheritance.embeddable;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.Imported;
|
||||||
|
|
||||||
import jakarta.persistence.DiscriminatorValue;
|
import jakarta.persistence.DiscriminatorValue;
|
||||||
import jakarta.persistence.Embeddable;
|
import jakarta.persistence.Embeddable;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ public class MetadataCopyingTest {
|
||||||
existingInstance.getEntityBindingMap(),
|
existingInstance.getEntityBindingMap(),
|
||||||
existingInstance.getComposites(),
|
existingInstance.getComposites(),
|
||||||
existingInstance.getGenericComponentsMap(),
|
existingInstance.getGenericComponentsMap(),
|
||||||
|
existingInstance.getEmbeddableDiscriminatorTypesMap(),
|
||||||
existingInstance.getMappedSuperclassMap(),
|
existingInstance.getMappedSuperclassMap(),
|
||||||
existingInstance.getCollectionBindingMap(),
|
existingInstance.getCollectionBindingMap(),
|
||||||
existingInstance.getTypeDefinitionMap(),
|
existingInstance.getTypeDefinitionMap(),
|
||||||
|
|
|
@ -57,7 +57,6 @@ Support for `array_contains()` to accept an array as element argument is depreca
|
||||||
To check if an array is a subset of another array, use the `array_includes()` function,
|
To check if an array is a subset of another array, use the `array_includes()` function,
|
||||||
or the new `INCLUDES` predicate i.e. `array INCLUDES subarray`.
|
or the new `INCLUDES` predicate i.e. `array INCLUDES subarray`.
|
||||||
|
|
||||||
|
|
||||||
[[merge-versioned-deleted]]
|
[[merge-versioned-deleted]]
|
||||||
=== Merge versioned entity when row is deleted
|
=== Merge versioned entity when row is deleted
|
||||||
Previously, merging a detached entity resulted in a SQL `insert` whenever there was no matching row in the database (for example, if the object had been deleted in another transaction).
|
Previously, merging a detached entity resulted in a SQL `insert` whenever there was no matching row in the database (for example, if the object had been deleted in another transaction).
|
||||||
|
@ -70,3 +69,11 @@ For this determination to be possible, the entity must have either:
|
||||||
- a non-primitive `@Version` field.
|
- a non-primitive `@Version` field.
|
||||||
|
|
||||||
For entities which have neither, it's impossible to distinguish a new instance from a deleted detached instance, and there is no change from the previous behavior.
|
For entities which have neither, it's impossible to distinguish a new instance from a deleted detached instance, and there is no change from the previous behavior.
|
||||||
|
|
||||||
|
[[embeddable-treated-paths]]
|
||||||
|
== Changes to the `SqmTreatedPath` interface
|
||||||
|
|
||||||
|
ORM 6.6 introduced support for `@Embeddable` type inheritance.
|
||||||
|
With it, we also enabled the `type()` and `treat()` functions to work with embeddable-typed paths.
|
||||||
|
As a consequence, the `SqmTreatedPath#getTreatTarget()` method will now return a generic `ManagedDomainType` object,
|
||||||
|
which could in turn be an `EntityDomainType` (as it was before) or also an `EmbeddableDomainType` instance.
|
|
@ -58,6 +58,7 @@ import org.hibernate.metamodel.internal.MetadataContext;
|
||||||
import org.hibernate.metamodel.internal.RuntimeMetamodelsImpl;
|
import org.hibernate.metamodel.internal.RuntimeMetamodelsImpl;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
import org.hibernate.metamodel.model.domain.DomainType;
|
import org.hibernate.metamodel.model.domain.DomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
||||||
|
@ -201,6 +202,7 @@ public abstract class MockSessionFactory
|
||||||
emptyMap(),
|
emptyMap(),
|
||||||
emptyMap(),
|
emptyMap(),
|
||||||
emptyMap(),
|
emptyMap(),
|
||||||
|
emptyMap(),
|
||||||
new Database(this, MockJdbcServicesInitiator.jdbcServices.getJdbcEnvironment()),
|
new Database(this, MockJdbcServicesInitiator.jdbcServices.getJdbcEnvironment()),
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue