parent
055ce0c542
commit
5631a702a7
|
@ -14,12 +14,14 @@ import java.io.Serializable;
|
|||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
@ -41,6 +43,7 @@ import org.hibernate.internal.CoreLogging;
|
|||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.type.SerializationException;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
/**
|
||||
|
@ -64,6 +67,8 @@ public class MetadataSources implements Serializable {
|
|||
private LinkedHashSet<String> annotatedClassNames = new LinkedHashSet<>();
|
||||
private LinkedHashSet<String> annotatedPackages = new LinkedHashSet<>();
|
||||
|
||||
private Map<String,Class<?>> extraQueryImports;
|
||||
|
||||
public MetadataSources() {
|
||||
this( new BootstrapServiceRegistryBuilder().build() );
|
||||
}
|
||||
|
@ -111,6 +116,10 @@ public class MetadataSources implements Serializable {
|
|||
return annotatedClassNames;
|
||||
}
|
||||
|
||||
public Map<String,Class<?>> getExtraQueryImports() {
|
||||
return extraQueryImports;
|
||||
}
|
||||
|
||||
public ServiceRegistry getServiceRegistry() {
|
||||
return serviceRegistry;
|
||||
}
|
||||
|
@ -196,6 +205,16 @@ public class MetadataSources implements Serializable {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Var-arg form of {@link #addAnnotatedClass}
|
||||
*/
|
||||
public MetadataSources addAnnotatedClasses(Class<?>... annotatedClasses) {
|
||||
if ( annotatedClasses != null && annotatedClasses.length > 0 ) {
|
||||
Collections.addAll( this.annotatedClasses, annotatedClasses );
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read metadata from the annotations attached to the given class. The important
|
||||
* distinction here is that the {@link Class} will not be accessed until later
|
||||
|
@ -210,6 +229,26 @@ public class MetadataSources implements Serializable {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Var-arg form of {@link #addAnnotatedClassName}
|
||||
*/
|
||||
public MetadataSources addAnnotatedClassNames(String... annotatedClassNames) {
|
||||
if ( annotatedClassNames != null && annotatedClassNames.length > 0 ) {
|
||||
Collections.addAll( this.annotatedClassNames, annotatedClassNames );
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public MetadataSources addQueryImport(String importedName, Class<?> target) {
|
||||
if ( extraQueryImports == null ) {
|
||||
extraQueryImports = new HashMap<>();
|
||||
}
|
||||
|
||||
extraQueryImports.put( importedName, target );
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read package-level metadata.
|
||||
*
|
||||
|
|
|
@ -30,6 +30,7 @@ public class ManagedResourcesImpl implements ManagedResources {
|
|||
private Set<String> annotatedClassNames = new LinkedHashSet<>();
|
||||
private Set<String> annotatedPackageNames = new LinkedHashSet<>();
|
||||
private List<Binding> mappingFileBindings = new ArrayList<>();
|
||||
private Map<String, Class<?>> extraQueryImports;
|
||||
|
||||
public static ManagedResourcesImpl baseline(MetadataSources sources, BootstrapContext bootstrapContext) {
|
||||
final ManagedResourcesImpl impl = new ManagedResourcesImpl();
|
||||
|
@ -38,6 +39,7 @@ public class ManagedResourcesImpl implements ManagedResources {
|
|||
impl.annotatedClassNames.addAll( sources.getAnnotatedClassNames() );
|
||||
impl.annotatedPackageNames.addAll( sources.getAnnotatedPackages() );
|
||||
impl.mappingFileBindings.addAll( sources.getXmlBindings() );
|
||||
impl.extraQueryImports = sources.getExtraQueryImports();
|
||||
return impl;
|
||||
}
|
||||
|
||||
|
@ -69,6 +71,11 @@ public class ManagedResourcesImpl implements ManagedResources {
|
|||
return Collections.unmodifiableList( mappingFileBindings );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Class<?>> getExtraQueryImports() {
|
||||
return extraQueryImports;
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// package private
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
package org.hibernate.boot.model.process.spi;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.boot.AttributeConverterInfo;
|
||||
import org.hibernate.boot.jaxb.spi.Binding;
|
||||
|
@ -66,4 +68,6 @@ public interface ManagedResources {
|
|||
* @return The list of bindings for all known XML mapping files.
|
||||
*/
|
||||
Collection<Binding> getXmlMappingBindings();
|
||||
|
||||
Map<String,Class<?>> getExtraQueryImports();
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.boot.model.process.spi;
|
|||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
|
@ -304,9 +305,24 @@ public class MetadataBuildingProcess {
|
|||
}
|
||||
}
|
||||
|
||||
applyExtraQueryImports( managedResources, metadataCollector );
|
||||
|
||||
return metadataCollector.buildMetadataInstance( rootMetadataBuildingContext );
|
||||
}
|
||||
|
||||
private static void applyExtraQueryImports(
|
||||
ManagedResources managedResources,
|
||||
InFlightMetadataCollectorImpl metadataCollector) {
|
||||
final Map<String, Class<?>> extraQueryImports = managedResources.getExtraQueryImports();
|
||||
if ( extraQueryImports == null || extraQueryImports.isEmpty() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
for ( Map.Entry<String, Class<?>> entry : extraQueryImports.entrySet() ) {
|
||||
metadataCollector.addImport( entry.getKey(), entry.getValue().getName() );
|
||||
}
|
||||
}
|
||||
|
||||
// todo (7.0) : buildJandexInitializer
|
||||
// private static JandexInitManager buildJandexInitializer(
|
||||
// MetadataBuildingOptions options,
|
||||
|
|
|
@ -81,6 +81,8 @@ public interface JpaMetamodel extends javax.persistence.metamodel.Metamodel {
|
|||
|
||||
void visitEmbeddables(Consumer<EmbeddableDomainType<?>> action);
|
||||
|
||||
String qualifyImportableName(String queryName);
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Covariant returns
|
||||
|
|
|
@ -269,6 +269,11 @@ public class JpaMetamodelImpl implements JpaMetamodel {
|
|||
return results;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String qualifyImportableName(String queryName) {
|
||||
return resolveImportedName( queryName );
|
||||
}
|
||||
|
||||
private String resolveImportedName(String name) {
|
||||
String result = nameToImportNameMap.get( name );
|
||||
if ( result == null ) {
|
||||
|
|
|
@ -238,9 +238,4 @@ public class FullyQualifiedReflectivePathTerminal
|
|||
public NodeBuilder nodeBuilder() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpressable getExpressableType() {
|
||||
return expressableType;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -570,11 +570,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
else {
|
||||
final String className = ctx.dynamicInstantiationTarget().dotIdentifierSequence().getText();
|
||||
try {
|
||||
final Class<?> targetJavaType = classForName( className );
|
||||
final JavaTypeDescriptor jtd = creationContext.getJpaMetamodel()
|
||||
.getTypeConfiguration()
|
||||
.getJavaTypeDescriptorRegistry()
|
||||
.resolveDescriptor( targetJavaType );
|
||||
final JavaTypeDescriptor jtd = resolveInstantiationTargetJtd( className );
|
||||
dynamicInstantiation = SqmDynamicInstantiation.forClassInstantiation(
|
||||
jtd,
|
||||
creationContext.getNodeBuilder()
|
||||
|
@ -592,6 +588,14 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
return dynamicInstantiation;
|
||||
}
|
||||
|
||||
private JavaTypeDescriptor resolveInstantiationTargetJtd(String className) {
|
||||
final Class<?> targetJavaType = classForName( creationContext.getJpaMetamodel().qualifyImportableName( className ) );
|
||||
return creationContext.getJpaMetamodel()
|
||||
.getTypeConfiguration()
|
||||
.getJavaTypeDescriptorRegistry()
|
||||
.resolveDescriptor( targetJavaType );
|
||||
}
|
||||
|
||||
private Class classForName(String className) {
|
||||
return creationContext.getServiceRegistry().getService( ClassLoaderService.class ).classForName( className );
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import org.hibernate.NotYetImplementedFor6Exception;
|
|||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.internal.util.collections.Stack;
|
||||
import org.hibernate.internal.util.collections.StandardStack;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
|
@ -35,12 +35,12 @@ import org.hibernate.query.sqm.SqmExpressable;
|
|||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.function.SqmFunction;
|
||||
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||
import org.hibernate.query.sqm.internal.SqmMappingModelHelper;
|
||||
import org.hibernate.query.sqm.spi.BaseSemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.spi.JdbcParameterBySqmParameterAccess;
|
||||
import org.hibernate.query.sqm.sql.internal.BasicValuedPathInterpretation;
|
||||
import org.hibernate.query.sqm.sql.internal.EmbeddableValuedPathInterpretation;
|
||||
import org.hibernate.query.sqm.sql.internal.SqlAstQuerySpecProcessingStateImpl;
|
||||
import org.hibernate.query.sqm.sql.internal.SqmExpressionInterpretation;
|
||||
import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation;
|
||||
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
|
||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||
|
@ -614,8 +614,12 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
// General expressions
|
||||
|
||||
@Override
|
||||
public SqmExpressionInterpretation visitLiteral(SqmLiteral literal) {
|
||||
return literal;
|
||||
public Expression visitLiteral(SqmLiteral literal) {
|
||||
return new QueryLiteral(
|
||||
literal.getLiteralValue(),
|
||||
(BasicValuedMapping) SqmMappingModelHelper.resolveMappingModelExpressable( literal, this ),
|
||||
getCurrentClauseStack().getCurrent()
|
||||
);
|
||||
}
|
||||
|
||||
private final Map<SqmParameter,List<JdbcParameter>> jdbcParamsBySqmParam = new IdentityHashMap<>();
|
||||
|
@ -627,12 +631,12 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmExpressionInterpretation visitNamedParameterExpression(SqmNamedParameter expression) {
|
||||
public Expression visitNamedParameterExpression(SqmNamedParameter expression) {
|
||||
return consumeSqmParameter( expression );
|
||||
}
|
||||
|
||||
|
||||
private SqmExpressionInterpretation consumeSqmParameter(SqmParameter sqmParameter) {
|
||||
private Expression consumeSqmParameter(SqmParameter sqmParameter) {
|
||||
final MappingModelExpressable valueMapping = determineValueMapping( sqmParameter );
|
||||
final List<JdbcParameter> jdbcParametersForSqm = new ArrayList<>();
|
||||
|
||||
|
@ -1242,7 +1246,7 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
public Object visitEnumLiteral(SqmEnumLiteral sqmEnumLiteral) {
|
||||
return new QueryLiteral(
|
||||
sqmEnumLiteral.getEnumValue(),
|
||||
determineValueMapping( sqmEnumLiteral ),
|
||||
(BasicValuedMapping) determineValueMapping( sqmEnumLiteral ),
|
||||
getCurrentClauseStack().getCurrent()
|
||||
);
|
||||
}
|
||||
|
@ -1251,7 +1255,7 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
public Object visitFieldLiteral(SqmFieldLiteral sqmFieldLiteral) {
|
||||
return new QueryLiteral(
|
||||
sqmFieldLiteral.getValue(),
|
||||
determineValueMapping( sqmFieldLiteral ),
|
||||
(BasicValuedMapping) determineValueMapping( sqmFieldLiteral ),
|
||||
getCurrentClauseStack().getCurrent()
|
||||
);
|
||||
}
|
||||
|
@ -1322,11 +1326,7 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
|
||||
final Expression lhs;
|
||||
try {
|
||||
lhs = ( (SqmExpressionInterpretation) predicate.getLeftHandExpression().accept( this ) ).toSqlExpression(
|
||||
getCurrentClauseStack().getCurrent(),
|
||||
this,
|
||||
this
|
||||
);
|
||||
lhs = (Expression) predicate.getLeftHandExpression().accept( this );
|
||||
}
|
||||
finally {
|
||||
inferableTypeAccessStack.pop();
|
||||
|
@ -1336,11 +1336,7 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
|
||||
final Expression rhs;
|
||||
try {
|
||||
rhs = ( (SqmExpressionInterpretation) predicate.getRightHandExpression().accept( this ) ).toSqlExpression(
|
||||
getCurrentClauseStack().getCurrent(),
|
||||
this,
|
||||
this
|
||||
);
|
||||
rhs = (Expression) predicate.getRightHandExpression().accept( this );
|
||||
}
|
||||
finally {
|
||||
inferableTypeAccessStack.pop();
|
||||
|
@ -1472,13 +1468,7 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
domainParameterXref.addExpansion( domainParam, sqmParameter, sqmParamToConsume );
|
||||
}
|
||||
|
||||
inListPredicate.addExpression(
|
||||
consumeSqmParameter( sqmParamToConsume ).toSqlExpression(
|
||||
getCurrentClauseStack().getCurrent(),
|
||||
this,
|
||||
this
|
||||
)
|
||||
);
|
||||
inListPredicate.addExpression( consumeSqmParameter( sqmParamToConsume ) );
|
||||
}
|
||||
}
|
||||
finally {
|
||||
|
|
|
@ -6,8 +6,10 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.sql;
|
||||
|
||||
import org.hibernate.internal.util.collections.Stack;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
|
||||
/**
|
||||
* Specialized SemanticQueryWalker (SQM visitor) for producing SQL AST.
|
||||
|
@ -15,4 +17,5 @@ import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmToSqlAstConverter extends SemanticQueryWalker<Object>, SqlAstCreationState {
|
||||
Stack<Clause> getCurrentClauseStack();
|
||||
}
|
||||
|
|
|
@ -10,15 +10,16 @@ import java.util.function.Consumer;
|
|||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.internal.SqmMappingModelHelper;
|
||||
import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
import org.hibernate.sql.ast.spi.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.update.Assignment;
|
||||
|
@ -44,45 +45,63 @@ public class BasicValuedPathInterpretation<T> implements AssignableSqmPathInterp
|
|||
null
|
||||
);
|
||||
|
||||
return new BasicValuedPathInterpretation<>( sqmPath, mapping, tableGroup );
|
||||
final ColumnReference columnReference = (ColumnReference) sqlAstCreationState.getSqlExpressionResolver().resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey(
|
||||
mapping.getContainingTableExpression(),
|
||||
mapping.getMappedColumnExpression()
|
||||
),
|
||||
sacs -> new ColumnReference(
|
||||
mapping.getMappedColumnExpression(),
|
||||
tableGroup.resolveTableReference( mapping.getContainingTableExpression() )
|
||||
.getIdentificationVariable(),
|
||||
mapping.getJdbcMapping(),
|
||||
sqlAstCreationState.getCreationContext().getSessionFactory()
|
||||
)
|
||||
);
|
||||
|
||||
return new BasicValuedPathInterpretation<>( columnReference, sqmPath, mapping, tableGroup );
|
||||
}
|
||||
|
||||
private final ColumnReference columnReference;
|
||||
|
||||
private final SqmBasicValuedSimplePath<T> sqmPath;
|
||||
private final BasicValuedModelPart mapping;
|
||||
private final TableGroup tableGroup;
|
||||
|
||||
private Expression expression;
|
||||
|
||||
private BasicValuedPathInterpretation(
|
||||
ColumnReference columnReference,
|
||||
SqmBasicValuedSimplePath<T> sqmPath,
|
||||
BasicValuedModelPart mapping,
|
||||
TableGroup tableGroup) {
|
||||
assert columnReference != null;
|
||||
this.columnReference = columnReference;
|
||||
|
||||
assert sqmPath != null;
|
||||
this.sqmPath = sqmPath;
|
||||
|
||||
assert mapping != null;
|
||||
this.mapping = mapping;
|
||||
|
||||
assert tableGroup != null;
|
||||
this.tableGroup = tableGroup;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigablePath getNavigablePath() {
|
||||
return sqmPath.getNavigablePath();
|
||||
public SqmPath<T> getInterpretedSqmPath() {
|
||||
return sqmPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource<T> getSqmPathSource() {
|
||||
return sqmPath.getReferencedPathSource();
|
||||
public ModelPart getExpressionType() {
|
||||
return mapping;
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// DomainResultProducer
|
||||
|
||||
@Override
|
||||
public DomainResultProducer<T> getDomainResultProducer(
|
||||
SqmToSqlAstConverter walker,
|
||||
SqlAstCreationState sqlAstCreationState) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult<T> createDomainResult(
|
||||
String resultVariable,
|
||||
|
@ -95,17 +114,6 @@ public class BasicValuedPathInterpretation<T> implements AssignableSqmPathInterp
|
|||
mapping.applySqlSelections( getNavigablePath(), tableGroup, creationState );
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// SqmExpressionInterpretation
|
||||
|
||||
@Override
|
||||
public Expression toSqlExpression(
|
||||
Clause clause, SqmToSqlAstConverter walker,
|
||||
SqlAstCreationState sqlAstCreationState) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySqlAssignments(
|
||||
Expression newValueExpression,
|
||||
|
@ -115,6 +123,11 @@ public class BasicValuedPathInterpretation<T> implements AssignableSqmPathInterp
|
|||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(SqlAstWalker sqlTreeWalker) {
|
||||
columnReference.accept( sqlTreeWalker );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BasicValuedPathInterpretation(" + sqmPath.getNavigablePath().getFullPath() + ')';
|
||||
|
|
|
@ -10,15 +10,15 @@ import java.util.function.Consumer;
|
|||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.internal.SqmMappingModelHelper;
|
||||
import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
import org.hibernate.sql.ast.spi.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.update.Assignment;
|
||||
|
@ -28,59 +28,67 @@ import org.hibernate.sql.results.spi.DomainResultCreationState;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EmbeddableValuedPathInterpretation<T> implements AssignableSqmPathInterpretation<T>, DomainResultProducer<T> {
|
||||
public class EmbeddableValuedPathInterpretation<T> implements AssignableSqmPathInterpretation<T> {
|
||||
|
||||
/**
|
||||
* Static factory
|
||||
*/
|
||||
public static <T> EmbeddableValuedPathInterpretation<T> from(
|
||||
SqmEmbeddedValuedSimplePath<T> sqmPath,
|
||||
SqlAstCreationState sqlAstCreationState,
|
||||
SqmToSqlAstConverter converter,
|
||||
SemanticQueryWalker sqmWalker) {
|
||||
final TableGroup tableGroup = SqmMappingModelHelper.resolveLhs( sqmPath.getNavigablePath(), sqlAstCreationState );
|
||||
tableGroup.getModelPart().prepareAsLhs( sqmPath.getNavigablePath(), sqlAstCreationState );
|
||||
final TableGroup tableGroup = SqmMappingModelHelper.resolveLhs( sqmPath.getNavigablePath(), converter );
|
||||
tableGroup.getModelPart().prepareAsLhs( sqmPath.getNavigablePath(), converter );
|
||||
|
||||
final EmbeddableValuedModelPart mapping = (EmbeddableValuedModelPart) tableGroup.getModelPart().findSubPart(
|
||||
sqmPath.getReferencedPathSource().getPathName(),
|
||||
null
|
||||
);
|
||||
|
||||
return new EmbeddableValuedPathInterpretation<>( sqmPath, mapping, tableGroup );
|
||||
return new EmbeddableValuedPathInterpretation<>(
|
||||
mapping.toSqlExpression(
|
||||
tableGroup,
|
||||
converter.getCurrentClauseStack().getCurrent(),
|
||||
converter,
|
||||
converter
|
||||
),
|
||||
sqmPath,
|
||||
mapping,
|
||||
tableGroup
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private final Expression sqlExpression;
|
||||
|
||||
private final SqmEmbeddedValuedSimplePath<T> sqmPath;
|
||||
private final EmbeddableValuedModelPart mapping;
|
||||
private final TableGroup tableGroup;
|
||||
|
||||
public EmbeddableValuedPathInterpretation(
|
||||
Expression sqlExpression,
|
||||
SqmEmbeddedValuedSimplePath<T> sqmPath,
|
||||
EmbeddableValuedModelPart mapping,
|
||||
TableGroup tableGroup) {
|
||||
this.sqlExpression = sqlExpression;
|
||||
this.sqmPath = sqmPath;
|
||||
this.mapping = mapping;
|
||||
this.tableGroup = tableGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigablePath getNavigablePath() {
|
||||
return sqmPath.getNavigablePath();
|
||||
public SqmPath<T> getInterpretedSqmPath() {
|
||||
return sqmPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource<T> getSqmPathSource() {
|
||||
return sqmPath.getReferencedPathSource();
|
||||
public ModelPart getExpressionType() {
|
||||
return mapping;
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// DomainResultProducer
|
||||
|
||||
@Override
|
||||
public DomainResultProducer<T> getDomainResultProducer(
|
||||
SqmToSqlAstConverter walker,
|
||||
SqlAstCreationState sqlAstCreationState) {
|
||||
return this;
|
||||
public void accept(SqlAstWalker sqlTreeWalker) {
|
||||
sqlExpression.accept( sqlTreeWalker );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -93,18 +101,6 @@ public class EmbeddableValuedPathInterpretation<T> implements AssignableSqmPathI
|
|||
mapping.applySqlSelections( getNavigablePath(), tableGroup, creationState );
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// SqmPathInterpretation
|
||||
|
||||
@Override
|
||||
public Expression toSqlExpression(
|
||||
Clause clause,
|
||||
SqmToSqlAstConverter walker,
|
||||
SqlAstCreationState sqlAstCreationState) {
|
||||
return mapping.toSqlExpression( tableGroup, clause, walker, sqlAstCreationState );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySqlAssignments(
|
||||
Expression newValueExpression,
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* 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.sql.internal;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
|
||||
/**
|
||||
* The interpretation of an SqmExpression as part of the SQM -> SQL conversion.
|
||||
*
|
||||
* Allows multi-column navigable references to be used anywhere a (SqlExpression)
|
||||
* can be. The trick is to properly define methods on this interface for how the
|
||||
* thing should be rendered into the SQL AST.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmExpressionInterpretation<T> extends SqmSelectableInterpretation<T> {
|
||||
SqmExpressable<T> getExpressableType();
|
||||
|
||||
default Expression toSqlExpression(
|
||||
Clause clause,
|
||||
SqmToSqlAstConverter walker,
|
||||
SqlAstCreationState sqlAstCreationState) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
}
|
|
@ -9,13 +9,8 @@ package org.hibernate.query.sqm.sql.internal;
|
|||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.metamodel.model.domain.internal.DomainModelHelper;
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.spi.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.exec.spi.JdbcParameter;
|
||||
|
@ -23,44 +18,34 @@ import org.hibernate.sql.exec.spi.JdbcParameter;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmParameterInterpretation implements SqmExpressionInterpretation {
|
||||
public class SqmParameterInterpretation implements Expression {
|
||||
private final SqmParameter sqmParameter;
|
||||
private final List<JdbcParameter> jdbcParameters;
|
||||
private final MappingModelExpressable valueMapping;
|
||||
|
||||
private final Expression resolvedExpression;
|
||||
|
||||
public SqmParameterInterpretation(
|
||||
SqmParameter sqmParameter,
|
||||
List<JdbcParameter> jdbcParameters,
|
||||
MappingModelExpressable valueMapping) {
|
||||
this.sqmParameter = sqmParameter;
|
||||
this.valueMapping = valueMapping;
|
||||
|
||||
assert jdbcParameters != null;
|
||||
assert jdbcParameters.size() > 0;
|
||||
|
||||
this.sqmParameter = sqmParameter;
|
||||
this.jdbcParameters = jdbcParameters;
|
||||
this.resolvedExpression = jdbcParameters.size() == 1
|
||||
? jdbcParameters.get( 0 )
|
||||
: new SqlTuple( jdbcParameters, valueMapping );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpressable getExpressableType() {
|
||||
return sqmParameter.getExpressableType();
|
||||
public void accept(SqlAstWalker sqlTreeWalker) {
|
||||
resolvedExpression.accept( sqlTreeWalker );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression toSqlExpression(
|
||||
Clause clause,
|
||||
SqmToSqlAstConverter walker,
|
||||
SqlAstCreationState sqlAstCreationState) {
|
||||
if ( jdbcParameters.size() == 1 ) {
|
||||
return jdbcParameters.get( 0 );
|
||||
}
|
||||
|
||||
return new SqlTuple( jdbcParameters, valueMapping );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResultProducer getDomainResultProducer(
|
||||
SqmToSqlAstConverter walker,
|
||||
SqlAstCreationState sqlAstCreationState) {
|
||||
throw new SemanticException( "SqmParameter parameter cannot be a DomainResult" );
|
||||
public MappingModelExpressable getExpressionType() {
|
||||
return valueMapping;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,68 +6,26 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.sql.internal;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.metamodel.model.domain.internal.BasicSqmPathSource;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.sql.ConversionException;
|
||||
import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
|
||||
/**
|
||||
* todo (6.0) : consider having `SqmPathInterpretation` extend `org.hibernate.sql.ast.tree.expression.Expression`.
|
||||
* - Basic paths would logically resolve to a `ColumnReference`
|
||||
* - Composite and entity-valued paths would logically resolve to a `SqlTuple`
|
||||
* Interpretation of a {@link SqmPath} as part of the translation to SQL AST
|
||||
*
|
||||
* @see org.hibernate.query.sqm.sql.SqmToSqlAstConverter
|
||||
* @see #getInterpretedSqmPath
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmPathInterpretation<T> extends SqmExpressionInterpretation<T> {
|
||||
NavigablePath getNavigablePath();
|
||||
|
||||
@Override
|
||||
default SqmPathSource<T> getExpressableType() {
|
||||
return getSqmPathSource();
|
||||
public interface SqmPathInterpretation<T> extends Expression, DomainResultProducer<T> {
|
||||
default NavigablePath getNavigablePath() {
|
||||
return getInterpretedSqmPath().getNavigablePath();
|
||||
}
|
||||
|
||||
SqmPathSource<T> getSqmPathSource();
|
||||
SqmPath<T> getInterpretedSqmPath();
|
||||
|
||||
// @Override
|
||||
// default Expression toSqlExpression(SqlAstCreationState sqlAstCreationState) {
|
||||
// throw new NotYetImplementedFor6Exception( getClass() );
|
||||
// final TableGroup tableGroup;
|
||||
//
|
||||
// if ( getSqmPathSource() instanceof BasicSqmPathSource ) {
|
||||
// // maybe we should register the LHS TableGroup for the basic value
|
||||
// // under its NavigablePath, similar to what we do for embeddables
|
||||
// tableGroup = sqlAstCreationState.getFromClauseAccess().findTableGroup( getNavigablePath().getParent() );
|
||||
// }
|
||||
// else {
|
||||
// // for embeddable-, entity- and plural-valued Navigables we maybe do not have a TableGroup
|
||||
// final TableGroup thisTableGroup = sqlAstCreationState.getFromClauseAccess().findTableGroup( getNavigablePath() );
|
||||
// if ( thisTableGroup != null ) {
|
||||
// tableGroup = thisTableGroup;
|
||||
// }
|
||||
// else {
|
||||
// final NavigablePath lhsNavigablePath = getNavigablePath().getParent();
|
||||
// if ( lhsNavigablePath == null ) {
|
||||
// throw new ConversionException( "Could not find TableGroup to use - " + getNavigablePath().getFullPath() );
|
||||
// }
|
||||
// tableGroup = sqlAstCreationState.getFromClauseAccess().findTableGroup( lhsNavigablePath );
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// sqlAstCreationState.getCreationContext().getDomainModel().resolveMappingExpressable( )
|
||||
//
|
||||
// final List list = getNavigable().resolveColumnReferences( tableGroup, sqlAstCreationState );
|
||||
// if ( list.size() == 1 ) {
|
||||
// assert list.get( 0 ) instanceof Expression;
|
||||
// return (Expression) list.get( 0 );
|
||||
// }
|
||||
//
|
||||
// return new SqlTuple( list, sqlAstCreationState.getJdbcMapping() );
|
||||
// }
|
||||
@Override
|
||||
ModelPart getExpressionType();
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import java.util.Locale;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
|
@ -32,10 +31,6 @@ import org.hibernate.query.spi.QueryParameterBindings;
|
|||
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||
import org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
||||
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
import org.hibernate.sql.results.internal.domain.instantiation.DynamicInstantiation;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
|
||||
|
@ -53,6 +48,7 @@ import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
|||
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||
import org.hibernate.sql.results.internal.domain.instantiation.DynamicInstantiation;
|
||||
import org.hibernate.sql.results.spi.CircularFetchDetector;
|
||||
import org.hibernate.sql.results.spi.DomainResult;
|
||||
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||
|
@ -141,8 +137,7 @@ public class SqmSelectToSqlAstConverter
|
|||
}
|
||||
|
||||
private DomainResultProducer resolveDomainResultProducer(SqmSelection sqmSelection) {
|
||||
SqmSelectableInterpretation<?> interpretation = (SqmSelectableInterpretation<?>) sqmSelection.getSelectableNode().accept( this );
|
||||
return interpretation.getDomainResultProducer( this, getSqlAstCreationState() );
|
||||
return (DomainResultProducer) sqmSelection.getSelectableNode().accept( this );
|
||||
}
|
||||
|
||||
private int fetchDepth = 0;
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
/*
|
||||
* 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.sql.internal;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmSelectableInterpretation<T> {
|
||||
default DomainResultProducer<T> getDomainResultProducer(SqmToSqlAstConverter walker, SqlAstCreationState sqlAstCreationState) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* 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.sql.internal;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||
import org.hibernate.query.sqm.sql.ConversionException;
|
||||
import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class SqmSqlHelper {
|
||||
private SqmSqlHelper() {
|
||||
}
|
||||
|
||||
public static TableGroup resolveTableGroup(SqmPath<?> sqmPath, SqlAstCreationState creationState) {
|
||||
SqmPath<?> lhs = sqmPath;
|
||||
while ( lhs.getReferencedPathSource().getSqmPathType() instanceof EmbeddableDomainType ) {
|
||||
lhs = lhs.getLhs();
|
||||
}
|
||||
|
||||
final TableGroup tableGroup = creationState.getFromClauseAccess().findTableGroup( lhs.getNavigablePath() );
|
||||
if ( tableGroup != null ) {
|
||||
return tableGroup;
|
||||
}
|
||||
|
||||
throw new ConversionException( "Could not locate TableGroup to use : " + lhs.getNavigablePath() );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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.sql.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.internal.SqmMappingModelHelper;
|
||||
import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmTupleInterpretation<T> extends SqlTuple {
|
||||
|
||||
public static <T> SqmTupleInterpretation<T> from(
|
||||
SqmTuple<T> sqmTuple,
|
||||
SemanticQueryWalker<?> walker,
|
||||
SqlAstCreationState sqlAstCreationState) {
|
||||
final List<Expression> groupedSqlExpressions = new ArrayList<>();
|
||||
|
||||
for ( SqmExpression<?> groupedExpression : sqmTuple.getGroupedExpressions() ) {
|
||||
groupedSqlExpressions.add( (Expression) groupedExpression.accept( walker ) );
|
||||
}
|
||||
|
||||
return new SqmTupleInterpretation<>(
|
||||
sqmTuple,
|
||||
groupedSqlExpressions,
|
||||
SqmMappingModelHelper.resolveMappingModelExpressable( sqmTuple, sqlAstCreationState )
|
||||
);
|
||||
}
|
||||
|
||||
private final SqmTuple<T> interpretedSqmTuple;
|
||||
|
||||
public SqmTupleInterpretation(
|
||||
SqmTuple<T> sqmTuple,
|
||||
List<? extends Expression> expressions,
|
||||
MappingModelExpressable valueMapping) {
|
||||
|
||||
super( expressions, valueMapping );
|
||||
interpretedSqmTuple = sqmTuple;
|
||||
}
|
||||
|
||||
public SqmTuple<T> getInterpretedSqmTuple() {
|
||||
return interpretedSqmTuple;
|
||||
}
|
||||
}
|
|
@ -31,11 +31,6 @@ public abstract class AbstractSqmExpression<T> extends AbstractJpaSelection<T> i
|
|||
super( type, criteriaBuilder );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpressable<T> getExpressableType() {
|
||||
return getNodeType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void applyInferableType(SqmExpressable<?> type) {
|
||||
if ( type == null ) {
|
||||
|
|
|
@ -65,11 +65,6 @@ public class SqmEnumLiteral implements SqmExpression<Enum>, SqmExpressable<Enum>
|
|||
return referencedEnumTypeDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpressable<Enum> getExpressableType() {
|
||||
return expressable;
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// SemanticPathPart
|
||||
|
|
|
@ -16,7 +16,6 @@ import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
|||
import org.hibernate.metamodel.model.domain.DomainType;
|
||||
import org.hibernate.query.criteria.JpaExpression;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.sql.internal.SqmExpressionInterpretation;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
|
||||
|
||||
|
@ -29,7 +28,7 @@ import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmExpression<T> extends SqmSelectableNode<T>, JpaExpression<T>, SqmExpressionInterpretation<T> {
|
||||
public interface SqmExpression<T> extends SqmSelectableNode<T>, JpaExpression<T> {
|
||||
/**
|
||||
* The expression's type.
|
||||
*
|
||||
|
|
|
@ -77,11 +77,6 @@ public class SqmFieldLiteral<T> implements SqmExpression<T>, SqmExpressable<T>,
|
|||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpressable<T> getExpressableType() {
|
||||
return expressable;
|
||||
}
|
||||
|
||||
public JavaTypeDescriptor<T> getFieldJavaTypeDescriptor() {
|
||||
return fieldJavaTypeDescriptor;
|
||||
}
|
||||
|
|
|
@ -9,13 +9,7 @@ package org.hibernate.query.sqm.tree.expression;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.internal.SqmMappingModelHelper;
|
||||
import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
|
||||
|
||||
/**
|
||||
* Represents a literal value in the sqm, e.g.<ul>
|
||||
|
@ -46,18 +40,6 @@ public class SqmLiteral<T>
|
|||
return walker.visitLiteral( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression toSqlExpression(
|
||||
Clause clause,
|
||||
SqmToSqlAstConverter walker,
|
||||
SqlAstCreationState sqlAstCreationState) {
|
||||
return new QueryLiteral(
|
||||
getLiteralValue(),
|
||||
SqmMappingModelHelper.resolveMappingModelExpressable( this, sqlAstCreationState ),
|
||||
clause
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asLoggableText() {
|
||||
return "Literal( " + value + ")";
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.tree.expression;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -16,14 +15,7 @@ import org.hibernate.query.criteria.JpaSelection;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
import org.hibernate.query.sqm.sql.internal.SqmExpressionInterpretation;
|
||||
import org.hibernate.query.sqm.tree.select.SqmJpaCompoundSelection;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
|
@ -38,7 +30,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|||
*/
|
||||
public class SqmTuple<T>
|
||||
extends AbstractSqmExpression<T>
|
||||
implements JpaCompoundSelection<T>, SqmExpressionInterpretation<T> {
|
||||
implements JpaCompoundSelection<T> {
|
||||
private final List<SqmExpression<?>> groupedExpressions;
|
||||
|
||||
public SqmTuple(NodeBuilder nodeBuilder, SqmExpression<?>... groupedExpressions) {
|
||||
|
@ -63,6 +55,10 @@ public class SqmTuple<T>
|
|||
applyInferableType( type );
|
||||
}
|
||||
|
||||
public List<SqmExpression<?>> getGroupedExpressions() {
|
||||
return groupedExpressions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpressable<T> getNodeType() {
|
||||
final SqmExpressable<T> expressableType = super.getNodeType();
|
||||
|
@ -86,37 +82,6 @@ public class SqmTuple<T>
|
|||
return walker.visitTuple( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression toSqlExpression(
|
||||
Clause clause,
|
||||
SqmToSqlAstConverter walker,
|
||||
SqlAstCreationState sqlAstCreationState) {
|
||||
final List<Expression> groupedSqlExpressions = new ArrayList<>();
|
||||
|
||||
for ( SqmExpression groupedExpression : groupedExpressions ) {
|
||||
final SqmExpressionInterpretation interpretation = (SqmExpressionInterpretation) groupedExpression.accept( walker );
|
||||
final Expression sqlExpression = interpretation.toSqlExpression(
|
||||
clause, walker,
|
||||
sqlAstCreationState
|
||||
);
|
||||
|
||||
groupedSqlExpressions.add( sqlExpression );
|
||||
}
|
||||
|
||||
return new SqlTuple(
|
||||
groupedSqlExpressions,
|
||||
sqlAstCreationState.getCreationContext().getDomainModel()
|
||||
.resolveMappingExpressable( getExpressableType() )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResultProducer getDomainResultProducer(
|
||||
SqmToSqlAstConverter walker,
|
||||
SqlAstCreationState sqlAstCreationState) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asLoggableText() {
|
||||
return toString();
|
||||
|
@ -134,7 +99,7 @@ public class SqmTuple<T>
|
|||
|
||||
@Override
|
||||
public List<? extends JpaSelection<?>> getSelectionItems() {
|
||||
return groupedExpressions;
|
||||
return getGroupedExpressions();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.query.sqm.tree.from;
|
|||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
@ -16,15 +15,12 @@ import org.hibernate.query.PathException;
|
|||
import org.hibernate.query.criteria.JpaRoot;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
import org.hibernate.query.sqm.tree.domain.AbstractSqmFrom;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmTreatedRoot;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.results.spi.DomainResult;
|
||||
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
@ -102,20 +98,6 @@ public class SqmRoot<E> extends AbstractSqmFrom<E,E> implements JpaRoot<E>, Doma
|
|||
return new SqmTreatedRoot<>( this, treatTarget, nodeBuilder() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResultProducer<E> getDomainResultProducer(
|
||||
SqmToSqlAstConverter walker,
|
||||
SqlAstCreationState sqlAstCreationState) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression toSqlExpression(
|
||||
Clause clause, SqmToSqlAstConverter walker,
|
||||
SqlAstCreationState sqlAstCreationState) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJdbcTypes(Consumer<JdbcMapping> action, TypeConfiguration typeConfiguration) {
|
||||
final String entityName = getReferencedPathSource().getHibernateEntityName();
|
||||
|
|
|
@ -9,12 +9,7 @@ package org.hibernate.query.sqm.tree.select;
|
|||
import java.util.function.Consumer;
|
||||
import javax.persistence.criteria.Selection;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.query.criteria.JpaSelection;
|
||||
import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
import org.hibernate.query.sqm.sql.internal.SqmSelectableInterpretation;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||
|
||||
|
@ -24,7 +19,7 @@ import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmSelectableNode<T> extends JpaSelection<T>, SqmTypedNode<T>, SqmVisitableNode, SqmSelectableInterpretation<T> {
|
||||
public interface SqmSelectableNode<T> extends JpaSelection<T>, SqmTypedNode<T>, SqmVisitableNode {
|
||||
/**
|
||||
* Visit each of this selectable's direct sub-selectables - used to
|
||||
* support JPA's {@link Selection} model (which is really a "selectable",
|
||||
|
@ -34,8 +29,4 @@ public interface SqmSelectableNode<T> extends JpaSelection<T>, SqmTypedNode<T>,
|
|||
* @see Selection#getCompoundSelectionItems()
|
||||
*/
|
||||
void visitSubSelectableNodes(Consumer<SqmSelectableNode<?>> jpaSelectionConsumer);
|
||||
|
||||
default DomainResultProducer<T> getDomainResultProducer(SqmToSqlAstConverter walker, SqlAstCreationState sqlAstCreationState) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,8 +25,8 @@ import org.hibernate.NotYetImplementedFor6Exception;
|
|||
import org.hibernate.query.criteria.JpaSelection;
|
||||
import org.hibernate.query.criteria.JpaSubQuery;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.tree.SqmQuery;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmBagJoin;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmListJoin;
|
||||
|
@ -72,11 +72,6 @@ public class SqmSubQuery<T> extends AbstractSqmSelectQuery<T> implements SqmSele
|
|||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpressable<T> getExpressableType() {
|
||||
return expressableType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmQuery<?> getContainingQuery() {
|
||||
return parent;
|
||||
|
|
|
@ -22,5 +22,7 @@ import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface JdbcLiteralFormatter<T> {
|
||||
String NULL = "null";
|
||||
|
||||
String toJdbcLiteral(T value, Dialect dialect, SharedSessionContractImplementor session);
|
||||
}
|
||||
|
|
|
@ -8,17 +8,24 @@ package org.hibernate.sql.ast.tree.expression;
|
|||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||
import org.hibernate.sql.exec.spi.JdbcParameterBinder;
|
||||
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||
import org.hibernate.sql.results.internal.SqlSelectionImpl;
|
||||
import org.hibernate.sql.results.internal.domain.basic.BasicResult;
|
||||
import org.hibernate.sql.results.spi.DomainResult;
|
||||
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* We classify literals different based on their source so that we can handle then differently
|
||||
|
@ -31,10 +38,10 @@ import org.hibernate.type.BasicType;
|
|||
public abstract class AbstractLiteral<T>
|
||||
implements JdbcParameterBinder, Expression, DomainResultProducer<T> {
|
||||
private final Object value;
|
||||
private final MappingModelExpressable type;
|
||||
private final BasicValuedMapping type;
|
||||
private final Clause clause;
|
||||
|
||||
public AbstractLiteral(Object value, MappingModelExpressable type, Clause clause) {
|
||||
public AbstractLiteral(Object value, BasicValuedMapping type, Clause clause) {
|
||||
this.value = value;
|
||||
this.type = type;
|
||||
this.clause = clause;
|
||||
|
@ -49,15 +56,51 @@ public abstract class AbstractLiteral<T>
|
|||
}
|
||||
|
||||
@Override
|
||||
public MappingModelExpressable getExpressionType() {
|
||||
public BasicValuedMapping getExpressionType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult createDomainResult(
|
||||
public DomainResult<T> createDomainResult(
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
final SqlExpressionResolver sqlExpressionResolver = creationState.getSqlAstCreationState().getSqlExpressionResolver();
|
||||
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
|
||||
this,
|
||||
type.getMappedTypeDescriptor().getMappedJavaTypeDescriptor(),
|
||||
creationState.getSqlAstCreationState()
|
||||
.getCreationContext()
|
||||
.getSessionFactory()
|
||||
.getTypeConfiguration()
|
||||
);
|
||||
|
||||
//noinspection unchecked
|
||||
return new BasicResult<>(
|
||||
sqlSelection.getJdbcResultSetIndex(),
|
||||
resultVariable,
|
||||
type.getMappedTypeDescriptor().getMappedJavaTypeDescriptor()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlSelection createSqlSelection(
|
||||
int jdbcPosition,
|
||||
int valuesArrayPosition,
|
||||
JavaTypeDescriptor javaTypeDescriptor,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return new SqlSelectionImpl(
|
||||
jdbcPosition,
|
||||
valuesArrayPosition,
|
||||
this,
|
||||
type.getJdbcMapping()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJdbcTypes(
|
||||
Consumer<JdbcMapping> action,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
action.accept( type.getJdbcMapping() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.sql.ast.tree.expression;
|
||||
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.spi.SqlAstWalker;
|
||||
|
||||
|
@ -16,7 +16,7 @@ import org.hibernate.sql.ast.spi.SqlAstWalker;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class QueryLiteral<T> extends AbstractLiteral<T> {
|
||||
public QueryLiteral(Object value, MappingModelExpressable expressableType, Clause clause) {
|
||||
public QueryLiteral(Object value, BasicValuedMapping expressableType, Clause clause) {
|
||||
super( value, expressableType, clause );
|
||||
}
|
||||
|
||||
|
|
|
@ -12,9 +12,6 @@ import java.util.function.Consumer;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.spi.SqlAstWalker;
|
||||
|
||||
|
@ -77,10 +74,4 @@ public class StandardTableGroup extends AbstractTableGroup {
|
|||
public List<TableReferenceJoin> getTableReferenceJoins() {
|
||||
return tableJoins;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResultProducer getDomainResultProducer(
|
||||
SqmToSqlAstConverter walker, SqlAstCreationState sqlAstCreationState) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,11 +11,9 @@ import java.util.Set;
|
|||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
import org.hibernate.query.sqm.sql.internal.SqmSelectableInterpretation;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.spi.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
|
@ -30,7 +28,7 @@ import org.hibernate.sql.results.spi.DomainResultCreationState;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface TableGroup
|
||||
extends SqlAstNode, ColumnReferenceQualifier, DomainResultProducer, SqmSelectableInterpretation {
|
||||
extends SqlAstNode, ColumnReferenceQualifier, DomainResultProducer {
|
||||
NavigablePath getNavigablePath();
|
||||
|
||||
ModelPartContainer getModelPart();
|
||||
|
|
|
@ -37,6 +37,10 @@ public class ArgumentDomainResult<A> implements DomainResult<A> {
|
|||
public ArgumentReader<A> createResultAssembler(
|
||||
Consumer<Initializer> initializerCollector,
|
||||
AssemblerCreationState creationState) {
|
||||
return null;
|
||||
//noinspection unchecked
|
||||
return new ArgumentReader(
|
||||
realDomainResult.createResultAssembler( initializerCollector, creationState ),
|
||||
getResultVariable()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,20 +6,15 @@
|
|||
*/
|
||||
package org.hibernate.sql.results.internal.domain.instantiation;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.query.DynamicInstantiationNature;
|
||||
import org.hibernate.query.sqm.sql.ConversionException;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
import org.hibernate.query.sqm.tree.expression.Compatibility;
|
||||
import org.hibernate.sql.results.spi.AssemblerCreationState;
|
||||
import org.hibernate.sql.results.spi.DomainResult;
|
||||
import org.hibernate.sql.results.spi.DomainResultAssembler;
|
||||
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
|
@ -116,131 +111,124 @@ public class DynamicInstantiation<T> implements DomainResultProducer {
|
|||
public DomainResult createDomainResult(
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
//noinspection unchecked
|
||||
return new DynamicInstantiationResultImpl(
|
||||
resultVariable,
|
||||
getNature(),
|
||||
getTargetJavaTypeDescriptor(),
|
||||
getArguments().stream()
|
||||
.map( argument -> argument.buildArgumentDomainResult( creationState ) )
|
||||
.collect( Collectors.toList() )
|
||||
);
|
||||
}
|
||||
|
||||
// @Override
|
||||
//
|
||||
// @SuppressWarnings("unchecked")
|
||||
// public DomainResult createDomainResult(
|
||||
// String resultVariable,
|
||||
// DomainResultCreationState creationState) {
|
||||
// return new DynamicInstantiationResult(
|
||||
// resultVariable,
|
||||
// getNature(),
|
||||
// (JavaTypeDescriptor) getTargetJavaTypeDescriptor(),
|
||||
// getArguments().stream()
|
||||
// .map( argument -> argument.buildArgumentDomainResult( creationState ) )
|
||||
// .collect( Collectors.toList() )
|
||||
// );
|
||||
// private static DomainResultAssembler resolveAssembler(
|
||||
// DynamicInstantiation dynamicInstantiation,
|
||||
// boolean areAllArgumentsAliased,
|
||||
// boolean areAnyArgumentsAliased,
|
||||
// List<String> duplicatedAliases,
|
||||
// List<ArgumentReader<?>> argumentReaders,
|
||||
// AssemblerCreationState creationState) {
|
||||
//
|
||||
// if ( dynamicInstantiation.getNature() == DynamicInstantiationNature.LIST ) {
|
||||
// if ( log.isDebugEnabled() && areAnyArgumentsAliased ) {
|
||||
// log.debug( "One or more arguments for List dynamic instantiation (`new list(...)`) specified an alias; ignoring" );
|
||||
// }
|
||||
// return new DynamicInstantiationListAssemblerImpl(
|
||||
// (JavaTypeDescriptor<List>) dynamicInstantiation.getTargetJavaTypeDescriptor(),
|
||||
// argumentReaders
|
||||
// );
|
||||
// }
|
||||
// else if ( dynamicInstantiation.getNature() == DynamicInstantiationNature.MAP ) {
|
||||
// if ( ! areAllArgumentsAliased ) {
|
||||
// throw new IllegalStateException( "Map dynamic instantiation contained one or more arguments with no alias" );
|
||||
// }
|
||||
// if ( !duplicatedAliases.isEmpty() ) {
|
||||
// throw new IllegalStateException(
|
||||
// "Map dynamic instantiation contained arguments with duplicated aliases [" + StringHelper.join( ",", duplicatedAliases ) + "]"
|
||||
// );
|
||||
// }
|
||||
// return new DynamicInstantiationMapAssemblerImpl(
|
||||
// (JavaTypeDescriptor<Map>) dynamicInstantiation.getTargetJavaTypeDescriptor(),
|
||||
// argumentReaders
|
||||
// );
|
||||
// }
|
||||
// else {
|
||||
// // find a constructor matching argument types
|
||||
// constructor_loop:
|
||||
// for ( Constructor constructor : dynamicInstantiation.getTargetJavaTypeDescriptor().getJavaType().getDeclaredConstructors() ) {
|
||||
// if ( constructor.getParameterTypes().length != dynamicInstantiation.arguments.size() ) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// for ( int i = 0; i < dynamicInstantiation.arguments.size(); i++ ) {
|
||||
// final ArgumentReader argumentReader = argumentReaders.get( i );
|
||||
// final JavaTypeDescriptor argumentTypeDescriptor = creationState.getSqlAstCreationContext().getDomainModel()
|
||||
// .getTypeConfiguration()
|
||||
// .getJavaTypeDescriptorRegistry()
|
||||
// .resolveDescriptor( constructor.getParameterTypes()[i] );
|
||||
//
|
||||
// final boolean assignmentCompatible = Compatibility.areAssignmentCompatible(
|
||||
// argumentTypeDescriptor,
|
||||
// argumentReader.getAssembledJavaTypeDescriptor()
|
||||
// );
|
||||
// if ( !assignmentCompatible ) {
|
||||
// log.debugf(
|
||||
// "Skipping constructor for dynamic-instantiation match due to argument mismatch [%s] : %s -> %s",
|
||||
// i,
|
||||
// constructor.getParameterTypes()[i].getName(),
|
||||
// argumentTypeDescriptor.getJavaType().getName()
|
||||
// );
|
||||
// continue constructor_loop;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// constructor.setAccessible( true );
|
||||
// return new DynamicInstantiationConstructorAssemblerImpl(
|
||||
// constructor,
|
||||
// dynamicInstantiation.getTargetJavaTypeDescriptor(),
|
||||
// argumentReaders
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// log.debugf(
|
||||
// "Could not locate appropriate constructor for dynamic instantiation of [%s]; attempting bean-injection instantiation",
|
||||
// dynamicInstantiation.getTargetJavaTypeDescriptor().getJavaType().getName()
|
||||
// );
|
||||
//
|
||||
//
|
||||
// if ( ! areAllArgumentsAliased ) {
|
||||
// throw new IllegalStateException(
|
||||
// "Could not determine appropriate instantiation strategy - no matching constructor found and one or more arguments did not define alias for bean-injection"
|
||||
// );
|
||||
// }
|
||||
// if ( !duplicatedAliases.isEmpty() ) {
|
||||
// throw new IllegalStateException(
|
||||
// "Could not determine appropriate instantiation strategy - no matching constructor found and arguments defined duplicated aliases [" +
|
||||
// StringHelper.join( ",", duplicatedAliases ) + "] for bean-injection"
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// return new DynamicInstantiationInjectionAssemblerImpl(
|
||||
// dynamicInstantiation.getTargetJavaTypeDescriptor(),
|
||||
// argumentReaders
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
//
|
||||
@SuppressWarnings("unchecked")
|
||||
private static DomainResultAssembler resolveAssembler(
|
||||
DynamicInstantiation dynamicInstantiation,
|
||||
boolean areAllArgumentsAliased,
|
||||
boolean areAnyArgumentsAliased,
|
||||
List<String> duplicatedAliases,
|
||||
List<ArgumentReader<?>> argumentReaders,
|
||||
AssemblerCreationState creationState) {
|
||||
|
||||
if ( dynamicInstantiation.getNature() == DynamicInstantiationNature.LIST ) {
|
||||
if ( log.isDebugEnabled() && areAnyArgumentsAliased ) {
|
||||
log.debug( "One or more arguments for List dynamic instantiation (`new list(...)`) specified an alias; ignoring" );
|
||||
}
|
||||
return new DynamicInstantiationListAssemblerImpl(
|
||||
(JavaTypeDescriptor<List>) dynamicInstantiation.getTargetJavaTypeDescriptor(),
|
||||
argumentReaders
|
||||
);
|
||||
}
|
||||
else if ( dynamicInstantiation.getNature() == DynamicInstantiationNature.MAP ) {
|
||||
if ( ! areAllArgumentsAliased ) {
|
||||
throw new IllegalStateException( "Map dynamic instantiation contained one or more arguments with no alias" );
|
||||
}
|
||||
if ( !duplicatedAliases.isEmpty() ) {
|
||||
throw new IllegalStateException(
|
||||
"Map dynamic instantiation contained arguments with duplicated aliases [" + StringHelper.join( ",", duplicatedAliases ) + "]"
|
||||
);
|
||||
}
|
||||
return new DynamicInstantiationMapAssemblerImpl(
|
||||
(JavaTypeDescriptor<Map>) dynamicInstantiation.getTargetJavaTypeDescriptor(),
|
||||
argumentReaders
|
||||
);
|
||||
}
|
||||
else {
|
||||
// find a constructor matching argument types
|
||||
constructor_loop:
|
||||
for ( Constructor constructor : dynamicInstantiation.getTargetJavaTypeDescriptor().getJavaType().getDeclaredConstructors() ) {
|
||||
if ( constructor.getParameterTypes().length != dynamicInstantiation.arguments.size() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for ( int i = 0; i < dynamicInstantiation.arguments.size(); i++ ) {
|
||||
final ArgumentReader argumentReader = argumentReaders.get( i );
|
||||
final JavaTypeDescriptor argumentTypeDescriptor = creationState.getSqlAstCreationContext().getDomainModel()
|
||||
.getTypeConfiguration()
|
||||
.getJavaTypeDescriptorRegistry()
|
||||
.resolveDescriptor( constructor.getParameterTypes()[i] );
|
||||
|
||||
final boolean assignmentCompatible = Compatibility.areAssignmentCompatible(
|
||||
argumentTypeDescriptor,
|
||||
argumentReader.getAssembledJavaTypeDescriptor()
|
||||
);
|
||||
if ( !assignmentCompatible ) {
|
||||
log.debugf(
|
||||
"Skipping constructor for dynamic-instantiation match due to argument mismatch [%s] : %s -> %s",
|
||||
i,
|
||||
constructor.getParameterTypes()[i].getName(),
|
||||
argumentTypeDescriptor.getJavaType().getName()
|
||||
);
|
||||
continue constructor_loop;
|
||||
}
|
||||
}
|
||||
|
||||
constructor.setAccessible( true );
|
||||
return new DynamicInstantiationConstructorAssemblerImpl(
|
||||
constructor,
|
||||
dynamicInstantiation.getTargetJavaTypeDescriptor(),
|
||||
argumentReaders
|
||||
);
|
||||
}
|
||||
|
||||
log.debugf(
|
||||
"Could not locate appropriate constructor for dynamic instantiation of [%s]; attempting bean-injection instantiation",
|
||||
dynamicInstantiation.getTargetJavaTypeDescriptor().getJavaType().getName()
|
||||
);
|
||||
|
||||
|
||||
if ( ! areAllArgumentsAliased ) {
|
||||
throw new IllegalStateException(
|
||||
"Could not determine appropriate instantiation strategy - no matching constructor found and one or more arguments did not define alias for bean-injection"
|
||||
);
|
||||
}
|
||||
if ( !duplicatedAliases.isEmpty() ) {
|
||||
throw new IllegalStateException(
|
||||
"Could not determine appropriate instantiation strategy - no matching constructor found and arguments defined duplicated aliases [" +
|
||||
StringHelper.join( ",", duplicatedAliases ) + "] for bean-injection"
|
||||
);
|
||||
}
|
||||
|
||||
return new DynamicInstantiationInjectionAssemblerImpl(
|
||||
dynamicInstantiation.getTargetJavaTypeDescriptor(),
|
||||
argumentReaders
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Builder {
|
||||
private final DynamicInstantiationNature nature;
|
||||
private final JavaTypeDescriptor<T> targetJavaTypeDescriptor;
|
||||
private List<DynamicInstantiationArgument> arguments;
|
||||
|
||||
public Builder(
|
||||
DynamicInstantiationNature nature,
|
||||
JavaTypeDescriptor<T> targetJavaTypeDescriptor) {
|
||||
this.nature = nature;
|
||||
this.targetJavaTypeDescriptor = targetJavaTypeDescriptor;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// class Builder {
|
||||
// private final DynamicInstantiationNature nature;
|
||||
// private final JavaTypeDescriptor<T> targetJavaTypeDescriptor;
|
||||
// private List<DynamicInstantiationArgument> arguments;
|
||||
//
|
||||
// public Builder(
|
||||
// DynamicInstantiationNature nature,
|
||||
// JavaTypeDescriptor<T> targetJavaTypeDescriptor) {
|
||||
// this.nature = nature;
|
||||
// this.targetJavaTypeDescriptor = targetJavaTypeDescriptor;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -12,11 +12,14 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.sql.ast.spi.JdbcLiteralFormatter;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
import static org.hibernate.sql.ast.spi.JdbcLiteralFormatter.NULL;
|
||||
|
||||
/**
|
||||
* Descriptor for {@link Types#NVARCHAR NVARCHAR} handling.
|
||||
*
|
||||
|
@ -38,6 +41,11 @@ public class NVarcharTypeDescriptor implements SqlTypeDescriptor {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||
return (value, dialect, session) -> value == null ? NULL : "'" + value.toString() + "'";
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
|
|
|
@ -12,11 +12,14 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.sql.ast.spi.JdbcLiteralFormatter;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
import static org.hibernate.sql.ast.spi.JdbcLiteralFormatter.NULL;
|
||||
|
||||
/**
|
||||
* Descriptor for {@link Types#VARCHAR VARCHAR} handling.
|
||||
*
|
||||
|
@ -38,6 +41,11 @@ public class VarcharTypeDescriptor implements SqlTypeDescriptor {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||
return (value, dialect, session) -> value == null ? NULL : "'" + value.toString() + "'";
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
|
|
|
@ -163,6 +163,14 @@ public class SmokeTests {
|
|||
private String attribute1;
|
||||
private String attribute2;
|
||||
|
||||
public Component() {
|
||||
}
|
||||
|
||||
public Component(String attribute1, String attribute2) {
|
||||
this.attribute1 = attribute1;
|
||||
this.attribute2 = attribute2;
|
||||
}
|
||||
|
||||
public String getAttribute1() {
|
||||
return attribute1;
|
||||
}
|
||||
|
|
|
@ -125,15 +125,6 @@ public class SmokeTests {
|
|||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleHqlExecution(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final QueryImplementor<String> query = session.createQuery( "select e.name from SimpleEntity e", String.class );
|
||||
query.list();
|
||||
}
|
||||
);
|
||||
}
|
||||
@Test
|
||||
public void testConvertedHqlInterpretation(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
|
@ -232,46 +223,6 @@ public class SmokeTests {
|
|||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertedHqlExecution(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final QueryImplementor<Gender> query = session.createQuery( "select e.gender from SimpleEntity e", Gender.class );
|
||||
query.list();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectRootHqlExecution(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final QueryImplementor<SimpleEntity> query = session.createQuery( "select e from SimpleEntity e", SimpleEntity.class );
|
||||
query.list();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectEmbeddedHqlExecution(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final QueryImplementor<Component> query = session.createQuery( "select e.component from SimpleEntity e", Component.class );
|
||||
query.list();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectEmbeddableSubPathHqlExecution(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final QueryImplementor<String> query = session.createQuery( "select e.component.attribute1 from SimpleEntity e", String.class );
|
||||
query.list();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadQueryResultType(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
|
|
|
@ -10,8 +10,10 @@ import java.sql.Statement;
|
|||
import java.util.List;
|
||||
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.Component;
|
||||
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.SimpleEntity;
|
||||
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender;
|
||||
import org.hibernate.query.Query;
|
||||
import org.hibernate.query.spi.QueryImplementor;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
|
@ -24,6 +26,7 @@ import org.junit.jupiter.api.BeforeEach;
|
|||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender.FEMALE;
|
||||
import static org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender.MALE;
|
||||
|
@ -33,13 +36,21 @@ import static org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender.MALE;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
@DomainModel(
|
||||
annotatedClasses = SimpleEntity.class
|
||||
annotatedClasses = SimpleEntity.class,
|
||||
extraQueryImportClasses = {
|
||||
SmokeTests.ListItemDto.class,
|
||||
SmokeTests.CategorizedListItemDto.class,
|
||||
SmokeTests.CompoundDto.class,
|
||||
SmokeTests.BasicSetterBasedDto.class
|
||||
}
|
||||
)
|
||||
@ServiceRegistry(
|
||||
settings = @ServiceRegistry.Setting(
|
||||
name = AvailableSettings.HBM2DDL_AUTO,
|
||||
value = "create-drop"
|
||||
)
|
||||
settings = {
|
||||
@ServiceRegistry.Setting(
|
||||
name = AvailableSettings.HBM2DDL_AUTO,
|
||||
value = "create-drop"
|
||||
)
|
||||
}
|
||||
)
|
||||
@SessionFactory
|
||||
public class SmokeTests {
|
||||
|
@ -53,6 +64,7 @@ public class SmokeTests {
|
|||
simpleEntity.setGender( FEMALE );
|
||||
simpleEntity.setName( "Fab" );
|
||||
simpleEntity.setGender2( MALE );
|
||||
simpleEntity.setComponent( new Component( "a1", "a2" ) );
|
||||
session.save( simpleEntity );
|
||||
}
|
||||
);
|
||||
|
@ -73,7 +85,7 @@ public class SmokeTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testSelectEntityFieldHqlExecution(SessionFactoryScope scope) {
|
||||
public void testHqlSelectEntityBasicAttribute(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final QueryImplementor<String> query = session.createQuery(
|
||||
|
@ -88,7 +100,7 @@ public class SmokeTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testSelectGenderHql(SessionFactoryScope scope) {
|
||||
public void testHqlSelectConvertedAttribute(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final QueryImplementor<Gender> query = session.createQuery(
|
||||
|
@ -103,7 +115,7 @@ public class SmokeTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testSelectEntityHqlExecution(SessionFactoryScope scope) {
|
||||
public void testHqlSelectRootEntity(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final QueryImplementor<SimpleEntity> query = session.createQuery(
|
||||
|
@ -117,6 +129,168 @@ public class SmokeTests {
|
|||
assertThat( simpleEntity.getGender(), is(FEMALE) );
|
||||
assertThat( simpleEntity.getGender2(), is(MALE) );
|
||||
assertThat( simpleEntity.getName(), is("Fab") );
|
||||
assertThat( simpleEntity.getComponent(), notNullValue() );
|
||||
assertThat( simpleEntity.getComponent().getAttribute1(), is( "a1" ) );
|
||||
assertThat( simpleEntity.getComponent().getAttribute2(), is( "a2" ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHqlSelectEmbeddedAttribute(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final QueryImplementor<Component> query = session.createQuery( "select e.component from SimpleEntity e", Component.class );
|
||||
final Component component = query.uniqueResult();
|
||||
assertThat( component, notNullValue() );
|
||||
assertThat( component.getAttribute1(), is( "a1" ) );
|
||||
assertThat( component.getAttribute2(), is( "a2" ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHqlSelectEmbeddableSubAttribute(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final QueryImplementor<String> query = session.createQuery( "select e.component.attribute1 from SimpleEntity e", String.class );
|
||||
final String attribute1 = query.uniqueResult();
|
||||
assertThat( attribute1, is( "a1" ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Dynamic instantiations
|
||||
|
||||
public static class ListItemDto {
|
||||
private String code;
|
||||
private String value;
|
||||
|
||||
public ListItemDto(String code, String value) {
|
||||
this.code = code;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static class CategorizedListItemDto {
|
||||
private ListItemDto category;
|
||||
private String code;
|
||||
private String value;
|
||||
|
||||
public CategorizedListItemDto(ListItemDto category, String code, String value) {
|
||||
this.category = category;
|
||||
this.code = code;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static class CompoundDto {
|
||||
private ListItemDto first;
|
||||
private ListItemDto second;
|
||||
|
||||
public CompoundDto(ListItemDto first, ListItemDto second) {
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
}
|
||||
}
|
||||
|
||||
public static class BasicSetterBasedDto {
|
||||
private String code;
|
||||
private String value;
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHqlBasicDynamicInstantiation(SessionFactoryScope scope) {
|
||||
scope.getSessionFactory().inTransaction(
|
||||
session -> {
|
||||
final Query<ListItemDto> query = session.createQuery(
|
||||
"select new ListItemDto( e.component.attribute1, e.name ) from SimpleEntity e",
|
||||
ListItemDto.class
|
||||
);
|
||||
|
||||
final ListItemDto dto = query.getSingleResult();
|
||||
assertThat( dto, notNullValue() );
|
||||
assertThat( dto.code, is( "a1" ) );
|
||||
assertThat( dto.value, is( "Fab" ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHqlNestedDynamicInstantiation(SessionFactoryScope scope) {
|
||||
scope.getSessionFactory().inTransaction(
|
||||
session -> {
|
||||
final Query<CategorizedListItemDto> query = session.createQuery(
|
||||
"select new CategorizedListItemDto( new ListItemDto( e.component.attribute2, e.component.attribute1 ), e.component.attribute1, e.name ) from SimpleEntity e",
|
||||
CategorizedListItemDto.class
|
||||
);
|
||||
|
||||
final CategorizedListItemDto dto = query.getSingleResult();
|
||||
assertThat( dto, notNullValue() );
|
||||
assertThat( dto.category, notNullValue() );
|
||||
assertThat( dto.category.code, is( "a2") );
|
||||
assertThat( dto.category.value, is( "a1") );
|
||||
assertThat( dto.code, is( "a1" ) );
|
||||
assertThat( dto.value, is( "Fab" ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHqlMultipleDynamicInstantiation(SessionFactoryScope scope) {
|
||||
scope.getSessionFactory().inTransaction(
|
||||
session -> {
|
||||
final Query<CompoundDto> query = session.createQuery(
|
||||
"select new CompoundDto( new ListItemDto( e.component.attribute1, e.name ), new ListItemDto( e.component.attribute2, e.name ) ) from SimpleEntity e",
|
||||
CompoundDto.class
|
||||
);
|
||||
|
||||
final CompoundDto dto = query.getSingleResult();
|
||||
assertThat( dto, notNullValue() );
|
||||
|
||||
assertThat( dto.first, notNullValue() );
|
||||
assertThat( dto.first.code, is( "a1" ) );
|
||||
assertThat( dto.first.value, is( "Fab" ) );
|
||||
|
||||
assertThat( dto.second, notNullValue() );
|
||||
assertThat( dto.second.code, is( "a2" ) );
|
||||
assertThat( dto.second.value, is( "Fab" ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasicSetterDynamicInstantiation(SessionFactoryScope scope) {
|
||||
scope.getSessionFactory().inTransaction(
|
||||
session -> {
|
||||
final Query<BasicSetterBasedDto> query = session.createQuery(
|
||||
"select new BasicSetterBasedDto( e.component.attribute1 as code, e.name as value ) from SimpleEntity e",
|
||||
BasicSetterBasedDto.class
|
||||
);
|
||||
|
||||
final BasicSetterBasedDto dto = query.getSingleResult();
|
||||
assertThat( dto, notNullValue() );
|
||||
|
||||
assertThat( dto.code, is( "a1" ) );
|
||||
assertThat( dto.value, is( "Fab" ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -93,4 +93,11 @@ public @interface DomainModel {
|
|||
Class[] annotatedClasses() default {};
|
||||
String[] annotatedClassNames() default {};
|
||||
String[] xmlMappings() default {};
|
||||
ExtraQueryImport[] extraQueryImports() default {};
|
||||
Class<?>[] extraQueryImportClasses() default {};
|
||||
|
||||
@interface ExtraQueryImport {
|
||||
String name();
|
||||
Class<?> importedClass();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,6 +95,14 @@ public class DomainModelExtension
|
|||
metadataSources.addResource( xmlMapping );
|
||||
}
|
||||
|
||||
for ( DomainModel.ExtraQueryImport extraQueryImport : domainModelAnnotation.extraQueryImports() ) {
|
||||
metadataSources.addQueryImport( extraQueryImport.name(), extraQueryImport.importedClass() );
|
||||
}
|
||||
|
||||
for ( Class<?> importedClass : domainModelAnnotation.extraQueryImportClasses() ) {
|
||||
metadataSources.addQueryImport( importedClass.getSimpleName(), importedClass );
|
||||
}
|
||||
|
||||
return (MetadataImplementor) metadataSources.buildMetadata();
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue