6 - SQM based on JPA type system

- further work on `org.hibernate.query` (especially `NamedQueryRepository` and friends)
- initial work on `org.hibernate.sql.exec`
- initial work on `org.hibernate.sql.results`
- SemanticPathPart handling
This commit is contained in:
Steve Ebersole 2019-05-28 16:12:18 -05:00 committed by Andrea Boriero
parent fb12f3a60f
commit 2167abd373
76 changed files with 3416 additions and 727 deletions

View File

@ -0,0 +1,25 @@
/*
* 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;
/**
* Hibernate often deals with compound names/paths. This interface
* defines a standard way of interacting with them
*
* @author Steve Ebersole
*/
public interface DotIdentifierSequence {
DotIdentifierSequence getParent();
String getLocalName();
String getFullPath();
DotIdentifierSequence append(String subPathName);
default boolean isRoot() {
return getParent() == null;
}
}

View File

@ -43,7 +43,7 @@ import org.hibernate.mapping.MappedSuperclass;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Table;
import org.hibernate.procedure.NamedCallableQueryMemento;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.query.spi.NamedQueryRepository;
import org.hibernate.type.Type;
import org.hibernate.type.TypeResolver;

View File

@ -0,0 +1,220 @@
/*
* 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.boot.internal;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.ParameterMode;
import javax.persistence.StoredProcedureParameter;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockOptions;
import org.hibernate.boot.spi.AbstractNamedQueryMapping;
import org.hibernate.boot.spi.NamedCallableQueryMapping;
import org.hibernate.boot.spi.NamedQueryParameterMapping;
import org.hibernate.cfg.BinderHelper;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.procedure.internal.NamedCallableQueryMementoImpl;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.procedure.spi.ParameterStrategy;
import org.hibernate.query.procedure.internal.ProcedureParameterImpl;
import org.hibernate.query.spi.ParameterMemento;
/**
* @author Steve Ebersole
*/
public class NamedCallableQueryMappingImpl extends AbstractNamedQueryMapping implements NamedCallableQueryMapping {
private final String callableName;
private final List<String> resultSetMappingNames;
private final List<Class> resultClasses;
private final Set<String> querySpaces;
public NamedCallableQueryMappingImpl(
String name,
String callableName,
List<NamedQueryParameterMapping> parameterMappings,
List<Class> resultClasses,
List<String> resultSetMappingNames,
Set<String> querySpaces,
Boolean cacheable,
String cacheRegion,
CacheMode cacheMode,
FlushMode flushMode,
Boolean readOnly,
LockOptions lockOptions,
Integer timeout,
Integer fetchSize,
String comment,
Map<String,Object> hints) {
super(
name,
parameterMappings,
cacheable,
cacheRegion,
cacheMode,
flushMode,
readOnly,
lockOptions,
timeout,
fetchSize,
comment,
hints
);
this.callableName = callableName;
this.resultSetMappingNames = resultSetMappingNames;
this.resultClasses = resultClasses;
this.querySpaces = querySpaces;
}
@Override
public NamedCallableQueryMemento resolve(SessionFactoryImplementor factory) {
return new NamedCallableQueryMementoImpl(
getName(),
callableName,
ParameterStrategy.UNKNOWN,
resolveParameterMappings( factory ),
resultClasses,
resultSetMappingNames,
querySpaces,
getCacheable(),
getCacheRegion(),
getCacheMode(),
getFlushMode(),
getReadOnly(),
getLockOptions(),
getTimeout(),
getFetchSize(),
getComment(),
getHints()
);
}
@Override
protected List<? extends NamedCallableQueryMementoImpl.CallableParameterMemento> resolveParameterMappings(SessionFactoryImplementor factory) {
//noinspection unchecked
return (List) super.resolveParameterMappings( factory );
}
public static class Builder extends AbstractBuilder<Builder> {
private String callableName;
private List<Class> resultClasses;
private List<String> resultSetMappingNames;
private ParameterStrategy parameterStrategy = ParameterStrategy.UNKNOWN;
private List<NamedCallableQueryParameterMapping> parameterMappings;
public Builder(String name) {
super( name );
}
@Override
protected Builder getThis() {
return this;
}
public Builder consume(StoredProcedureParameter[] parameters) {
if ( parameters != null && parameters.length > 0 ) {
for ( StoredProcedureParameter parameter : parameters ) {
consume( parameter );
}
}
return getThis();
}
private void consume(StoredProcedureParameter parameter) {
if ( BinderHelper.isEmptyAnnotationValue( parameter.name() ) ) {
consumeNamedParameter( parameter.name(), parameter.type(), parameter.mode() );
}
if ( parameter.name() != null ) {
}
}
private void consumeNamedParameter(String name, Class type, ParameterMode mode) {
if ( parameterStrategy == ParameterStrategy.POSITIONAL ) {
throw new IllegalArgumentException(
"Named queries cannot mix named and positional parameters: " + getName()
);
}
parameterStrategy = ParameterStrategy.NAMED;
final NamedCallableQueryParameterMapping namedParameter = new NamedCallableQueryParameterMapping() {
@Override
public ParameterMemento resolve(SessionFactoryImplementor factory) {
return session -> new ProcedureParameterImpl(
label,
mode,
javaType,
factory.getMetamodel().getTypeConfiguration().standardBasicTypeForJavaType( javaType ),
factory.getSessionFactoryOptions().isProcedureParameterNullPassingEnabled()
);
}
};
parameterMappings.add( namedParameter );
}
@Override
protected NamedCallableQueryParameterMapping createPositionalParameter(int label, Class javaType, ParameterMode mode) {
return
}
@Override
protected NamedCallableQueryParameterMapping createNamedParameter(String name, Class javaType, ParameterMode mode) {
//noinspection Convert2Lambda
return new NamedQueryParameterMapping() {
@Override
@SuppressWarnings("unchecked")
public ParameterMemento resolve(SessionFactoryImplementor factory) {
return session -> new ProcedureParameterImpl(
name,
mode,
javaType,
factory.getMetamodel().getTypeConfiguration().standardBasicTypeForJavaType( javaType ),
factory.getSessionFactoryOptions().isProcedureParameterNullPassingEnabled()
);
}
};
}
public NamedCallableQueryMapping build() {
return new NamedCallableQueryMappingImpl(
getName(),
callableName,
getParameterMappings(),
resultClasses,
resultSetMappingNames,
getQuerySpaces(),
getCacheable(),
getCacheRegion(),
getCacheMode(),
getFlushMode(),
getReadOnly(),
getLockOptions(),
getTimeout(),
getFetchSize(),
getComment(),
getHints()
);
}
public Builder setCallableName(String callableName) {
this.callableName = callableName;
return this;
}
}
private static class NamedCallableQueryParameterMapping implements NamedQueryParameterMapping {
@Override
public ParameterMemento resolve(SessionFactoryImplementor factory) {
return null;
}
}
}

View File

@ -0,0 +1,161 @@
/*
* 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.boot.internal;
import java.util.List;
import java.util.Map;
import javax.persistence.ParameterMode;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockOptions;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.boot.spi.AbstractNamedQueryMapping;
import org.hibernate.boot.spi.NamedHqlQueryMapping;
import org.hibernate.boot.spi.NamedQueryParameterMapping;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
/**
* @author Steve Ebersole
*/
public class NamedHqlQueryMappingImpl extends AbstractNamedQueryMapping implements NamedHqlQueryMapping {
private final String hqlString;
private final Integer firstResult;
private final Integer maxResults;
public NamedHqlQueryMappingImpl(
String name,
String hqlString,
List<NamedQueryParameterMapping> parameterMappings,
Integer firstResult,
Integer maxResults,
Boolean cacheable,
String cacheRegion,
CacheMode cacheMode,
FlushMode flushMode,
Boolean readOnly,
LockOptions lockOptions,
Integer timeout,
Integer fetchSize,
String comment,
Map<String,Object> hints) {
super(
name,
parameterMappings,
cacheable,
cacheRegion,
cacheMode,
flushMode,
readOnly,
lockOptions,
timeout,
fetchSize,
comment,
hints
);
this.hqlString = hqlString;
this.firstResult = firstResult;
this.maxResults = maxResults;
}
@Override
public String getQueryString() {
return hqlString;
}
@Override
public NamedHqlQueryMemento resolve(SessionFactoryImplementor factory) {
return new NamedHqlQueryMementoImpl(
getName(),
hqlString,
resolveParameterMappings( factory ),
firstResult,
maxResults,
getCacheable(),
getCacheRegion(),
getCacheMode(),
getFlushMode(),
getReadOnly(),
getLockOptions(),
getTimeout(),
getFetchSize(),
getComment(),
getHints()
);
}
public static class Builder extends AbstractBuilder<Builder> {
private final String hqlString;
private Integer firstResult;
private Integer maxResults;
public Builder(String name, String hqlString) {
super( name );
this.hqlString = hqlString;
}
@Override
protected Builder getThis() {
return this;
}
public Builder setFirstResult(Integer firstResult) {
this.firstResult = firstResult;
return getThis();
}
public Builder setMaxResults(Integer maxResults) {
this.maxResults = maxResults;
return getThis();
}
@Override
protected NamedQueryParameterMapping createPositionalParameter(int i, Class javaType, ParameterMode mode) {
/// todo (6.0) : this really ought to just adjust the type, if one...
throw new NotYetImplementedFor6Exception();
// return new ParameterDefinition() {
// @Override
// public ParameterDescriptor resolve(SessionFactoryImplementor factory) {
// return new ParameterDescriptor() {
// @Override
// public QueryParameter toQueryParameter(SharedSessionContractImplementor session) {
// return new QueryParameterPositionalImpl( i, );
// }
// };
// }
// };
}
@Override
protected NamedQueryParameterMapping createNamedParameter(String name, Class javaType, ParameterMode mode) {
throw new NotYetImplementedFor6Exception();
}
public NamedHqlQueryMappingImpl build() {
return new NamedHqlQueryMappingImpl(
getName(),
hqlString,
getParameterMappings(),
firstResult,
maxResults,
getCacheable(),
getCacheRegion(),
getCacheMode(),
getFlushMode(),
getReadOnly(),
getLockOptions(),
getTimeout(),
getFetchSize(),
getComment(),
getHints()
);
}
}
}

View File

@ -0,0 +1,166 @@
/*
* 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.boot.internal;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.ParameterMode;
import org.hibernate.BasicQueryContract;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockOptions;
import org.hibernate.boot.spi.AbstractNamedQueryMapping;
import org.hibernate.boot.spi.NamedNativeQueryMapping;
import org.hibernate.boot.spi.NamedQueryParameterMapping;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.spi.ParameterMemento;
import org.hibernate.query.sql.internal.NamedNativeQueryMementoImpl;
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
/**
* @author Steve Ebersole
*/
public class NamedNativeQueryMappingImpl extends AbstractNamedQueryMapping implements NamedNativeQueryMapping {
private final String sqlString;
private final String resultSetMappingName;
private final Set<String> querySpaces;
public NamedNativeQueryMappingImpl(
String name,
String sqlString,
List<NamedQueryParameterMapping> parameterMappings,
String resultSetMappingName,
Set<String> querySpaces,
Boolean cacheable,
String cacheRegion,
CacheMode cacheMode,
FlushMode flushMode,
Boolean readOnly,
LockOptions lockOptions,
Integer timeout,
Integer fetchSize,
String comment,
Map<String,Object> hints) {
super(
name,
parameterMappings,
cacheable,
cacheRegion,
cacheMode,
flushMode,
readOnly,
lockOptions,
timeout,
fetchSize,
comment,
hints
);
this.sqlString = sqlString;
this.resultSetMappingName = resultSetMappingName;
this.querySpaces = querySpaces;
}
@Override
public String getQueryString() {
return sqlString;
}
@Override
public String getResultSetMappingName() {
return resultSetMappingName;
}
@Override
public NamedNativeQueryMemento resolve(SessionFactoryImplementor factory) {
return new NamedNativeQueryMementoImpl(
getName(),
sqlString,
resultSetMappingName,
resolveParameterMappings( factory ),
querySpaces,
getCacheable(),
getCacheRegion(),
getCacheMode(),
getFlushMode(),
getReadOnly(),
getLockOptions(),
getTimeout(),
getFetchSize(),
getComment(),
getHints()
);
}
public static class Builder extends AbstractBuilder<Builder> {
private String sqlString;
private String resultSetMappingName;
private Class resultSetMappingClass;
public Builder(String name) {
super( name );
}
public Builder setSqlString(String sqlString) {
this.sqlString = sqlString;
return getThis();
}
public NamedNativeQueryMappingImpl build() {
return new NamedNativeQueryMappingImpl(
getName(),
sqlString,
getParameterMappings(),
resultSetMappingName,
getQuerySpaces(),
getCacheable(),
getCacheRegion(),
getCacheMode(),
getFlushMode(),
getReadOnly(),
getLockOptions(),
getTimeout(),
getFetchSize(),
getComment(),
getHints()
);
}
@Override
protected Builder getThis() {
return this;
}
@Override
protected NamedQueryParameterMapping createPositionalParameter(int i, Class javaType, ParameterMode mode) {
//noinspection Convert2Lambda
return new NamedQueryParameterMapping() {
@Override
@SuppressWarnings("unchecked")
public ParameterMemento resolve(SessionFactoryImplementor factory) {
return session -> new QueryParameterPositionalImpl(
i,
false,
factory.getMetamodel().getTypeConfiguration().standardBasicTypeForJavaType( javaType )
);
}
};
}
@Override
protected NamedQueryParameterMapping createNamedParameter(String name, Class javaType, ParameterMode mode) {
return null;
}
public Builder setResultSetMappingName(String resultSetMappingName) {
this.resultSetMappingName = resultSetMappingName;
return this;
}
}
}

View File

@ -22,12 +22,11 @@ import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryScalarReturnType;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmQueryParamType;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmSynchronizeType;
import org.hibernate.cfg.SecondPass;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.spi.NamedResultSetMappingMemento;
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
import org.hibernate.query.sql.spi.ResultSetMappingDescriptor;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
import org.hibernate.engine.spi.NamedQueryDefinitionBuilder;
import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder;
import org.hibernate.boot.spi.NamedNativeQueryMementoBuilder;
import org.hibernate.internal.util.StringHelper;
/**
@ -74,7 +73,7 @@ public class NamedQueryBinder {
);
}
context.getMetadataCollector().addNamedQuery(
new NamedQueryDefinitionBuilder()
new NamedHqlQueryMemento.Builder()
.setName( prefix + namedQueryBinding.getName() )
.setQuery( query )
.setComment( namedQueryBinding.getComment() )
@ -101,7 +100,7 @@ public class NamedQueryBinder {
JaxbHbmNamedNativeQueryType namedQueryBinding,
String prefix) {
final String queryName = prefix + namedQueryBinding.getName();
final NamedSQLQueryDefinitionBuilder builder = new NamedSQLQueryDefinitionBuilder()
final NamedNativeQueryMementoBuilder builder = new NamedNativeQueryMementoBuilder()
.setName( queryName )
.setComment( namedQueryBinding.getComment() )
.setCacheable( namedQueryBinding.isCacheable() )
@ -190,7 +189,7 @@ public class NamedQueryBinder {
private static boolean processNamedQueryContentItem(
Object content,
NamedSQLQueryDefinitionBuilder builder,
NamedNativeQueryMementoBuilder builder,
ImplicitResultSetMappingDefinition.Builder implicitResultSetMappingBuilder,
JaxbHbmNamedNativeQueryType namedQueryBinding,
HbmLocalMetadataBuildingContext context) {

View File

@ -0,0 +1,318 @@
/*
* 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.boot.spi;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.ParameterMode;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockOptions;
import org.hibernate.boot.internal.NamedNativeQueryMappingImpl;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.spi.ParameterMemento;
/**
* @author Steve Ebersole
*/
public abstract class AbstractNamedQueryMapping implements NamedQueryMapping {
private final String name;
private final List<? extends NamedQueryParameterMapping> parameterMappings;
private final Boolean cacheable;
private final String cacheRegion;
private final CacheMode cacheMode;
private final FlushMode flushMode;
private final Boolean readOnly;
private final LockOptions lockOptions;
private final Integer timeout;
private final Integer fetchSize;
private final String comment;
private final Map<String,Object> hints;
public AbstractNamedQueryMapping(
String name,
List<? extends NamedQueryParameterMapping> parameterMappings,
Boolean cacheable,
String cacheRegion,
CacheMode cacheMode,
FlushMode flushMode,
Boolean readOnly,
LockOptions lockOptions,
Integer timeout,
Integer fetchSize,
String comment,
Map<String,Object> hints) {
this.name = name;
this.parameterMappings = parameterMappings == null
? new ArrayList<>()
: new ArrayList<>( parameterMappings );
this.cacheable = cacheable;
this.cacheRegion = cacheRegion;
this.cacheMode = cacheMode;
this.flushMode = flushMode;
this.readOnly = readOnly;
this.lockOptions = lockOptions;
this.timeout = timeout;
this.fetchSize = fetchSize;
this.comment = comment;
this.hints = hints == null ? new HashMap<>() : new HashMap<>( hints );
}
@Override
public String getName() {
return name;
}
public Boolean getCacheable() {
return cacheable;
}
public String getCacheRegion() {
return cacheRegion;
}
public CacheMode getCacheMode() {
return cacheMode;
}
public FlushMode getFlushMode() {
return flushMode;
}
public Boolean getReadOnly() {
return readOnly;
}
public LockOptions getLockOptions() {
return lockOptions;
}
public Integer getTimeout() {
return timeout;
}
public Integer getFetchSize() {
return fetchSize;
}
public String getComment() {
return comment;
}
public Map<String, Object> getHints() {
return hints;
}
protected List<? extends ParameterMemento> resolveParameterMappings(SessionFactoryImplementor factory) {
final ArrayList<ParameterMemento> descriptors = new ArrayList<>();
parameterMappings.forEach( parameterMapping -> descriptors.add( parameterMapping.resolve( factory ) ) );
return descriptors;
}
protected static abstract class AbstractBuilder<T extends AbstractBuilder> {
private final String name;
private Set<String> querySpaces;
private Boolean cacheable;
private String cacheRegion;
private CacheMode cacheMode;
private FlushMode flushMode;
private Boolean readOnly;
private LockOptions lockOptions;
private Integer timeout;
private Integer fetchSize;
private String comment;
private Map<String,Object> hints;
public AbstractBuilder(String name) {
this.name = name;
}
public String getName() {
return name;
}
protected abstract T getThis();
public T addParameter(Class javaType, ParameterMode mode) {
return addParameter(
createPositionalParameter(
parameterMappings.size() + 1,
javaType,
mode
)
);
}
protected abstract NamedQueryParameterMapping createPositionalParameter(int i, Class javaType, ParameterMode mode);
public <P extends NamedQueryParameterMapping> T addParameter(P parameterMapping) {
if ( parameterMappings == null ) {
parameterMappings = new ArrayList<>();
}
parameterMappings.add( (P) parameterMapping );
return getThis();
}
public T addParameter(String name, Class javaType, ParameterMode mode) {
if ( parameterMappings == null ) {
parameterMappings = new ArrayList<>();
}
parameterMappings.add( createNamedParameter( name, javaType, mode ) );
return getThis();
}
protected abstract <P extends NamedQueryParameterMapping> P createNamedParameter(String name, Class javaType, ParameterMode mode);
public T addQuerySpaces(Set<String> querySpaces) {
if ( querySpaces == null || querySpaces.isEmpty() ) {
return getThis();
}
if ( this.querySpaces == null ) {
this.querySpaces = new HashSet<>();
}
this.querySpaces.addAll( querySpaces );
return getThis();
}
public T addQuerySpace(String space) {
if ( this.querySpaces == null ) {
this.querySpaces = new HashSet<>();
}
this.querySpaces.add( space );
return getThis();
}
public T setQuerySpaces(Set<String> spaces) {
this.querySpaces = spaces;
return getThis();
}
public T setCacheable(Boolean cacheable) {
this.cacheable = cacheable;
return getThis();
}
public T setCacheRegion(String cacheRegion) {
this.cacheRegion = cacheRegion;
return getThis();
}
public T setCacheMode(CacheMode cacheMode) {
this.cacheMode = cacheMode;
return getThis();
}
public T setLockOptions(LockOptions lockOptions) {
this.lockOptions = lockOptions;
return getThis();
}
public T setTimeout(Integer timeout) {
this.timeout = timeout;
return getThis();
}
public T setFlushMode(FlushMode flushMode) {
this.flushMode = flushMode;
return getThis();
}
public T setReadOnly(Boolean readOnly) {
this.readOnly = readOnly;
return getThis();
}
public T setFetchSize(Integer fetchSize) {
this.fetchSize = fetchSize;
return getThis();
}
public T setComment(String comment) {
this.comment = comment;
return getThis();
}
public Set<String> getQuerySpaces() {
return querySpaces;
}
public Boolean getCacheable() {
return cacheable;
}
public String getCacheRegion() {
return cacheRegion;
}
public CacheMode getCacheMode() {
return cacheMode;
}
public FlushMode getFlushMode() {
return flushMode;
}
public Boolean getReadOnly() {
return readOnly;
}
public LockOptions getLockOptions() {
return lockOptions;
}
public Integer getTimeout() {
return timeout;
}
public Integer getFetchSize() {
return fetchSize;
}
public String getComment() {
return comment;
}
protected List<? extends NamedQueryParameterMapping> getParameterMappings() {
return parameterMappings;
}
public void addHint(String name, Object value) {
if ( hints == null ) {
hints = new HashMap<>();
}
hints.put( name, value );
}
public Map<String, Object> getHints() {
return hints;
}
}
}

View File

@ -35,6 +35,7 @@ import org.hibernate.cfg.SecondPass;
import org.hibernate.cfg.UniqueConstraintHolder;
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
import org.hibernate.cfg.annotations.NamedProcedureCallDefinition;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.spi.NamedResultSetMappingMemento;
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
import org.hibernate.query.sql.spi.ResultSetMappingDescriptor;
@ -140,7 +141,7 @@ public interface InFlightMetadataCollector extends Mapping, MetadataImplementor
*
* @throws DuplicateMappingException If a query already exists with that name.
*/
void addNamedQuery(NamedHqlQueryMementoImpl query) throws DuplicateMappingException;
void addNamedQuery(NamedHqlQueryMapping query) throws DuplicateMappingException;
/**
* Adds metadata for a named SQL query to this repository.
@ -149,7 +150,7 @@ public interface InFlightMetadataCollector extends Mapping, MetadataImplementor
*
* @throws DuplicateMappingException If a query already exists with that name.
*/
void addNamedNativeQuery(NamedNativeQueryMemento query) throws DuplicateMappingException;
void addNamedNativeQuery(NamedNativeQueryMapping query) throws DuplicateMappingException;
/**
* Adds the metadata for a named SQL result set mapping to this repository.
@ -269,9 +270,9 @@ public interface InFlightMetadataCollector extends Mapping, MetadataImplementor
void addDefaultIdentifierGenerator(IdentifierGeneratorDefinition generatorDefinition);
void addDefaultQuery(NamedHqlQueryMementoImpl queryDefinition);
void addDefaultQuery(NamedHqlQueryMapping queryDefinition);
void addDefaultNamedNativeQuery(NamedSQLQueryDefinition query);
void addDefaultNamedNativeQuery(NamedNativeQueryMapping query);
void addDefaultResultSetMapping(ResultSetMappingDescriptor definition);

View File

@ -0,0 +1,26 @@
/*
* 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.boot.spi;
import java.util.List;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
/**
* Named query mapping for callable queries
*
* @author Steve Ebersole
* @author Gavin King
*/
public interface NamedCallableQueryMapping extends NamedQueryMapping {
List<String> getResultSetMappingNames();
List<Class> getResultSetMappingClasses();
@Override
NamedCallableQueryMemento resolve(SessionFactoryImplementor factory);
}

View File

@ -0,0 +1,23 @@
/*
* 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.boot.spi;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
/**
* Named query mapping for HQL queries
*
* @author Steve Ebersole
* @author Gavin King
*/
public interface NamedHqlQueryMapping extends NamedQueryMapping {
String getQueryString();
@Override
NamedHqlQueryMemento resolve(SessionFactoryImplementor factory);
}

View File

@ -0,0 +1,24 @@
/*
* 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.boot.spi;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
/**
* Named query mapping for native queries
*
* @author Steve Ebersole
* @author Gavin King
*/
public interface NamedNativeQueryMapping extends NamedQueryMapping {
String getQueryString();
String getResultSetMappingName();
@Override
NamedNativeQueryMemento resolve(SessionFactoryImplementor factory);
}

View File

@ -0,0 +1,186 @@
/*
* 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.boot.spi;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockOptions;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
/**
* Delegate used in creating named native-sql query mementos for queries defined in
* annotations, hbm.xml or orm.xml
*/
public class NamedNativeQueryMementoBuilder extends NamedHqlQueryMemento.Builder {
private NativeSQLQueryReturn[] queryReturns;
private Collection<String> querySpaces;
private boolean callable;
private String resultSetRef;
public NamedNativeQueryMementoBuilder() {
}
public NamedNativeQueryMementoBuilder(String name) {
super( name );
}
public NamedNativeQueryMementoBuilder setQueryReturns(NativeSQLQueryReturn[] queryReturns) {
this.queryReturns = queryReturns;
return this;
}
public NamedNativeQueryMementoBuilder setQueryReturns(List<NativeSQLQueryReturn> queryReturns) {
if ( queryReturns != null ) {
this.queryReturns = queryReturns.toArray( new NativeSQLQueryReturn[ queryReturns.size() ] );
}
else {
this.queryReturns = null;
}
return this;
}
public NamedNativeQueryMementoBuilder setQuerySpaces(List<String> querySpaces) {
this.querySpaces = querySpaces;
return this;
}
public NamedNativeQueryMementoBuilder setQuerySpaces(Collection<String> synchronizedQuerySpaces) {
this.querySpaces = synchronizedQuerySpaces;
return this;
}
public NamedNativeQueryMementoBuilder addSynchronizedQuerySpace(String table) {
if ( this.querySpaces == null ) {
this.querySpaces = new ArrayList<String>();
}
this.querySpaces.add( table );
return this;
}
public NamedNativeQueryMementoBuilder setResultSetRef(String resultSetRef) {
this.resultSetRef = resultSetRef;
return this;
}
public NamedNativeQueryMementoBuilder setCallable(boolean callable) {
this.callable = callable;
return this;
}
@Override
public NamedNativeQueryMementoBuilder setName(String name) {
return (NamedNativeQueryMementoBuilder) super.setName( name );
}
@Override
public NamedNativeQueryMementoBuilder setQuery(String query) {
return (NamedNativeQueryMementoBuilder) super.setQuery( query );
}
@Override
public NamedNativeQueryMementoBuilder setCacheable(boolean cacheable) {
return (NamedNativeQueryMementoBuilder) super.setCacheable( cacheable );
}
@Override
public NamedNativeQueryMementoBuilder setCacheRegion(String cacheRegion) {
return (NamedNativeQueryMementoBuilder) super.setCacheRegion( cacheRegion );
}
@Override
public NamedNativeQueryMementoBuilder setTimeout(Integer timeout) {
return (NamedNativeQueryMementoBuilder) super.setTimeout( timeout );
}
@Override
public NamedNativeQueryMementoBuilder setFetchSize(Integer fetchSize) {
return (NamedNativeQueryMementoBuilder) super.setFetchSize( fetchSize );
}
@Override
public NamedNativeQueryMementoBuilder setFlushMode(FlushMode flushMode) {
return (NamedNativeQueryMementoBuilder) super.setFlushMode( flushMode );
}
@Override
public NamedNativeQueryMementoBuilder setCacheMode(CacheMode cacheMode) {
return (NamedNativeQueryMementoBuilder) super.setCacheMode( cacheMode );
}
@Override
public NamedNativeQueryMementoBuilder setReadOnly(boolean readOnly) {
return (NamedNativeQueryMementoBuilder) super.setReadOnly( readOnly );
}
@Override
public NamedNativeQueryMementoBuilder setComment(String comment) {
return (NamedNativeQueryMementoBuilder) super.setComment( comment );
}
@Override
public NamedNativeQueryMementoBuilder addParameterType(String name, String typeName) {
return (NamedNativeQueryMementoBuilder) super.addParameterType( name, typeName );
}
@Override
public NamedNativeQueryMementoBuilder setParameterTypes(Map parameterTypes) {
return (NamedNativeQueryMementoBuilder) super.setParameterTypes( parameterTypes );
}
@Override
public NamedNativeQueryMementoBuilder setLockOptions(LockOptions lockOptions) {
// todo : maybe throw an exception here instead? since this is not valid for native-0sql queries?
return (NamedNativeQueryMementoBuilder) super.setLockOptions( lockOptions );
}
@Override
public NamedNativeQueryMementoBuilder setFirstResult(Integer firstResult) {
return (NamedNativeQueryMementoBuilder) super.setFirstResult( firstResult );
}
@Override
public NamedNativeQueryMementoBuilder setMaxResults(Integer maxResults) {
return (NamedNativeQueryMementoBuilder) super.setMaxResults( maxResults );
}
@Override
public NamedNativeQueryMemento createNamedQueryDefinition() {
return new NamedSQLQueryDefinition(
name,
query,
cacheable,
cacheRegion,
timeout,
fetchSize,
flushMode,
cacheMode,
readOnly,
comment,
parameterTypes,
firstResult,
maxResults,
resultSetRef,
querySpacesCopy(),
callable,
queryReturns
);
}
private List<String> querySpacesCopy() {
return querySpaces == null
? null
: new ArrayList<String>( querySpaces );
}
}

View File

@ -0,0 +1,29 @@
/*
* 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.boot.spi;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.spi.NamedQueryMemento;
/**
* Common attributes shared across the mapping of named HQL, native
* and "callable" queries defined in annotations, orm.xml and hbm.xml
*
* @author Steve Ebersole
* @author Gavin King
*/
public interface NamedQueryMapping {
/**
* The name of the query
*/
String getName();
/**
* Resolve the mapping definition into its run-time memento form
*/
NamedQueryMemento resolve(SessionFactoryImplementor factory);
}

View File

@ -0,0 +1,23 @@
/*
* 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.boot.spi;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.spi.ParameterMemento;
/**
* Describes a parameter defined in the mapping of a {@link NamedQueryMapping}
*
* @author Steve Ebersole
* @author Gavin King
*/
public interface NamedQueryParameterMapping {
/**
* Resolve the mapping definition into its run-time memento form
*/
ParameterMemento resolve(SessionFactoryImplementor factory);
}

View File

@ -23,7 +23,7 @@ import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.procedure.NamedCallableQueryMemento;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.procedure.internal.NamedCallableQueryMementoImpl;
import org.hibernate.procedure.internal.Util;
import org.hibernate.procedure.spi.ParameterStrategy;
@ -49,7 +49,7 @@ public class NamedProcedureCallDefinition {
NamedProcedureCallDefinition(NamedStoredProcedureQuery annotation) {
this.registeredName = annotation.name();
this.procedureName = annotation.procedureName();
this.hints = new QueryHintDefinition( annotation.hints() ).getHintsMap();
this.hints = new QueryHintDefinition( queryName, annotation.hints() ).getHintsMap();
this.resultClasses = annotation.resultClasses();
this.resultSetMappings = annotation.resultSetMappings();

View File

@ -23,15 +23,19 @@ import org.hibernate.LockMode;
import org.hibernate.annotations.CacheModeType;
import org.hibernate.annotations.FlushModeType;
import org.hibernate.annotations.QueryHints;
import org.hibernate.boot.internal.NamedHqlQueryMappingImpl;
import org.hibernate.boot.internal.NamedNativeQueryMappingImpl;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.boot.spi.NamedHqlQueryMapping;
import org.hibernate.boot.spi.NamedNativeQueryMapping;
import org.hibernate.cfg.BinderHelper;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn;
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
import org.hibernate.engine.spi.NamedQueryDefinitionBuilder;
import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder;
import org.hibernate.boot.spi.NamedNativeQueryMementoBuilder;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.jboss.logging.Logger;
@ -47,36 +51,40 @@ public abstract class QueryBinder {
NamedQuery queryAnn,
MetadataBuildingContext context,
boolean isDefault) {
if ( queryAnn == null ) return;
if ( queryAnn == null ) {
return;
}
if ( BinderHelper.isEmptyAnnotationValue( queryAnn.name() ) ) {
throw new AnnotationException( "A named query must have a name when used in class or package level" );
}
//EJBQL Query
QueryHintDefinition hints = new QueryHintDefinition( queryAnn.hints() );
String queryName = queryAnn.query();
NamedHqlQueryMementoImpl queryDefinition = new NamedQueryDefinitionBuilder( queryAnn.name() )
.setLockOptions( hints.determineLockOptions( queryAnn ) )
.setQuery( queryName )
.setCacheable( hints.getBoolean( queryName, QueryHints.CACHEABLE ) )
.setCacheRegion( hints.getString( queryName, QueryHints.CACHE_REGION ) )
.setTimeout( hints.getTimeout( queryName ) )
.setFetchSize( hints.getInteger( queryName, QueryHints.FETCH_SIZE ) )
.setFlushMode( hints.getFlushMode( queryName ) )
.setCacheMode( hints.getCacheMode( queryName ) )
.setReadOnly( hints.getBoolean( queryName, QueryHints.READ_ONLY ) )
.setComment( hints.getString( queryName, QueryHints.COMMENT ) )
.setParameterTypes( null )
.createNamedQueryDefinition();
if ( isDefault ) {
context.getMetadataCollector().addDefaultQuery( queryDefinition );
}
else {
context.getMetadataCollector().addNamedQuery( queryDefinition );
}
final String queryName = queryAnn.name();
final String queryString = queryAnn.query();
if ( LOG.isDebugEnabled() ) {
LOG.debugf( "Binding named query: %s => %s", queryDefinition.getName(), queryDefinition.getQueryString() );
LOG.debugf( "Binding named query: %s => %s", queryName, queryString );
}
final QueryHintDefinition hints = new QueryHintDefinition( queryName, queryAnn.hints() );
final NamedHqlQueryMapping queryMapping = new NamedHqlQueryMappingImpl.Builder( queryName, queryString )
.setCacheable( hints.getCacheability() )
.setCacheMode( hints.getCacheMode() )
.setCacheRegion( hints.getString( QueryHints.CACHE_REGION ) )
.setTimeout( hints.getTimeout() )
.setFetchSize( hints.getInteger( QueryHints.FETCH_SIZE ) )
.setFlushMode( hints.getFlushMode() )
.setReadOnly( hints.getBoolean( QueryHints.READ_ONLY ) )
.setLockOptions( hints.determineLockOptions( queryAnn ) )
.setComment( hints.getString( QueryHints.COMMENT ) )
.build();
if ( isDefault ) {
context.getMetadataCollector().addDefaultQuery( queryMapping );
}
else {
context.getMetadataCollector().addNamedQuery( queryMapping );
}
}
@ -86,28 +94,35 @@ public abstract class QueryBinder {
NamedNativeQuery queryAnn,
MetadataBuildingContext context,
boolean isDefault) {
if ( queryAnn == null ) return;
//ResultSetMappingDefinition mappingDefinition = mappings.getResultSetMapping( queryAnn.resultSetMapping() );
if ( queryAnn == null ) {
return;
}
if ( BinderHelper.isEmptyAnnotationValue( queryAnn.name() ) ) {
throw new AnnotationException( "A named query must have a name when used in class or package level" );
}
final String queryName = queryAnn.name();
final String queryString = queryAnn.query();
//ResultSetMappingDefinition mappingDefinition = mappings.getResultSetMapping( queryAnn.resultSetMapping() );
String resultSetMapping = queryAnn.resultSetMapping();
QueryHintDefinition hints = new QueryHintDefinition( queryAnn.hints() );
String queryName = queryAnn.query();
NamedSQLQueryDefinitionBuilder builder = new NamedSQLQueryDefinitionBuilder( queryAnn.name() )
.setQuery( queryName )
QueryHintDefinition hints = new QueryHintDefinition( queryName, queryAnn.hints() );
new NamedNativeQueryMappingImpl.Builder( queryName )
.setSqlString( queryString )
// todo (6.0) : add support for supplying synchronized query-spaces
.setQuerySpaces( null )
.setCacheable( hints.getBoolean( queryName, QueryHints.CACHEABLE ) )
.setCacheRegion( hints.getString( queryName, QueryHints.CACHE_REGION ) )
.setTimeout( hints.getTimeout( queryName ) )
.setFetchSize( hints.getInteger( queryName, QueryHints.FETCH_SIZE ) )
.setFlushMode( hints.getFlushMode( queryName ) )
.setCacheMode( hints.getCacheMode( queryName ) )
.setReadOnly( hints.getBoolean( queryName, QueryHints.READ_ONLY ) )
.setCacheable( hints.getCacheability() )
.setCacheMode( hints.getCacheMode() )
.setCacheRegion( hints.getString( QueryHints.CACHE_REGION ) )
.setTimeout( hints.getTimeout() )
.setFetchSize( hints.getInteger( QueryHints.FETCH_SIZE ) )
.setFlushMode( hints.getFlushMode() )
.setReadOnly( hints.getBoolean( QueryHints.READ_ONLY ) )
.setComment( hints.getString( queryName, QueryHints.COMMENT ) )
.setParameterTypes( null )
.setCallable( hints.getBoolean( queryName, QueryHints.CALLABLE ) );
.bu
if ( !BinderHelper.isEmptyAnnotationValue( resultSetMapping ) ) {
//sql result set usage
@ -124,9 +139,9 @@ public abstract class QueryBinder {
else {
builder.setQueryReturns( new NativeSQLQueryReturn[0] );
}
NamedSQLQueryDefinition query = builder.createNamedQueryDefinition();
if ( isDefault ) {
context.getMetadataCollector().addDefaultNamedNativeQuery( query );
}
@ -154,7 +169,7 @@ public abstract class QueryBinder {
String resultSetMapping = queryAnn.resultSetMapping();
if ( !BinderHelper.isEmptyAnnotationValue( resultSetMapping ) ) {
//sql result set usage
query = new NamedSQLQueryDefinitionBuilder().setName( queryAnn.name() )
query = new NamedNativeQueryMementoBuilder().setName( queryAnn.name() )
.setQuery( queryAnn.query() )
.setResultSetRef( resultSetMapping )
.setQuerySpaces( null )
@ -179,7 +194,7 @@ public abstract class QueryBinder {
//FIXME should be done in a second pass due to entity name?
final NativeSQLQueryRootReturn entityQueryReturn =
new NativeSQLQueryRootReturn( "alias1", queryAnn.resultClass().getName(), new HashMap(), LockMode.READ );
query = new NamedSQLQueryDefinitionBuilder().setName( queryAnn.name() )
query = new NamedNativeQueryMementoBuilder().setName( queryAnn.name() )
.setQuery( queryAnn.query() )
.setQueryReturns( new NativeSQLQueryReturn[] {entityQueryReturn} )
.setQuerySpaces( null )
@ -257,7 +272,7 @@ public abstract class QueryBinder {
FlushMode flushMode;
flushMode = getFlushMode( queryAnn.flushMode() );
NamedHqlQueryMementoImpl query = new NamedQueryDefinitionBuilder().setName( queryAnn.name() )
NamedHqlQueryMementoImpl query = new NamedHqlQueryMemento.Builder().setName( queryAnn.name() )
.setQuery( queryAnn.query() )
.setCacheable( queryAnn.cacheable() )
.setCacheRegion(

View File

@ -21,19 +21,23 @@ import org.hibernate.LockOptions;
import org.hibernate.MappingException;
import org.hibernate.annotations.QueryHints;
import org.hibernate.internal.util.LockModeConverter;
import org.hibernate.internal.util.config.ConfigurationException;
import org.hibernate.internal.util.config.ConfigurationHelper;
/**
* @author Strong Liu <stliu@hibernate.org>
*/
public class QueryHintDefinition {
private final String queryName;
private final Map<String, Object> hintsMap;
public QueryHintDefinition(final QueryHint[] hints) {
public QueryHintDefinition(String queryName, final QueryHint[] hints) {
this.queryName = queryName;
if ( hints == null || hints.length == 0 ) {
hintsMap = Collections.emptyMap();
}
else {
final Map<String, Object> hintsMap = new HashMap<String, Object>();
final Map<String, Object> hintsMap = new HashMap<>();
for ( QueryHint hint : hints ) {
hintsMap.put( hint.name(), hint.value() );
}
@ -42,31 +46,74 @@ public class QueryHintDefinition {
}
public CacheMode getCacheMode(String query) {
String hitName = QueryHints.CACHE_MODE;
String value =(String) hintsMap.get( hitName );
if ( value == null ) {
return null;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Generic access
public Map<String, Object> getHintsMap() {
return hintsMap;
}
public String getString(String hintName) {
return (String) hintsMap.get( hintName );
}
public boolean getBoolean(String hintName) {
try {
return CacheMode.interpretExternalSetting( value );
return ConfigurationHelper.getBoolean( hintName, hintsMap );
}
catch ( MappingException e ) {
throw new AnnotationException( "Unknown CacheMode in hint: " + query + ":" + hitName, e );
catch (Exception e) {
throw new AnnotationException( "Named query hint [" + hintName + "] is not a boolean: " + queryName, e );
}
}
public FlushMode getFlushMode(String query) {
String hitName = QueryHints.FLUSH_MODE;
String value =(String) hintsMap.get( hitName );
if ( value == null ) {
return null;
}
public Integer getInteger(String hintName) {
try {
return FlushMode.interpretExternalSetting( value );
return ConfigurationHelper.getInteger( hintName, hintsMap );
}
catch ( MappingException e ) {
throw new AnnotationException( "Unknown FlushMode in hint: " + query + ":" + hitName, e );
catch (Exception e) {
throw new AnnotationException( "Named query hint [" + hintName + "] is not an integer: " + queryName, e );
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Specialized access
public Integer getTimeout() {
final Integer jpaTimeout = getInteger( QueryHints.TIMEOUT_JPA );
if ( jpaTimeout != null ) {
// convert milliseconds to seconds
return (int) Math.round( jpaTimeout.doubleValue() / 1000.0 );
}
return getInteger( QueryHints.TIMEOUT_HIBERNATE );
}
public boolean getCacheability() {
return getBoolean( QueryHints.CACHEABLE );
}
public CacheMode getCacheMode() {
final String value = getString( QueryHints.CACHE_MODE );
try {
return value == null
? null
: CacheMode.interpretExternalSetting( value );
}
catch (Exception e) {
throw new AnnotationException( "Unable to interpret CacheMode in named query hint: " + queryName, e );
}
}
public FlushMode getFlushMode() {
final String value = getString( QueryHints.FLUSH_MODE );
try {
return value == null
? null
: FlushMode.interpretExternalSetting( value );
}
catch (MappingException e) {
throw new AnnotationException( "Unable to interpret FlushMode in named query hint: " + queryName, e );
}
}
@ -84,58 +131,10 @@ public class QueryHintDefinition {
}
}
public boolean getBoolean(String query, String hintName) {
String value =(String) hintsMap.get( hintName );
if ( value == null ) {
return false;
}
if ( value.equalsIgnoreCase( "true" ) ) {
return true;
}
else if ( value.equalsIgnoreCase( "false" ) ) {
return false;
}
else {
throw new AnnotationException( "Not a boolean in hint: " + query + ":" + hintName );
}
}
public String getString(String query, String hintName) {
return (String) hintsMap.get( hintName );
}
public Integer getInteger(String query, String hintName) {
String value = (String) hintsMap.get( hintName );
if ( value == null ) {
return null;
}
try {
return Integer.decode( value );
}
catch ( NumberFormatException nfe ) {
throw new AnnotationException( "Not an integer in hint: " + query + ":" + hintName, nfe );
}
}
public Integer getTimeout(String queryName) {
Integer timeout = getInteger( queryName, QueryHints.TIMEOUT_JPA );
if ( timeout != null ) {
// convert milliseconds to seconds
timeout = (int) Math.round( timeout.doubleValue() / 1000.0 );
}
else {
// timeout is already in seconds
timeout = getInteger( queryName, QueryHints.TIMEOUT_HIBERNATE );
}
return timeout;
}
public LockOptions determineLockOptions(NamedQuery namedQueryAnnotation) {
LockModeType lockModeType = namedQueryAnnotation.lockMode();
Integer lockTimeoutHint = getInteger( namedQueryAnnotation.name(), "javax.persistence.lock.timeout" );
Boolean followOnLocking = getBoolean( namedQueryAnnotation.name(), QueryHints.FOLLOW_ON_LOCKING );
Integer lockTimeoutHint = getInteger( "javax.persistence.lock.timeout" );
Boolean followOnLocking = getBoolean( QueryHints.FOLLOW_ON_LOCKING );
return determineLockOptions(lockModeType, lockTimeoutHint, followOnLocking);
}
@ -150,8 +149,4 @@ public class QueryHintDefinition {
return lockOptions;
}
public Map<String, Object> getHintsMap() {
return hintsMap;
}
}

View File

@ -1,138 +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.engine.spi;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockOptions;
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
import org.hibernate.query.sql.internal.NamedNativeQueryMementoImpl;
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
public class NamedQueryDefinitionBuilder {
protected String name;
protected String query;
protected boolean cacheable;
protected String cacheRegion;
protected Integer timeout;
protected Integer fetchSize;
protected FlushMode flushMode;
protected CacheMode cacheMode;
protected boolean readOnly;
protected String comment;
protected Map parameterTypes;
protected LockOptions lockOptions;
protected Integer firstResult;
protected Integer maxResults;
public NamedQueryDefinitionBuilder() {
}
public NamedQueryDefinitionBuilder(String name) {
this.name = name;
}
public NamedQueryDefinitionBuilder setName(String name) {
this.name = name;
return this;
}
public NamedQueryDefinitionBuilder setQuery(String query) {
this.query = query;
return this;
}
public NamedQueryDefinitionBuilder setCacheable(boolean cacheable) {
this.cacheable = cacheable;
return this;
}
public NamedQueryDefinitionBuilder setCacheRegion(String cacheRegion) {
this.cacheRegion = cacheRegion;
return this;
}
public NamedQueryDefinitionBuilder setTimeout(Integer timeout) {
this.timeout = timeout;
return this;
}
public NamedQueryDefinitionBuilder setFetchSize(Integer fetchSize) {
this.fetchSize = fetchSize;
return this;
}
public NamedQueryDefinitionBuilder setFlushMode(FlushMode flushMode) {
this.flushMode = flushMode;
return this;
}
public NamedQueryDefinitionBuilder setCacheMode(CacheMode cacheMode) {
this.cacheMode = cacheMode;
return this;
}
public NamedQueryDefinitionBuilder setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
return this;
}
public NamedQueryDefinitionBuilder setComment(String comment) {
this.comment = comment;
return this;
}
public NamedQueryDefinitionBuilder addParameterType(String name, String typeName) {
if ( this.parameterTypes == null ) {
this.parameterTypes = new HashMap();
}
this.parameterTypes.put( name, typeName );
return this;
}
public NamedQueryDefinitionBuilder setParameterTypes(Map parameterTypes) {
this.parameterTypes = parameterTypes;
return this;
}
public NamedQueryDefinitionBuilder setLockOptions(LockOptions lockOptions) {
this.lockOptions = lockOptions;
return this;
}
public NamedQueryDefinitionBuilder setFirstResult(Integer firstResult) {
this.firstResult = firstResult;
return this;
}
public NamedQueryDefinitionBuilder setMaxResults(Integer maxResults) {
this.maxResults = maxResults;
return this;
}
public NamedNativeQueryMemento createNamedQueryDefinition() {
return new NamedNativeQueryMementoImpl(
name,
query,
cacheable,
cacheRegion,
timeout,
lockOptions,
fetchSize,
flushMode,
cacheMode,
readOnly,
comment,
parameterTypes,
firstResult,
maxResults
);
}
}

View File

@ -1,182 +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.engine.spi;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockOptions;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
import org.hibernate.query.spi.NamedResultSetMappingMemento;
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
public class NamedSQLQueryDefinitionBuilder extends NamedQueryDefinitionBuilder {
private NativeSQLQueryReturn[] queryReturns;
private Collection<String> querySpaces;
private boolean callable;
private String resultSetRef;
public NamedSQLQueryDefinitionBuilder() {
}
public NamedSQLQueryDefinitionBuilder(String name) {
super( name );
}
public NamedSQLQueryDefinitionBuilder setQueryReturns(NativeSQLQueryReturn[] queryReturns) {
this.queryReturns = queryReturns;
return this;
}
public NamedSQLQueryDefinitionBuilder setQueryReturns(List<NativeSQLQueryReturn> queryReturns) {
if ( queryReturns != null ) {
this.queryReturns = queryReturns.toArray( new NativeSQLQueryReturn[ queryReturns.size() ] );
}
else {
this.queryReturns = null;
}
return this;
}
public NamedSQLQueryDefinitionBuilder setQuerySpaces(List<String> querySpaces) {
this.querySpaces = querySpaces;
return this;
}
public NamedSQLQueryDefinitionBuilder setQuerySpaces(Collection<String> synchronizedQuerySpaces) {
this.querySpaces = synchronizedQuerySpaces;
return this;
}
public NamedSQLQueryDefinitionBuilder addSynchronizedQuerySpace(String table) {
if ( this.querySpaces == null ) {
this.querySpaces = new ArrayList<String>();
}
this.querySpaces.add( table );
return this;
}
public NamedSQLQueryDefinitionBuilder setResultSetRef(String resultSetRef) {
this.resultSetRef = resultSetRef;
return this;
}
public NamedSQLQueryDefinitionBuilder setCallable(boolean callable) {
this.callable = callable;
return this;
}
@Override
public NamedSQLQueryDefinitionBuilder setName(String name) {
return (NamedSQLQueryDefinitionBuilder) super.setName( name );
}
@Override
public NamedSQLQueryDefinitionBuilder setQuery(String query) {
return (NamedSQLQueryDefinitionBuilder) super.setQuery( query );
}
@Override
public NamedSQLQueryDefinitionBuilder setCacheable(boolean cacheable) {
return (NamedSQLQueryDefinitionBuilder) super.setCacheable( cacheable );
}
@Override
public NamedSQLQueryDefinitionBuilder setCacheRegion(String cacheRegion) {
return (NamedSQLQueryDefinitionBuilder) super.setCacheRegion( cacheRegion );
}
@Override
public NamedSQLQueryDefinitionBuilder setTimeout(Integer timeout) {
return (NamedSQLQueryDefinitionBuilder) super.setTimeout( timeout );
}
@Override
public NamedSQLQueryDefinitionBuilder setFetchSize(Integer fetchSize) {
return (NamedSQLQueryDefinitionBuilder) super.setFetchSize( fetchSize );
}
@Override
public NamedSQLQueryDefinitionBuilder setFlushMode(FlushMode flushMode) {
return (NamedSQLQueryDefinitionBuilder) super.setFlushMode( flushMode );
}
@Override
public NamedSQLQueryDefinitionBuilder setCacheMode(CacheMode cacheMode) {
return (NamedSQLQueryDefinitionBuilder) super.setCacheMode( cacheMode );
}
@Override
public NamedSQLQueryDefinitionBuilder setReadOnly(boolean readOnly) {
return (NamedSQLQueryDefinitionBuilder) super.setReadOnly( readOnly );
}
@Override
public NamedSQLQueryDefinitionBuilder setComment(String comment) {
return (NamedSQLQueryDefinitionBuilder) super.setComment( comment );
}
@Override
public NamedSQLQueryDefinitionBuilder addParameterType(String name, String typeName) {
return (NamedSQLQueryDefinitionBuilder) super.addParameterType( name, typeName );
}
@Override
public NamedSQLQueryDefinitionBuilder setParameterTypes(Map parameterTypes) {
return (NamedSQLQueryDefinitionBuilder) super.setParameterTypes( parameterTypes );
}
@Override
public NamedSQLQueryDefinitionBuilder setLockOptions(LockOptions lockOptions) {
// todo : maybe throw an exception here instead? since this is not valid for native-0sql queries?
return (NamedSQLQueryDefinitionBuilder) super.setLockOptions( lockOptions );
}
@Override
public NamedSQLQueryDefinitionBuilder setFirstResult(Integer firstResult) {
return (NamedSQLQueryDefinitionBuilder) super.setFirstResult( firstResult );
}
@Override
public NamedSQLQueryDefinitionBuilder setMaxResults(Integer maxResults) {
return (NamedSQLQueryDefinitionBuilder) super.setMaxResults( maxResults );
}
@Override
public NamedNativeQueryMemento createNamedQueryDefinition() {
return new NamedSQLQueryDefinition(
name,
query,
cacheable,
cacheRegion,
timeout,
fetchSize,
flushMode,
cacheMode,
readOnly,
comment,
parameterTypes,
firstResult,
maxResults,
resultSetRef,
querySpacesCopy(),
callable,
queryReturns
);
}
private List<String> querySpacesCopy() {
return querySpaces == null
? null
: new ArrayList<String>( querySpaces );
}
}

View File

@ -69,7 +69,7 @@ import org.hibernate.jpa.spi.NativeQueryTupleTransformer;
import org.hibernate.jpa.spi.TupleBuilderTransformer;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.procedure.ProcedureCall;
import org.hibernate.procedure.NamedCallableQueryMemento;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.procedure.internal.ProcedureCallImpl;
import org.hibernate.query.ParameterMetadata;
import org.hibernate.query.Query;

View File

@ -73,12 +73,12 @@ import org.hibernate.engine.jndi.spi.JndiService;
import org.hibernate.engine.profile.Association;
import org.hibernate.engine.profile.Fetch;
import org.hibernate.engine.profile.FetchProfile;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.spi.QueryPlanCache;
import org.hibernate.engine.query.spi.ReturnMetadata;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
import org.hibernate.engine.spi.NamedQueryDefinitionBuilder;
import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder;
import org.hibernate.boot.spi.NamedNativeQueryMementoBuilder;
import org.hibernate.engine.spi.SessionBuilderImplementor;
import org.hibernate.engine.spi.SessionEventListenerManager;
import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -894,8 +894,8 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
);
}
private NamedSQLQueryDefinition extractSqlQueryDefinition(NativeQuery nativeSqlQuery, String name) {
final NamedSQLQueryDefinitionBuilder builder = new NamedSQLQueryDefinitionBuilder( name );
private NamedSQLQueryDefinition extractSqlQueryDefinition(org.hibernate.query.NativeQuery nativeSqlQuery, String name) {
final NamedNativeQueryMementoBuilder builder = new NamedNativeQueryMementoBuilder( name );
fillInNamedQueryBuilder( builder, nativeSqlQuery );
builder.setCallable( nativeSqlQuery.isCallable() )
.setQuerySpaces( nativeSqlQuery.getSynchronizedQuerySpaces() )
@ -904,14 +904,14 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
}
private NamedHqlQueryMementoImpl extractHqlQueryDefinition(org.hibernate.query.Query hqlQuery, String name) {
final NamedQueryDefinitionBuilder builder = new NamedQueryDefinitionBuilder( name );
final NamedHqlQueryMemento.Builder builder = new NamedHqlQueryMemento.Builder( name );
fillInNamedQueryBuilder( builder, hqlQuery );
// LockOptions only valid for HQL/JPQL queries...
builder.setLockOptions( hqlQuery.getLockOptions().makeCopy() );
return builder.createNamedQueryDefinition();
}
private void fillInNamedQueryBuilder(NamedQueryDefinitionBuilder builder, org.hibernate.query.Query query) {
private void fillInNamedQueryBuilder(NamedHqlQueryMemento.Builder builder, org.hibernate.query.Query query) {
builder.setQuery( query.getQueryString() )
.setComment( query.getComment() )
.setCacheable( query.isCacheable() )

View File

@ -158,7 +158,7 @@ import org.hibernate.persister.entity.MultiLoadOptions;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.procedure.ProcedureCall;
import org.hibernate.procedure.NamedCallableQueryMemento;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.procedure.UnknownSqlResultSetMappingException;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;

View File

@ -9,7 +9,6 @@ package org.hibernate.procedure;
import javax.persistence.ParameterMode;
import javax.persistence.TemporalType;
import org.hibernate.query.QueryParameter;
import org.hibernate.query.procedure.ProcedureParameter;
import org.hibernate.type.Type;
@ -72,8 +71,11 @@ public interface ParameterRegistration<T> extends ProcedureParameter<T> {
* The (global) default this setting is defined by {@link org.hibernate.cfg.AvailableSettings#PROCEDURE_NULL_PARAM_PASSING}
*
* @param enabled {@code true} indicates that the NULL should be passed; {@code false} indicates it should not.
*
* @deprecated (since 6.0) : see {@link #isPassNullsEnabled}
*/
@Override
@Deprecated
void enablePassingNulls(boolean enabled);
/**

View File

@ -14,6 +14,7 @@ import javax.persistence.StoredProcedureQuery;
import org.hibernate.BasicQueryContract;
import org.hibernate.MappingException;
import org.hibernate.SynchronizeableQuery;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.query.CommonQueryContract;
/**

View File

@ -11,53 +11,73 @@ import java.util.Map;
import java.util.Set;
import javax.persistence.ParameterMode;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockOptions;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.procedure.ProcedureCall;
import org.hibernate.procedure.NamedCallableQueryMemento;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.procedure.spi.ParameterRegistrationImplementor;
import org.hibernate.procedure.spi.ParameterStrategy;
import org.hibernate.query.QueryParameter;
import org.hibernate.query.spi.AbstractNamedQueryMemento;
import org.hibernate.query.spi.ParameterMemento;
import org.hibernate.type.Type;
/**
* Implementation of ProcedureCallMemento
* Implementation of NamedCallableQueryMemento
*
* @author Steve Ebersole
*/
public class NamedCallableQueryMementoImpl implements NamedCallableQueryMemento {
private final String procedureName;
private final NativeSQLQueryReturn[] queryReturns;
public class NamedCallableQueryMementoImpl extends AbstractNamedQueryMemento implements NamedCallableQueryMemento {
private final String callableName;
private final ParameterStrategy parameterStrategy;
private final List<ParameterMemento> parameterDeclarations;
private final Class[] resultClasses;
private final String[] resultSetMappingNames;
private final Set<String> querySpaces;
private final Set<String> synchronizedQuerySpaces;
private final Map<String, Object> hintsMap;
/**
* Constructs a ProcedureCallImpl
*
* @param procedureName The name of the procedure to be called
* @param queryReturns The result mappings
* @param parameterStrategy Are parameters named or positional?
* @param parameterDeclarations The parameters registrations
* @param synchronizedQuerySpaces Any query spaces to synchronize on execution
* @param hintsMap Map of JPA query hints
*/
public NamedCallableQueryMementoImpl(
String procedureName,
NativeSQLQueryReturn[] queryReturns,
String name,
String callableName,
ParameterStrategy parameterStrategy,
List<ParameterMemento> parameterDeclarations,
Set<String> synchronizedQuerySpaces,
Map<String, Object> hintsMap) {
this.procedureName = procedureName;
this.queryReturns = queryReturns;
List<CallableParameterMemento> parameterMementos,
Class[] resultClasses,
String[] resultSetMappingNames,
Set<String> querySpaces,
Boolean cacheable,
String cacheRegion,
CacheMode cacheMode,
FlushMode flushMode,
Boolean readOnly,
LockOptions lockOptions,
Integer timeout,
Integer fetchSize,
String comment,
Map<String, Object> hints) {
super(
name,
parameterMementos,
cacheable,
cacheRegion,
cacheMode,
flushMode,
readOnly,
lockOptions,
timeout,
fetchSize,
comment,
hints
);
this.callableName = callableName;
this.parameterStrategy = parameterStrategy;
this.parameterDeclarations = parameterDeclarations;
this.synchronizedQuerySpaces = synchronizedQuerySpaces;
this.hintsMap = hintsMap;
this.resultClasses = resultClasses;
this.resultSetMappingNames = resultSetMappingNames;
this.querySpaces = querySpaces;
}
@Override
@ -65,8 +85,8 @@ public class NamedCallableQueryMementoImpl implements NamedCallableQueryMemento
return new ProcedureCallImpl( session, this );
}
public String getProcedureName() {
return procedureName;
public String getCallableName() {
return callableName;
}
public NativeSQLQueryReturn[] getQueryReturns() {
@ -93,7 +113,7 @@ public class NamedCallableQueryMementoImpl implements NamedCallableQueryMemento
/**
* A "disconnected" copy of the metadata for a parameter, that can be used in ProcedureCallMementoImpl.
*/
public static class ParameterMemento {
public static class CallableParameterMemento implements ParameterMemento {
private final Integer position;
private final String name;
private final ParameterMode mode;
@ -111,7 +131,7 @@ public class NamedCallableQueryMementoImpl implements NamedCallableQueryMemento
* @param hibernateType The Hibernate Type.
* @param passNulls Should NULL values to passed to the database?
*/
public ParameterMemento(
public CallableParameterMemento(
int position,
String name,
ParameterMode mode,
@ -150,6 +170,11 @@ public class NamedCallableQueryMementoImpl implements NamedCallableQueryMemento
return passNulls;
}
@Override
public QueryParameter toQueryParameter(SharedSessionContractImplementor session) {
return null;
}
/**
* Build a ParameterMemento from the given parameter registration
*

View File

@ -39,7 +39,7 @@ import org.hibernate.procedure.NoSuchParameterException;
import org.hibernate.procedure.ParameterRegistration;
import org.hibernate.procedure.ParameterStrategyException;
import org.hibernate.procedure.ProcedureCall;
import org.hibernate.procedure.NamedCallableQueryMemento;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.procedure.ProcedureOutputs;
import org.hibernate.procedure.spi.ParameterRegistrationImplementor;
import org.hibernate.procedure.spi.ParameterStrategy;

View File

@ -1,10 +1,10 @@
/*
* 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>.
* 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.procedure;
package org.hibernate.procedure.spi;
import java.util.Map;
@ -12,6 +12,8 @@ import org.hibernate.Incubating;
import org.hibernate.Session;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.procedure.ProcedureCall;
import org.hibernate.query.spi.NamedQueryMemento;
/**
* Represents a "memento" (disconnected, externalizable form) of a ProcedureCall
@ -19,7 +21,20 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
* @author Steve Ebersole
*/
@Incubating
public interface NamedCallableQueryMemento {
public interface NamedCallableQueryMemento extends NamedQueryMemento {
@Override
default String getQueryString() {
return getCallableName();
}
/**
* The name of the database callable to execute. Whereas {@link #getName()}
* describes the name under which the named query is registered with the
* SessionFactory, the callable name is the actual database procedure/function
* name
*/
String getCallableName();
/**
* Convert the memento back into an executable (connected) form.
*

View File

@ -9,7 +9,6 @@ package org.hibernate.query;
import java.util.Objects;
import org.hibernate.DotIdentifierSequence;
import org.hibernate.internal.util.Loggable;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.model.domain.NavigableRole;
@ -21,7 +20,7 @@ import org.hibernate.metamodel.model.domain.NavigableRole;
*
* @author Steve Ebersole
*/
public class NavigablePath implements DotIdentifierSequence, Loggable {
public class NavigablePath implements DotIdentifierSequence {
public static final String IDENTIFIER_MAPPER_PROPERTY = "_identifierMapper";
private final NavigablePath parent;

View File

@ -4,11 +4,8 @@
* 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;
import javax.persistence.ParameterMode;
import org.hibernate.Incubating;
import org.hibernate.metamodel.model.domain.AllowableParameterType;
@ -21,18 +18,6 @@ import org.hibernate.metamodel.model.domain.AllowableParameterType;
*/
@Incubating
public interface QueryParameter<T> extends javax.persistence.Parameter<T> {
/**
* Is this a {@code IN}, {@code OUT} or {@code INOUT} parameter.
* <p/>
* Only really pertinent in regards to procedure/function calls. In all
* other cases the mode would be {@link ParameterMode#IN}
*
* @return The parameter mode.
*/
default ParameterMode getMode() {
return ParameterMode.IN;
}
/**
* Does this parameter allow multi-valued (collection, array, etc) binding?
* <p/>

View File

@ -4,7 +4,7 @@
* 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.produce;
package org.hibernate.query.hql;
import org.hibernate.HibernateException;
@ -14,12 +14,12 @@ import org.hibernate.HibernateException;
*
* @author Steve Ebersole
*/
public class SqmProductionException extends HibernateException {
public SqmProductionException(String message) {
public class HqlInterpretationException extends HibernateException {
public HqlInterpretationException(String message) {
super( message );
}
public SqmProductionException(String message, Throwable cause) {
public HqlInterpretationException(String message, Throwable cause) {
super( message, cause );
}
}

View File

@ -0,0 +1,69 @@
/*
* 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.hql.internal;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
/**
* @author Steve Ebersole
*/
public class FullyQualifiedReflectivePath implements SemanticPathPart, FullyQualifiedReflectivePathSource {
private final FullyQualifiedReflectivePathSource pathSource;
private final String localName;
@SuppressWarnings("WeakerAccess")
public FullyQualifiedReflectivePath(
FullyQualifiedReflectivePathSource pathSource,
String localName) {
this.pathSource = pathSource;
this.localName = localName;
}
@Override
public FullyQualifiedReflectivePath resolvePathPart(
String name,
boolean isTerminal,
SqmCreationState creationState) {
if ( isTerminal ) {
return new FullyQualifiedReflectivePathTerminal( this, name, creationState );
}
else {
return new FullyQualifiedReflectivePath( this, name );
}
}
@Override
public SqmPath<?> resolveIndexedAccess(
SqmExpression selector,
boolean isTerminal,
SqmCreationState creationState) {
throw new UnsupportedOperationException( "Fully qualified reflective paths cannot contain indexed access" );
}
@Override
public FullyQualifiedReflectivePathSource getParent() {
return pathSource;
}
@Override
public String getLocalName() {
return localName;
}
@Override
public String getFullPath() {
return pathSource.getFullPath() + '.' + localName;
}
@Override
public FullyQualifiedReflectivePath append(String subPathName) {
return new FullyQualifiedReflectivePath( this, subPathName );
}
}

View File

@ -0,0 +1,17 @@
/*
* 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.hql.internal;
import org.hibernate.DotIdentifierSequence;
import org.hibernate.query.hql.spi.SemanticPathPart;
/**
* @author Steve Ebersole
*/
@SuppressWarnings("WeakerAccess")
public interface FullyQualifiedReflectivePathSource extends DotIdentifierSequence, SemanticPathPart {
}

View File

@ -0,0 +1,226 @@
/*
* 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.hql.internal;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import javax.persistence.criteria.Expression;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.criteria.JpaSelection;
import org.hibernate.query.hql.HqlInterpretationException;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SqmExpressable;
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/**
* @author Steve Ebersole
*/
public class FullyQualifiedReflectivePathTerminal
extends FullyQualifiedReflectivePath
implements SqmExpression {
private final SqmExpressable expressableType;
private final SqmCreationState creationState;
private final Function<SemanticQueryWalker,?> handler;
@SuppressWarnings("WeakerAccess")
public FullyQualifiedReflectivePathTerminal(
FullyQualifiedReflectivePathSource pathSource,
String subPathName,
SqmCreationState creationState) {
super( pathSource, subPathName );
this.creationState = creationState;
this.handler = resolveTerminalSemantic();
// todo (6.0) : how to calculate this?
this.expressableType = null;
}
@SuppressWarnings("unchecked")
private Function<SemanticQueryWalker, ?> resolveTerminalSemantic() {
return semanticQueryWalker -> {
final ClassLoaderService cls = creationState.getCreationContext().getServiceRegistry().getService( ClassLoaderService.class );
final String fullPath = getFullPath();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// See if it is an entity-type literal
final EntityDomainType<?> entityDescriptor = creationState.getCreationContext().getJpaMetamodel().entity( fullPath );
if ( entityDescriptor != null ) {
return new SqmLiteralEntityType( entityDescriptor, creationState.getCreationContext().getNodeBuilder() );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// See if it is a Class FQN
try {
final Class namedClass = cls.classForName( fullPath );
if ( namedClass != null ) {
return semanticQueryWalker.visitFullyQualifiedClass( namedClass );
}
}
catch (ClassLoadingException ignore) {
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Check the parent path as a Class FQN, meaning the terminal is a field or
// enum-value
final String parentFullPath = getParent().getFullPath();
try {
final Class namedClass = cls.classForName( parentFullPath );
if ( namedClass != null ) {
if ( namedClass.isEnum() ) {
return semanticQueryWalker.visitFullyQualifiedEnum(
Enum.valueOf( namedClass, getLocalName() )
);
}
else {
final Field field = namedClass.getField( getLocalName() );
return semanticQueryWalker.visitFullyQualifiedField( field );
}
}
}
catch (ClassLoadingException | NoSuchFieldException ignore) {
}
throw new HqlInterpretationException( "Unsure how to handle semantic path terminal - " + fullPath );
};
}
@Override
public SqmExpressable getNodeType() {
return expressableType;
}
@Override
public Object accept(SemanticQueryWalker walker) {
return handler.apply( walker );
}
@Override
public JavaTypeDescriptor getJavaTypeDescriptor() {
return expressableType.getExpressableJavaTypeDescriptor();
}
@Override
public void applyInferableType(SqmExpressable type) {
}
@Override
public SqmExpression<Long> asLong() {
return null;
}
@Override
public SqmExpression<Integer> asInteger() {
return null;
}
@Override
public SqmExpression<Float> asFloat() {
return null;
}
@Override
public SqmExpression<Double> asDouble() {
return null;
}
@Override
public SqmExpression<BigDecimal> asBigDecimal() {
return null;
}
@Override
public SqmExpression<BigInteger> asBigInteger() {
return null;
}
@Override
public SqmExpression<String> asString() {
return null;
}
@Override
public SqmExpression as(Class type) {
return null;
}
@Override
public SqmPredicate isNull() {
return null;
}
@Override
public SqmPredicate isNotNull() {
return null;
}
@Override
public SqmPredicate in(Object... values) {
return null;
}
@Override
public SqmPredicate in(Expression[] values) {
return null;
}
@Override
public SqmPredicate in(Collection values) {
return null;
}
@Override
public SqmPredicate in(Expression values) {
return null;
}
@Override
public List<? extends JpaSelection<?>> getSelectionItems() {
return null;
}
@Override
public JpaSelection alias(String name) {
return null;
}
@Override
public boolean isCompoundSelection() {
return false;
}
@Override
public String getAlias() {
return null;
}
@Override
public NodeBuilder nodeBuilder() {
return null;
}
}

View File

@ -21,8 +21,10 @@ import org.hibernate.query.spi.ParameterMemento;
import org.hibernate.query.sqm.internal.QuerySqmImpl;
/**
* Definition of a named query, defined in the mapping metadata. Additional, as of JPA 2.1, named query definition
* can also come from a compiled query.
* Definition of a named query, defined in the mapping metadata.
*
* Additionally, as of JPA 2.1, named query definition can also come
* from a compiled query.
*
* @author Gavin King
* @author Steve Ebersole
@ -34,8 +36,8 @@ public class NamedHqlQueryMementoImpl extends AbstractNamedQueryMemento implemen
public NamedHqlQueryMementoImpl(
String name,
List<ParameterMemento> parameterMementos,
String hqlString,
List<ParameterMemento> parameterMementos,
Integer firstResult,
Integer maxResults,
Boolean cacheable,

View File

@ -0,0 +1,156 @@
/*
* 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.hql.internal;
import java.lang.reflect.Field;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.SemanticException;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.produce.spi.SqmCreationContext;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
import org.hibernate.type.descriptor.java.spi.EnumJavaDescriptor;
/**
* A delayed resolution of a non-terminal path part
*
* @author Steve Ebersole
*/
public class SemanticPathPartDelayedResolution implements SemanticPathPart, FullyQualifiedReflectivePathSource {
private final FullyQualifiedReflectivePathSource parent;
// todo (6.0) : consider reusing this PossiblePackageRoot instance, updating the state fields
// - we'd still add to the stack, but we'd save the instantiations
private final String fullPath;
private final String localName;
@SuppressWarnings("WeakerAccess")
public SemanticPathPartDelayedResolution(String name) {
this( null, name );
}
@SuppressWarnings("WeakerAccess")
public SemanticPathPartDelayedResolution(
FullyQualifiedReflectivePathSource parent,
String localName) {
this.parent = parent;
this.localName = localName;
this.fullPath = parent == null ? localName : parent.append( localName ).getFullPath();
}
@Override
public FullyQualifiedReflectivePathSource getParent() {
return parent;
}
@Override
public String getLocalName() {
return localName;
}
@Override
public String getFullPath() {
return fullPath;
}
@Override
public SemanticPathPartDelayedResolution append(String subPathName) {
throw new UnsupportedOperationException( "Use #resolvePathPart instead" );
}
@Override
public SemanticPathPart resolvePathPart(
String subName,
boolean isTerminal,
SqmCreationState creationState) {
final String combinedName = this.fullPath + '.' + subName;
final SqmCreationContext creationContext = creationState.getCreationContext();
if ( isTerminal ) {
final EntityDomainType entityTypeByName = creationContext.getJpaMetamodel().entity( combinedName );
if ( entityTypeByName != null ) {
//noinspection unchecked
return new SqmLiteralEntityType( entityTypeByName, creationContext.getNodeBuilder() );
}
// the incoming subName could be a field or enum reference relative to this combinedName
// which would mean the combinedName must be a class name
final ClassLoaderService classLoaderService = creationContext
.getServiceRegistry()
.getService( ClassLoaderService.class );
// todo (6.0) : would be nice to leverage imported names here
try {
final Class referencedClass = classLoaderService.classForName( combinedName );
if ( referencedClass.isEnum() ) {
try {
//noinspection unchecked
final Enum<?> enumValue = Enum.valueOf( referencedClass, subName );
//noinspection unchecked
return new SqmEnumLiteral(
enumValue,
(EnumJavaDescriptor) creationContext.getJpaMetamodel()
.getTypeConfiguration()
.getJavaTypeDescriptorRegistry()
.resolveDescriptor( referencedClass ),
subName,
creationContext.getNodeBuilder()
);
}
catch (Exception e) {
// ignore - it could still potentially be a static field reference
}
}
try {
final Field field = referencedClass.getDeclaredField( subName );
//noinspection unchecked
return new SqmFieldLiteral<>(
field.get( null ),
creationContext.getJpaMetamodel()
.getTypeConfiguration()
.getJavaTypeDescriptorRegistry()
.resolveDescriptor( referencedClass ),
subName,
creationContext.getNodeBuilder()
);
}
catch (Exception e) {
// ignore - fall through to the exception below
}
}
catch (ClassLoadingException e) {
// ignore - we will hit the exception below
}
throw new SemanticException( "Could not resolve path terminal : " + combinedName + '.' + subName );
}
else {
return new SemanticPathPartDelayedResolution( this, subName );
}
}
@Override
public SqmPath<?> resolveIndexedAccess(
SqmExpression selector,
boolean isTerminal,
SqmCreationState creationState) {
return null;
}
}

View File

@ -0,0 +1,85 @@
/*
* 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.hql.internal;
import java.util.Locale;
import org.hibernate.query.SemanticException;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SqmPathRegistry;
import org.hibernate.query.sqm.produce.SqmCreationProcessingState;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.from.SqmFrom;
/**
* @author Steve Ebersole
*/
public class SemanticPathPartJoinPredicate implements SemanticPathPart {
private final SqmFrom joinLhs;
@SuppressWarnings("WeakerAccess")
public SemanticPathPartJoinPredicate(SqmFrom joinLhs) {
super();
this.joinLhs = joinLhs;
}
@Override
public SemanticPathPart resolvePathPart(
String name,
boolean isTerminal,
SqmCreationState creationState) {
final SqmCreationProcessingState processingState = creationState.getCurrentProcessingState();
final SqmPathRegistry pathRegistry = processingState.getPathRegistry();
// #1 - name is joinLhs alias
if ( name.equals( joinLhs.getExplicitAlias() ) ) {
return joinLhs;
}
// #2 - name is alias for another SqmFrom
final SqmFrom fromByAlias = pathRegistry.findFromByAlias( name );
if ( fromByAlias != null ) {
validatePathRoot( fromByAlias );
return fromByAlias;
}
// #3 - name is a unqualified attribute reference relative to the current processing state
final SqmFrom fromExposing = pathRegistry.findFromExposing( name );
if ( fromExposing != null ) {
validatePathRoot( fromExposing );
return fromExposing;
}
if ( ! isTerminal ) {
return new SemanticPathPartDelayedResolution( name );
}
throw new SemanticException( "Could not resolve path root used in join predicate: " + name );
}
private void validatePathRoot(SqmPath path) {
if ( ! path.findRoot().equals( joinLhs.findRoot() ) ) {
throw new SemanticException(
String.format(
Locale.ROOT,
"Qualified join predicate path [%s] referred to from-clause root other that the join rhs",
path.getNavigablePath().getFullPath()
)
);
}
}
@Override
public SqmPath resolveIndexedAccess(
SqmExpression selector,
boolean isTerminal,
SqmCreationState creationState) {
throw new SemanticException( "Illegal index-access as join predicate root" );
}
}

View File

@ -0,0 +1,152 @@
/*
* 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.hql.internal;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.SemanticException;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SqmPathRegistry;
import org.hibernate.query.sqm.SqmJoinable;
import org.hibernate.query.sqm.produce.SqmCreationProcessingState;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.SqmJoinType;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
import org.hibernate.query.sqm.tree.from.SqmFrom;
import org.hibernate.query.sqm.tree.from.SqmRoot;
/**
* SemanticPathPart handling specific to processing a qualified join path
*
* @author Steve Ebersole
*/
public class SemanticPathPartQualifiedJoinPath implements SemanticPathPart {
private final SqmRoot sqmRoot;
private final SqmJoinType joinType;
private final boolean fetch;
private final String alias;
@SuppressWarnings("WeakerAccess")
public SemanticPathPartQualifiedJoinPath(SqmRoot sqmRoot, SqmJoinType joinType, boolean fetch, String alias) {
this.sqmRoot = sqmRoot;
this.joinType = joinType;
this.fetch = fetch;
this.alias = alias;
}
@Override
public SemanticPathPart resolvePathPart(
String name,
boolean isTerminal,
SqmCreationState creationState) {
final SqmCreationProcessingState processingState = creationState.getCurrentProcessingState();
final SqmPathRegistry pathRegistry = processingState.getPathRegistry();
final SqmFrom fromByAlias = pathRegistry.findFromByAlias( name );
if ( fromByAlias != null ) {
return fromByAlias;
}
final SqmFrom fromExposing = pathRegistry.findFromExposing( name );
if ( fromExposing != null ) {
final SqmAttributeJoin join = ( (SqmJoinable) fromExposing.getReferencedPathSource().findSubPathSource(
name ) ).createSqmJoin(
fromExposing,
joinType,
isTerminal ? alias : null,
fetch,
creationState
);
pathRegistry.register( join );
return join;
}
// otherwise it has to be an entity join
if ( isTerminal ) {
final EntityDomainType<?> entityType = processingState.getCreationState()
.getCreationContext()
.getJpaMetamodel()
.entity( name );
if ( entityType == null ) {
throw new SemanticException( "Could not resolve qualified join path: " + name );
}
final SqmEntityJoin<?> entityJoin = new SqmEntityJoin<>( entityType, alias, joinType, sqmRoot );
pathRegistry.register( entityJoin );
return entityJoin;
}
return new SemanticPathPartDelayedEntityJoinHandler( name, sqmRoot, joinType, alias );
}
@Override
public SqmPath resolveIndexedAccess(
SqmExpression selector,
boolean isTerminal,
SqmCreationState creationState) {
throw new SemanticException( "Illegal index-access as qualified join path" );
}
private static class SemanticPathPartDelayedEntityJoinHandler implements SemanticPathPart {
private final SqmRoot sqmRoot;
private final SqmJoinType joinType;
private final String alias;
private String pathSoFar;
private SemanticPathPartDelayedEntityJoinHandler(
String baseName,
SqmRoot sqmRoot,
SqmJoinType joinType,
String alias) {
this.sqmRoot = sqmRoot;
this.joinType = joinType;
this.alias = alias;
this.pathSoFar = baseName;
}
@Override
public SemanticPathPart resolvePathPart(
String name,
boolean isTerminal,
SqmCreationState creationState) {
pathSoFar = pathSoFar + '.' + name;
if ( ! isTerminal ) {
return this;
}
final SqmCreationProcessingState processingState = creationState.getCurrentProcessingState();
final SqmPathRegistry pathRegistry = processingState.getPathRegistry();
final EntityDomainType<?> entityType = processingState.getCreationState()
.getCreationContext()
.getJpaMetamodel()
.entity( name );
if ( entityType == null ) {
throw new SemanticException( "Could not resolve qualified join path: " + name );
}
final SqmEntityJoin<?> entityJoin = new SqmEntityJoin<>( entityType, alias, joinType, sqmRoot );
pathRegistry.register( entityJoin );
return entityJoin;
}
@Override
public SqmPath resolveIndexedAccess(
SqmExpression selector,
boolean isTerminal,
SqmCreationState creationState) {
throw new SemanticException( "Illegal index-access as qualified join path" );
}
}
}

View File

@ -0,0 +1,77 @@
/*
* 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.hql.internal;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.SemanticException;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SqmPathRegistry;
import org.hibernate.query.sqm.produce.spi.SqmCreationContext;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
import org.hibernate.query.sqm.tree.from.SqmFrom;
/**
* @author Steve Ebersole
*/
public class SemanticPathPartRoot implements SemanticPathPart {
public SemanticPathPartRoot() {
}
@Override
public SemanticPathPart resolvePathPart(
String name,
boolean isTerminal,
SqmCreationState creationState) {
// At this point we have a "root reference"... the first path part in
// a potential series of path parts
final SqmPathRegistry pathRegistry = creationState.getProcessingStateStack().getCurrent().getPathRegistry();
final SqmCreationContext creationContext = creationState.getCreationContext();
// this root reference could be any of:
// 1) a from-element alias
// 2) an unqualified attribute name exposed from one (and only one!) from-element
// 3) an unqualified (imported) entity name
// #1
final SqmFrom aliasedFromElement = pathRegistry.findFromByAlias( name );
if ( aliasedFromElement != null ) {
return aliasedFromElement;
}
// #2
final SqmFrom unqualifiedAttributeOwner = pathRegistry.findFromExposing( name );
if ( unqualifiedAttributeOwner != null ) {
return unqualifiedAttributeOwner.resolvePathPart( name, false, creationState );
}
// #3
final EntityDomainType<?> entityTypeByName = creationContext.getJpaMetamodel().entity( name );
if ( entityTypeByName != null ) {
//noinspection unchecked
return new SqmLiteralEntityType( entityTypeByName, creationState.getCreationContext().getNodeBuilder() );
}
if ( ! isTerminal ) {
return new SemanticPathPartDelayedResolution( name );
}
throw new SemanticException( "Could not resolve path root : " + name );
}
@Override
public SqmPath resolveIndexedAccess(
SqmExpression selector,
boolean isTerminal,
SqmCreationState creationState) {
throw new SemanticException( "Path cannot start with index-access" );
}
}

View File

@ -17,6 +17,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.NullPrecedence;
import org.hibernate.SortOrder;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
@ -38,7 +39,8 @@ import org.hibernate.query.QueryLogger;
import org.hibernate.query.SemanticException;
import org.hibernate.query.TrimSpec;
import org.hibernate.query.UnaryArithmeticOperator;
import org.hibernate.query.hql.DotIdentifierConsumer;
import org.hibernate.query.hql.HqlInterpretationException;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.LiteralNumberFormatException;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.ParsingException;
@ -47,15 +49,12 @@ import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.StrictJpaComplianceViolation;
import org.hibernate.query.sqm.UnknownEntityException;
import org.hibernate.query.sqm.produce.SqmCreationProcessingState;
import org.hibernate.query.sqm.produce.SqmProductionException;
import org.hibernate.query.sqm.produce.SqmQuerySpecCreationProcessingState;
import org.hibernate.query.sqm.produce.SqmTreeCreationLogger;
import org.hibernate.query.sqm.produce.function.SqmFunctionTemplate;
import org.hibernate.query.sqm.produce.function.spi.NamedSqmFunctionTemplate;
import org.hibernate.query.sqm.produce.internal.SqmDmlCreationProcessingState;
import org.hibernate.query.sqm.produce.internal.SqmQuerySpecCreationProcessingStateStandardImpl;
import org.hibernate.query.sqm.produce.internal.UniqueIdGenerator;
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
import org.hibernate.query.sqm.produce.spi.ImplicitAliasGenerator;
import org.hibernate.query.sqm.produce.spi.ParameterDeclarationContext;
import org.hibernate.query.sqm.produce.spi.SqmCreationContext;
@ -93,7 +92,6 @@ import org.hibernate.query.sqm.tree.expression.function.SqmExtractUnit;
import org.hibernate.query.sqm.tree.expression.function.SqmStar;
import org.hibernate.query.sqm.tree.expression.function.SqmTrimSpecification;
import org.hibernate.query.sqm.tree.from.DowncastLocation;
import org.hibernate.query.sqm.tree.from.MutableUsageDetails;
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
import org.hibernate.query.sqm.tree.from.SqmCrossJoin;
import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
@ -169,7 +167,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
private final ImplicitAliasGenerator implicitAliasGenerator;
private final UniqueIdGenerator uidGenerator;
private final Stack<DotIdentifierConsumer> identifierConsumerStack;
private final Stack<SemanticPathPart> semanticPathPartStack;
private final Stack<TreatHandler> treatHandlerStack = new StandardStack<>( new TreatHandlerNormal() );
@ -190,9 +188,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
this.implicitAliasGenerator = new ImplicitAliasGenerator();
this.uidGenerator = new UniqueIdGenerator();
this.identifierConsumerStack = new StandardStack<>(
new BasicDotIdentifierConsumer( processingStateStack::getCurrent )
);
this.semanticPathPartStack = new StandardStack<>( new SemanticPathPartRoot() );
}
@Override
@ -205,37 +201,10 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
return creationOptions;
}
@Override
public ImplicitAliasGenerator getImplicitAliasGenerator() {
return implicitAliasGenerator;
}
@Override
public String generateUniqueIdentifier() {
return uidGenerator.generateUniqueId();
}
@Override
public SqmQuerySpecCreationProcessingState getCurrentQuerySpecProcessingState() {
final SqmCreationProcessingState current = processingStateStack.getCurrent();
if ( current instanceof SqmQuerySpecCreationProcessingState ) {
return (SqmQuerySpecCreationProcessingState) current;
}
throw new UnsupportedOperationException( "Current processing state is not related to a SqmQuerySpec : " + current );
}
protected <T> void primeStack(Stack<T> stack, T initialValue) {
stack.push( initialValue );
}
protected Stack<ParameterDeclarationContext> getParameterDeclarationContextStack() {
return parameterDeclarationContextStack;
}
protected Stack<DotIdentifierConsumer> getIdentifierConsumerStack() {
return identifierConsumerStack;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Grammar rules
@ -322,13 +291,6 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
processingStateStack.push( new SqmDmlCreationProcessingState( insertStatement, this ) );
try {
String alias = getImplicitAliasGenerator().generateUniqueImplicitAlias();
log.debugf(
"Generated implicit alias [%s] for INSERT target [%s]",
alias,
targetType.getHibernateEntityName()
);
insertStatement.setSelectQuerySpec( visitQuerySpec( ctx.querySpec() ) );
for ( HqlParser.DotIdentifierSequenceContext stateFieldCtx : ctx.insertSpec().targetFieldsSpec().dotIdentifierSequence() ) {
@ -498,9 +460,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
public SqmSelectClause visitSelectClause(HqlParser.SelectClauseContext ctx) {
treatHandlerStack.push( new TreatHandlerNormal( DowncastLocation.SELECT ) );
identifierConsumerStack.push(
new SelectClauseDotIdentifierConsumer( this::getCurrentQuerySpecProcessingState )
);
// todo (6.0) : primer a select-clause-specific SemanticPathPart into the stack
try {
final SqmSelectClause selectClause = new SqmSelectClause(
@ -513,7 +473,6 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
return selectClause;
}
finally {
identifierConsumerStack.pop();
treatHandlerStack.pop();
}
}
@ -530,7 +489,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
creationContext.getNodeBuilder()
);
getCurrentQuerySpecProcessingState().registerSelection( selection );
getProcessingStateStack().getCurrent().getPathRegistry().register( selection );
return selection;
}
@ -737,7 +696,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
public SqmExpression visitSortExpression(HqlParser.SortExpressionContext ctx) {
if ( ctx.INTEGER_LITERAL() != null ) {
final int position = Integer.parseInt( ctx.INTEGER_LITERAL().getText() );
final SqmSelection selection = getCurrentQuerySpecProcessingState().findSelectionByPosition( position );
final SqmSelection selection = getCurrentProcessingState().getPathRegistry().findSelectionByPosition( position );
if ( selection != null ) {
final SqmSelectableNode selectableNode = selection.getSelectableNode();
if ( selectableNode instanceof SqmExpression ) {
@ -749,22 +708,13 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
}
if ( ctx.identifier() != null ) {
final SqmSelection selection = getCurrentQuerySpecProcessingState().findSelectionByAlias( ctx.identifier().getText() );
final SqmSelection selection = getCurrentProcessingState().getPathRegistry().findSelectionByAlias( ctx.identifier().getText() );
if ( selection != null ) {
final SqmSelectableNode selectableNode = selection.getSelectableNode();
if ( selectableNode instanceof SqmExpression ) {
return (SqmExpression) selectableNode;
}
}
final DotIdentifierConsumer dotIdentifierConsumer = identifierConsumerStack.getCurrent();
dotIdentifierConsumer.consumeIdentifier(
ctx.identifier().getText(),
true,
true
);
return (SqmExpression) dotIdentifierConsumer.getConsumedPart();
}
return (SqmExpression) ctx.expression().accept( this );
@ -1012,15 +962,14 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
final String alias = visitIdentificationVariableDef( parserJoin.qualifiedJoinRhs().identificationVariableDef() );
final DotIdentifierConsumer identifierConsumer = new QualifiedJoinPathIdentifierConsumer(
joinType,
parserJoin.FETCH() != null,
alias,
sqmRoot,
processingStateStack.getCurrent()
);
identifierConsumerStack.push( identifierConsumer );
semanticPathPartStack.push(
new SemanticPathPartQualifiedJoinPath(
sqmRoot,
joinType,
parserJoin.FETCH() != null,
alias
)
);
try {
final SqmQualifiedJoin join = (SqmQualifiedJoin) parserJoin.qualifiedJoinRhs().path().accept( this );
@ -1052,23 +1001,17 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
processingStateStack.getCurrent().getPathRegistry().register( join );
if ( parserJoin.qualifiedJoinPredicate() != null ) {
identifierConsumerStack.push(
new QualifiedJoinPredicateDotIdentifierConsumer(
processingStateStack::getCurrent,
join,
parserJoin.qualifiedJoinPredicate().getText()
)
);
semanticPathPartStack.push( new SemanticPathPartJoinPredicate( join ) );
try {
join.setJoinPredicate( (SqmPredicate) parserJoin.qualifiedJoinPredicate().predicate().accept( this ) );
}
finally {
identifierConsumerStack.pop();
semanticPathPartStack.pop();
}
}
}
finally {
identifierConsumerStack.pop();
semanticPathPartStack.pop();
}
}
@ -2258,7 +2201,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
);
}
default: {
throw new SqmProductionException( "unrecognized cast target type: " + text);
throw new HqlInterpretationException( "unrecognized cast target type: " + text);
}
}
}
@ -2649,18 +2592,12 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
if ( ctx.syntacticDomainPath() != null ) {
final SemanticPathPart syntacticNavigablePathResult = visitSyntacticDomainPath( ctx.syntacticDomainPath() );
if ( ctx.pathContinuation() != null ) {
identifierConsumerStack.push(
new BasicDotIdentifierConsumer( syntacticNavigablePathResult, processingStateStack::getCurrent ) {
@Override
protected void reset() {
}
}
);
semanticPathPartStack.push( syntacticNavigablePathResult );
try {
return (SemanticPathPart) ctx.pathContinuation().accept( this );
}
finally {
identifierConsumerStack.pop();
semanticPathPartStack.pop();
}
}
return syntacticNavigablePathResult;
@ -2706,26 +2643,26 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
final int numberOfContinuations = ctx.dotIdentifierSequenceContinuation().size();
final boolean hasContinuations = numberOfContinuations != 0;
final DotIdentifierConsumer dotIdentifierConsumer = identifierConsumerStack.getCurrent();
final SemanticPathPart currentPathPart = semanticPathPartStack.getCurrent();
dotIdentifierConsumer.consumeIdentifier(
SemanticPathPart result = currentPathPart.resolvePathPart(
ctx.identifier().getText(),
true,
! hasContinuations
!hasContinuations,
this
);
if ( hasContinuations ) {
int i = 1;
for ( HqlParser.DotIdentifierSequenceContinuationContext continuation : ctx.dotIdentifierSequenceContinuation() ) {
dotIdentifierConsumer.consumeIdentifier(
result = result.resolvePathPart(
continuation.identifier().getText(),
false,
i++ >= numberOfContinuations
i++ >= numberOfContinuations,
this
);
}
}
return dotIdentifierConsumer.getConsumedPart();
return result;
}
@Override
@ -2743,15 +2680,12 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
SqmPath<?> result = resolveTreatedPath( sqmPath, treatTarget );
if ( ctx.pathContinuation() != null ) {
identifierConsumerStack.push(
new BasicDotIdentifierConsumer( sqmPath, processingStateStack::getCurrent )
);
semanticPathPartStack.push( result );
try {
result = consumeDomainPath( ctx.pathContinuation().dotIdentifierSequence() );
}
finally {
identifierConsumerStack.pop();
semanticPathPartStack.pop();
}
}
@ -2820,9 +2754,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
private SqmPath consumeDomainPath(HqlParser.PathContext parserPath) {
parserPath.accept( this );
final DotIdentifierConsumer dotIdentifierConsumer = identifierConsumerStack.getCurrent();
final SemanticPathPart consumedPart = dotIdentifierConsumer.getConsumedPart();
final SemanticPathPart consumedPart = (SemanticPathPart) parserPath.accept( this );
if ( consumedPart instanceof SqmPath ) {
return (SqmPath) consumedPart;
}
@ -2832,9 +2764,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
private SqmPath consumeDomainPath(HqlParser.DotIdentifierSequenceContext sequence) {
sequence.accept( this );
final DotIdentifierConsumer dotIdentifierConsumer = identifierConsumerStack.getCurrent();
final SemanticPathPart consumedPart = dotIdentifierConsumer.getConsumedPart();
final SemanticPathPart consumedPart = (SemanticPathPart) sequence.accept( this );
if ( consumedPart instanceof SqmPath ) {
return (SqmPath) consumedPart;
}
@ -2886,7 +2816,8 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
public void addDowncast(
SqmFrom sqmFrom,
IdentifiableDomainType downcastTarget) {
( (MutableUsageDetails) sqmFrom.getUsageDetails() ).addDownCast( false, downcastTarget, downcastLocation );
// ( (MutableUsageDetails) sqmFrom.getUsageDetails() ).addDownCast( false, downcastTarget, downcastLocation );
throw new NotYetImplementedFor6Exception();
}
}
@ -2895,7 +2826,8 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
public void addDowncast(
SqmFrom sqmFrom,
IdentifiableDomainType downcastTarget) {
( (MutableUsageDetails) sqmFrom.getUsageDetails() ).addDownCast( true, downcastTarget, DowncastLocation.FROM );
// ( (MutableUsageDetails) sqmFrom.getUsageDetails() ).addDownCast( true, downcastTarget, DowncastLocation.FROM );
throw new NotYetImplementedFor6Exception();
}
}
}

View File

@ -0,0 +1,268 @@
/*
* 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.hql.internal;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.function.Function;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.QueryLogger;
import org.hibernate.query.hql.spi.SqmPathRegistry;
import org.hibernate.query.sqm.AliasCollisionException;
import org.hibernate.query.sqm.ParsingException;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.produce.SqmCreationProcessingState;
import org.hibernate.query.sqm.produce.SqmTreeCreationLogger;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.from.SqmFrom;
import org.hibernate.query.sqm.tree.select.SqmSelection;
/**
* Container for indexing needed while building an SQM tree.
*
* @author Steve Ebersole
*/
public class SqmPathRegistryImpl implements SqmPathRegistry {
private final SqmCreationProcessingState associatedProcessingState;
private final Map<NavigablePath, SqmPath> sqmPathByPath = new HashMap<>();
private final Map<NavigablePath, SqmFrom> sqmFromByPath = new HashMap<>();
private final Map<String, SqmFrom> sqmFromByAlias = new HashMap<>();
private final LinkedHashMap<String, SqmSelection> sqmSelectionsByAlias = new LinkedHashMap<>();
public SqmPathRegistryImpl(SqmCreationProcessingState associatedProcessingState) {
this.associatedProcessingState = associatedProcessingState;
}
@Override
public void register(SqmPath sqmPath) {
SqmTreeCreationLogger.LOGGER.tracef( "SqmProcessingIndex#register(SqmPath) : %s", sqmPath.getNavigablePath().getFullPath() );
// Generally we:
// 1) add the path to the path-by-path map
// 2) if the path is a from, we add it to the from-by-path map
// 3) if the path is a from and defines an alias, we add it to the from-by-alias map
//
// Regarding part #1 (add to the path-by-path map), it is ok for a SqmFrom to replace a
// non-SqmFrom. This should equate to, e.g., an implicit join.
if ( sqmPath instanceof SqmFrom ) {
final SqmFrom sqmFrom = (SqmFrom) sqmPath;
final String alias = sqmPath.getExplicitAlias();
if ( alias != null ) {
final SqmFrom previousFrom = sqmFromByAlias.put( alias, sqmFrom );
if ( previousFrom != null ) {
throw new AliasCollisionException(
String.format(
Locale.ENGLISH,
"Alias [%s] used for multiple from-clause elements : %s, %s",
alias,
previousFrom,
sqmPath
)
);
}
}
final SqmFrom previousFromByPath = sqmFromByPath.put( sqmPath.getNavigablePath(), sqmFrom );
if ( previousFromByPath != null ) {
// this should never happen
throw new ParsingException(
String.format(
Locale.ROOT,
"Registration for SqmFrom [%s] overrode previous registration: %s -> %s",
sqmPath.getNavigablePath(),
previousFromByPath,
sqmFrom
)
);
}
}
final SqmPath previousPath = sqmPathByPath.put( sqmPath.getNavigablePath(), sqmPath );
if ( previousPath instanceof SqmFrom ) {
// this should never happen
throw new ParsingException(
String.format(
Locale.ROOT,
"Registration for path [%s] overrode previous registration: %s -> %s",
sqmPath.getNavigablePath(),
previousPath,
sqmPath
)
);
}
}
@Override
public SqmPath findPath(NavigablePath path) {
final SqmPath found = sqmPathByPath.get( path );
if ( found != null ) {
return found;
}
if ( associatedProcessingState.getParentProcessingState() != null ) {
final SqmFrom containingQueryFrom = associatedProcessingState.getParentProcessingState()
.getPathRegistry()
.findFromByPath( path );
if ( containingQueryFrom != null ) {
// todo (6.0) create a correlation?
return containingQueryFrom;
}
}
return null;
}
@Override
public SqmFrom findFromByPath(NavigablePath navigablePath) {
final SqmFrom found = sqmFromByPath.get( navigablePath );
if ( found != null ) {
return found;
}
if ( associatedProcessingState.getParentProcessingState() != null ) {
final SqmFrom containingQueryFrom = associatedProcessingState.getParentProcessingState()
.getPathRegistry()
.findFromByPath( navigablePath );
if ( containingQueryFrom != null ) {
// todo (6.0) create a correlation?
return containingQueryFrom;
}
}
return null;
}
@Override
public SqmFrom findFromByAlias(String alias) {
final SqmFrom registered = sqmFromByAlias.get( alias );
if ( registered != null ) {
return registered;
}
if ( associatedProcessingState.getParentProcessingState() != null ) {
return associatedProcessingState.getParentProcessingState().getPathRegistry().findFromByAlias( alias );
}
return null;
}
@Override
public SqmFrom findFromExposing(String navigableName) {
// todo (6.0) : atm this checks every from-element every time, the idea being to make sure there
// is only one such element obviously that scales poorly across larger from-clauses. Another
// (configurable?) option would be to simply pick the first one as a perf optimization
SqmFrom found = null;
for ( SqmFrom fromElement : sqmFromByPath.values() ) {
if ( definesAttribute( fromElement.getReferencedPathSource(), navigableName ) ) {
if ( found != null ) {
throw new IllegalStateException( "Multiple from-elements expose unqualified attribute : " + navigableName );
}
found = fromElement;
}
}
if ( found == null ) {
if ( associatedProcessingState.getParentProcessingState() != null ) {
QueryLogger.QUERY_LOGGER.debugf(
"Unable to resolve unqualified attribute [%s] in local from-clause; checking parent ",
navigableName
);
found = associatedProcessingState.getParentProcessingState().getPathRegistry().findFromExposing( navigableName );
}
}
return found;
}
@Override
public SqmPath resolvePath(NavigablePath navigablePath, Function<NavigablePath, SqmPath> creator) {
SqmTreeCreationLogger.LOGGER.tracef( "SqmProcessingIndex#resolvePath(NavigablePath) : %s", navigablePath );
final SqmPath existing = sqmPathByPath.get( navigablePath );
if ( existing != null ) {
return existing;
}
final SqmPath sqmPath = creator.apply( navigablePath );
register( sqmPath );
return sqmPath;
}
private boolean definesAttribute(SqmPathSource containerType, String name) {
return containerType.findSubPathSource( name ) != null;
}
@Override
public SqmSelection findSelectionByAlias(String alias) {
return sqmSelectionsByAlias.get( alias );
}
@Override
public SqmSelection findSelectionByPosition(int position) {
// NOTE : 1-based
// so incoming position must be between >= 1 and <= map.size
if ( position >= 1 && position <= sqmSelectionsByAlias.size() ) {
int i = 1;
for ( Map.Entry<String, SqmSelection> entry : sqmSelectionsByAlias.entrySet() ) {
if ( position == i++ ) {
return entry.getValue();
}
}
}
return null;
}
@Override
public void register(SqmSelection selection) {
if ( selection.getAlias() != null ) {
checkResultVariable( selection );
sqmSelectionsByAlias.put( selection.getAlias(), selection );
}
}
private void checkResultVariable(SqmSelection selection) {
final String alias = selection.getAlias();
if ( sqmSelectionsByAlias.containsKey( alias ) ) {
throw new AliasCollisionException(
String.format(
Locale.ENGLISH,
"Alias [%s] is already used in same select clause",
alias
)
);
}
final SqmFrom registeredFromElement = sqmFromByAlias.get( alias );
if ( registeredFromElement != null ) {
if ( !registeredFromElement.equals( selection.getSelectableNode() ) ) {
throw new AliasCollisionException(
String.format(
Locale.ENGLISH,
"Alias [%s] used in select-clause [%s] also used in from-clause [%s]",
alias,
selection.getSelectableNode(),
registeredFromElement
)
);
}
}
}
}

View File

@ -6,7 +6,14 @@
*/
package org.hibernate.query.hql.spi;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockOptions;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
import org.hibernate.query.spi.NamedQueryMemento;
/**
@ -25,4 +32,129 @@ public interface NamedHqlQueryMemento extends NamedQueryMemento {
@Override
<T> HqlQueryImplementor<T> toQuery(SharedSessionContractImplementor session, Class<T> resultType);
/**
* Delegate used in creating named HQL query mementos for queries defined in
* annotations, hbm.xml or orm.xml
*/
class Builder {
protected String name;
protected String query;
protected boolean cacheable;
protected String cacheRegion;
protected Integer timeout;
protected Integer fetchSize;
protected FlushMode flushMode;
protected CacheMode cacheMode;
protected boolean readOnly;
protected String comment;
protected Map parameterTypes;
protected LockOptions lockOptions;
protected Integer firstResult;
protected Integer maxResults;
public Builder() {
}
public Builder(String name) {
this.name = name;
}
public Builder setName(String name) {
this.name = name;
return this;
}
public Builder setQuery(String query) {
this.query = query;
return this;
}
public Builder setCacheable(boolean cacheable) {
this.cacheable = cacheable;
return this;
}
public Builder setCacheRegion(String cacheRegion) {
this.cacheRegion = cacheRegion;
return this;
}
public Builder setTimeout(Integer timeout) {
this.timeout = timeout;
return this;
}
public Builder setFetchSize(Integer fetchSize) {
this.fetchSize = fetchSize;
return this;
}
public Builder setFlushMode(FlushMode flushMode) {
this.flushMode = flushMode;
return this;
}
public Builder setCacheMode(CacheMode cacheMode) {
this.cacheMode = cacheMode;
return this;
}
public Builder setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
return this;
}
public Builder setComment(String comment) {
this.comment = comment;
return this;
}
public Builder addParameterType(String name, String typeName) {
if ( this.parameterTypes == null ) {
this.parameterTypes = new HashMap();
}
this.parameterTypes.put( name, typeName );
return this;
}
public Builder setParameterTypes(Map parameterTypes) {
this.parameterTypes = parameterTypes;
return this;
}
public Builder setLockOptions(LockOptions lockOptions) {
this.lockOptions = lockOptions;
return this;
}
public Builder setFirstResult(Integer firstResult) {
this.firstResult = firstResult;
return this;
}
public Builder setMaxResults(Integer maxResults) {
this.maxResults = maxResults;
return this;
}
public NamedHqlQueryMemento createNamedQueryDefinition() {
return new NamedHqlQueryMementoImpl(
name,
query,
cacheable,
cacheRegion,
timeout,
lockOptions,
fetchSize,
flushMode,
cacheMode,
readOnly,
comment,
parameterTypes,
firstResult,
maxResults
);
}
}
}

View File

@ -4,7 +4,7 @@
* 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.produce.path.spi;
package org.hibernate.query.hql.spi;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.domain.SqmPath;
@ -27,13 +27,11 @@ import org.hibernate.query.sqm.tree.domain.SqmNavigableReference;
public interface SemanticPathPart {
SemanticPathPart resolvePathPart(
String name,
String currentContextKey,
boolean isTerminal,
SqmCreationState creationState);
SqmPath resolveIndexedAccess(
SqmExpression selector,
String currentContextKey,
boolean isTerminal,
SqmCreationState creationState);
}

View File

@ -4,7 +4,7 @@
* 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.produce;
package org.hibernate.query.hql.spi;
import java.util.function.Function;
@ -12,6 +12,7 @@ import org.hibernate.Incubating;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.from.SqmFrom;
import org.hibernate.query.sqm.tree.select.SqmSelection;
/**
* Registry for SqmPath references providing the ability to access them
@ -24,6 +25,12 @@ import org.hibernate.query.sqm.tree.from.SqmFrom;
public interface SqmPathRegistry {
void register(SqmPath sqmPath);
SqmSelection findSelectionByAlias(String alias);
SqmSelection findSelectionByPosition(int position);
void register(SqmSelection selection);
/**
* Find a SqmFrom by its identification variable (alias). Will search any
* parent contexts as well

View File

@ -6,7 +6,6 @@
*/
package org.hibernate.query.internal;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
@ -14,12 +13,13 @@ import java.util.function.Consumer;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification;
import org.hibernate.procedure.NamedCallableQueryMemento;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.query.hql.SemanticQueryProducer;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.spi.NamedQueryRepository;
import org.hibernate.query.spi.NamedResultSetMappingMemento;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryPlanCache;
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
import org.hibernate.query.sqm.tree.SqmStatement;
@ -131,6 +131,8 @@ public class NamedQueryRepositoryImpl implements NamedQueryRepository {
Map<String,HibernateException> errors = new HashMap<>();
final SemanticQueryProducer sqmProducer = queryEngine.getSemanticQueryProducer();
final QueryPlanCache queryPlanCache = queryEngine.getQueryPlanCache();
final boolean cachingEnabled = queryPlanCache.isEnabled();
// Check named HQL queries
log.debugf( "Checking %s named HQL queries", hqlMementoMap.size() );
@ -139,8 +141,11 @@ public class NamedQueryRepositoryImpl implements NamedQueryRepository {
try {
log.debugf( "Checking named query: %s", hqlMemento.getName() );
final SqmStatement sqmStatement = sqmProducer.interpret( hqlMemento.getQueryString() );
// todo (6.0) : need to cache these; however atm that requires producing a SqmQueryImpl
// queryEngine.getQueryPlanCache().getHQLQueryPlan( hqlMemento.getQueryString(), false, Collections.EMPTY_MAP );
if ( cachingEnabled ) {
// todo (6.0) : need to cache these; however atm that requires producing a SqmQueryImpl
// queryEngine.getQueryPlanCache().getHQLQueryPlan( hqlMemento.getQueryString(), false, Collections.EMPTY_MAP );
}
}
catch ( HibernateException e ) {
errors.put( hqlMemento.getName(), e );

View File

@ -54,6 +54,11 @@ public class QueryPlanCacheDisabledImpl implements QueryPlanCache {
public void cacheSqmStatement(String key, SqmStatement sqmStatement) {
}
@Override
public boolean isEnabled() {
return false;
}
@Override
public void close() {
}

View File

@ -99,6 +99,11 @@ public class QueryPlanCacheStandardImpl implements QueryPlanCache {
sqmStatementCache.putIfAbsent( queryString, sqmStatement );
}
@Override
public boolean isEnabled() {
return true;
}
@Override
public void close() {
// todo (6.0) : clear maps/caches and LOG

View File

@ -34,7 +34,14 @@ public interface ProcedureParameter<T> extends QueryParameter<T> {
* that it is ignored.
*
* @see ParameterRegistrationImplementor#isPassNullsEnabled()
*
* @deprecated (since 6.0) : Passing null or not is now triggered by whether
* setting the parameter was called at all. In other words a distinction is
* made between calling `setParameter` passing {@code null} versus not calling
* `setParameter` at all. In the first case, we pass along the {@code null}; in
* the second we do not pass {@code null}.
*/
@Deprecated
boolean isPassNullsEnabled();
/**
@ -44,6 +51,9 @@ public interface ProcedureParameter<T> extends QueryParameter<T> {
* @param enabled {@code true} indicates that the NULL should be passed; {@code false} indicates it should not.
*
* @see org.hibernate.procedure.ParameterRegistration#enablePassingNulls
*
* @deprecated (since 6.0) : see {@link #isPassNullsEnabled}
*/
@Deprecated
void enablePassingNulls(boolean enabled);
}

View File

@ -6,8 +6,14 @@
*/
package org.hibernate.query.spi;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.ParameterMode;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
@ -22,7 +28,7 @@ import org.hibernate.procedure.internal.Util;
public abstract class AbstractNamedQueryMemento implements NamedQueryMemento {
private final String name;
private final List<ParameterMemento> parameterMementos;
private final List<? extends ParameterMemento> parameterMementos;
private final Boolean cacheable;
private final String cacheRegion;
@ -42,7 +48,7 @@ public abstract class AbstractNamedQueryMemento implements NamedQueryMemento {
public AbstractNamedQueryMemento(
String name,
List<ParameterMemento> parameterMementos,
List<? extends ParameterMemento> parameterMementos,
Boolean cacheable,
String cacheRegion,
CacheMode cacheMode,
@ -169,4 +175,192 @@ public abstract class AbstractNamedQueryMemento implements NamedQueryMemento {
query.setComment( comment );
}
}
protected static abstract class AbstractBuilder<T extends AbstractBuilder> {
private final String name;
private List<ParameterDefinition> parameterDescriptors;
private Set<String> querySpaces;
private Boolean cacheable;
private String cacheRegion;
private CacheMode cacheMode;
private FlushMode flushMode;
private Boolean readOnly;
private LockOptions lockOptions;
private Integer timeout;
private Integer fetchSize;
private String comment;
private Map<String,Object> hints;
public AbstractBuilder(String name) {
this.name = name;
}
public String getName() {
return name;
}
protected abstract T getThis();
public T addParameter(Class javaType, ParameterMode mode) {
return addParameter(
createPositionalParameter(
parameterDescriptors.size() + 1,
javaType,
mode
)
);
}
protected abstract ParameterDefinition createPositionalParameter(int i, Class javaType, ParameterMode mode);
public T addParameter(ParameterDefinition parameterDefinition) {
if ( parameterDescriptors == null ) {
parameterDescriptors = new ArrayList<>();
}
parameterDescriptors.add( parameterDefinition );
return getThis();
}
public T addParameter(String name, Class javaType, ParameterMode mode) {
if ( parameterDescriptors == null ) {
parameterDescriptors = new ArrayList<>();
}
parameterDescriptors.add( createNamedParameter( name, javaType, mode ) );
return getThis();
}
protected abstract ParameterDefinition createNamedParameter(String name, Class javaType, ParameterMode mode);
public T addQuerySpaces(Set<String> querySpaces) {
if ( querySpaces == null || querySpaces.isEmpty() ) {
return getThis();
}
if ( this.querySpaces == null ) {
this.querySpaces = new HashSet<>();
}
this.querySpaces.addAll( querySpaces );
return getThis();
}
public T addQuerySpace(String space) {
if ( this.querySpaces == null ) {
this.querySpaces = new HashSet<>();
}
this.querySpaces.add( space );
return getThis();
}
public T setCacheable(Boolean cacheable) {
this.cacheable = cacheable;
return getThis();
}
public T setCacheRegion(String cacheRegion) {
this.cacheRegion = cacheRegion;
return getThis();
}
public T setCacheMode(CacheMode cacheMode) {
this.cacheMode = cacheMode;
return getThis();
}
public T setLockOptions(LockOptions lockOptions) {
this.lockOptions = lockOptions;
return getThis();
}
public T setTimeout(Integer timeout) {
this.timeout = timeout;
return getThis();
}
public T setFlushMode(FlushMode flushMode) {
this.flushMode = flushMode;
return getThis();
}
public T setReadOnly(Boolean readOnly) {
this.readOnly = readOnly;
return getThis();
}
public T setFetchSize(Integer fetchSize) {
this.fetchSize = fetchSize;
return getThis();
}
public T setComment(String comment) {
this.comment = comment;
return getThis();
}
public Set<String> getQuerySpaces() {
return querySpaces;
}
public Boolean getCacheable() {
return cacheable;
}
public String getCacheRegion() {
return cacheRegion;
}
public CacheMode getCacheMode() {
return cacheMode;
}
public FlushMode getFlushMode() {
return flushMode;
}
public Boolean getReadOnly() {
return readOnly;
}
public LockOptions getLockOptions() {
return lockOptions;
}
public Integer getTimeout() {
return timeout;
}
public Integer getFetchSize() {
return fetchSize;
}
public String getComment() {
return comment;
}
protected List<ParameterDefinition> getParameterDescriptors() {
return parameterDescriptors;
}
public void addHint(String name, Object value) {
if ( hints == null ) {
hints = new HashMap<>();
}
hints.put( name, value );
}
public Map<String, Object> getHints() {
return hints;
}
}
}

View File

@ -11,7 +11,7 @@ import java.util.function.Consumer;
import org.hibernate.HibernateException;
import org.hibernate.Incubating;
import org.hibernate.procedure.NamedCallableQueryMemento;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;

View File

@ -32,6 +32,8 @@ public interface QueryPlanCache {
SqmStatement getSqmStatement(String queryString);
void cacheSqmStatement(String key, SqmStatement sqmStatement);
boolean isEnabled();
/**
* Close the cache when the SessionFactory is closed.
* <p>

View File

@ -15,7 +15,7 @@ import org.hibernate.internal.util.collections.Stack;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.sqm.produce.SqmCreationProcessingState;
import org.hibernate.query.sqm.produce.SqmPathRegistry;
import org.hibernate.query.hql.spi.SqmPathRegistry;
import org.hibernate.query.sqm.produce.SqmQuerySpecCreationProcessingState;
import org.hibernate.query.sqm.produce.spi.ImplicitAliasGenerator;
import org.hibernate.query.sqm.produce.spi.SqmCreationContext;

View File

@ -27,7 +27,9 @@ import org.hibernate.query.sqm.tree.expression.SqmCaseSearched;
import org.hibernate.query.sqm.tree.expression.SqmCaseSimple;
import org.hibernate.query.sqm.tree.expression.SqmCollectionSize;
import org.hibernate.query.sqm.tree.expression.SqmCriteriaParameter;
import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
@ -157,6 +159,10 @@ public interface SemanticQueryWalker<T> {
T visitLiteral(SqmLiteral<?> literal);
T visitEnumLiteral(SqmEnumLiteral sqmEnumLiteral);
T visitFieldLiteral(SqmFieldLiteral sqmFieldLiteral);
T visitTuple(SqmTuple<?> sqmTuple);
T visitBinaryArithmeticExpression(SqmBinaryArithmetic<?> expression);

View File

@ -7,6 +7,7 @@
package org.hibernate.query.sqm.produce;
import org.hibernate.Incubating;
import org.hibernate.query.hql.spi.SqmPathRegistry;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.SqmQuery;

View File

@ -6,9 +6,9 @@
*/
package org.hibernate.query.sqm.produce.internal;
import org.hibernate.query.hql.internal.SqmProcessingIndex;
import org.hibernate.query.hql.internal.SqmPathRegistryImpl;
import org.hibernate.query.sqm.produce.SqmCreationProcessingState;
import org.hibernate.query.sqm.produce.SqmPathRegistry;
import org.hibernate.query.hql.spi.SqmPathRegistry;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.SqmQuery;
@ -19,7 +19,7 @@ public class SqmCreationProcessingStateImpl implements SqmCreationProcessingStat
private final SqmCreationState creationState;
private final SqmQuery<?> processingQuery;
private final SqmProcessingIndex processingIndex = new SqmProcessingIndex( this );
private final SqmPathRegistryImpl processingIndex = new SqmPathRegistryImpl( this );
public SqmCreationProcessingStateImpl(
SqmQuery<?> processingQuery,
@ -38,7 +38,7 @@ public class SqmCreationProcessingStateImpl implements SqmCreationProcessingStat
return processingQuery;
}
protected SqmProcessingIndex getProcessingIndex() {
protected SqmPathRegistryImpl getProcessingIndex() {
return processingIndex;
}

View File

@ -45,7 +45,7 @@ public class SqmQuerySpecCreationProcessingStateStandardImpl
@Override
public void registerSelection(SqmSelection selection) {
getProcessingIndex().registerSelection( selection );
getProcessingIndex().register( selection );
}
@Override

View File

@ -15,7 +15,7 @@ import org.hibernate.metamodel.model.mapping.spi.BasicValuedNavigable;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SqmExpressable;
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.expression.AbstractSqmExpression;
@ -49,7 +49,6 @@ public class SqmStaticEnumReference<T extends Enum<T>>
@Override
public SemanticPathPart resolvePathPart(
String name,
String currentContextKey,
boolean isTerminal,
SqmCreationState creationState) {
throw new UnsupportedOperationException( );
@ -58,7 +57,6 @@ public class SqmStaticEnumReference<T extends Enum<T>>
@Override
public SqmPath resolveIndexedAccess(
SqmExpression selector,
String currentContextKey,
boolean isTerminal,
SqmCreationState creationState) {
throw new UnsupportedOperationException( );

View File

@ -14,8 +14,8 @@ import org.hibernate.metamodel.model.mapping.spi.BasicValuedNavigable;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SqmExpressable;
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
import org.hibernate.query.sqm.produce.SqmProductionException;
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
import org.hibernate.query.hql.HqlInterpretationException;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.expression.AbstractSqmExpression;
@ -43,7 +43,7 @@ public class SqmStaticFieldReference<T>
this.fieldValue = referencedField.get( null );
}
catch (IllegalAccessException e) {
throw new SqmProductionException(
throw new HqlInterpretationException(
"Could not access field value : `"
+ referencedField.getDeclaringClass().getTypeName() + "."
+ referencedField.getName() + "`",
@ -62,7 +62,6 @@ public class SqmStaticFieldReference<T>
@Override
public SemanticPathPart resolvePathPart(
String name,
String currentContextKey,
boolean isTerminal,
SqmCreationState creationState) {
throw new UnsupportedOperationException( );
@ -71,7 +70,6 @@ public class SqmStaticFieldReference<T>
@Override
public SqmPath resolveIndexedAccess(
SqmExpression selector,
String currentContextKey,
boolean isTerminal,
SqmCreationState creationState) {
throw new UnsupportedOperationException( );
@ -111,7 +109,7 @@ public class SqmStaticFieldReference<T>
);
}
catch (IllegalAccessException e) {
throw new SqmProductionException(
throw new HqlInterpretationException(
"Could not access field value : `"
+ referencedField.getDeclaringClass().getTypeName() + "."
+ referencedField.getName() + "`",
@ -131,7 +129,7 @@ public class SqmStaticFieldReference<T>
);
}
catch (IllegalAccessException e) {
throw new SqmProductionException(
throw new HqlInterpretationException(
"Could not access field value : `"
+ referencedField.getDeclaringClass().getTypeName() + "."
+ referencedField.getName() + "`",
@ -151,7 +149,7 @@ public class SqmStaticFieldReference<T>
);
}
catch (IllegalAccessException e) {
throw new SqmProductionException(
throw new HqlInterpretationException(
"Could not access field value : `"
+ referencedField.getDeclaringClass().getTypeName() + "."
+ referencedField.getName() + "`",
@ -171,7 +169,7 @@ public class SqmStaticFieldReference<T>
);
}
catch (IllegalAccessException e) {
throw new SqmProductionException(
throw new HqlInterpretationException(
"Could not access field value : `"
+ referencedField.getDeclaringClass().getTypeName() + "."
+ referencedField.getName() + "`",

View File

@ -7,10 +7,8 @@
package org.hibernate.query.sqm.produce.spi;
import org.hibernate.Incubating;
import org.hibernate.annotations.Remove;
import org.hibernate.internal.util.collections.Stack;
import org.hibernate.query.sqm.produce.SqmCreationProcessingState;
import org.hibernate.query.sqm.produce.SqmQuerySpecCreationProcessingState;
/**
* Models the state pertaining to the creation of a single SQM.
@ -38,31 +36,7 @@ public interface SqmCreationState {
*/
Stack<SqmCreationProcessingState> getProcessingStateStack();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Would prefer to use NavigablePath to serve the role that uid currently
// serves
String generateUniqueIdentifier();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Below are the methods we want to re-think in terms of how SQM creation
// happens - SqmPath, etc
/**
* @deprecated we want to re-think in terms of how SQM creation happens
*/
@Remove
@Deprecated
ImplicitAliasGenerator getImplicitAliasGenerator();
/**
* @deprecated we want to re-think in terms of how SQM creation happens
*/
@Remove
@Deprecated
SqmQuerySpecCreationProcessingState getCurrentQuerySpecProcessingState();
default SqmCreationProcessingState getCurrentProcessingState() {
return getProcessingStateStack().getCurrent();
}
}

View File

@ -39,7 +39,7 @@ import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.UnknownPathException;
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.SqmJoinType;
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
@ -105,7 +105,6 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
@Override
public SemanticPathPart resolvePathPart(
String name,
String currentContextKey,
boolean isTerminal,
SqmCreationState creationState) {
final NavigablePath subNavPath = getNavigablePath().append( name );

View File

@ -22,7 +22,7 @@ import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.expression.AbstractSqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmExpression;

View File

@ -13,7 +13,7 @@ import org.hibernate.query.PathException;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
/**
@ -51,7 +51,6 @@ public class SqmAnyValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
@Override
public SemanticPathPart resolvePathPart(
String name,
String currentContextKey,
boolean isTerminal,
SqmCreationState creationState) {
return null;

View File

@ -12,7 +12,7 @@ import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
@ -40,7 +40,6 @@ public class SqmBasicValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
@Override
public SemanticPathPart resolvePathPart(
String name,
String currentContextKey,
boolean isTerminal,
SqmCreationState creationState) {
throw new SemanticException( "Basic-valued path [" + getNavigablePath() + "] cannot be de-referenced : " + name );

View File

@ -14,8 +14,8 @@ import org.hibernate.query.sqm.SqmJoinable;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.UnknownPathException;
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
import org.hibernate.query.sqm.produce.SqmPathRegistry;
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SqmPathRegistry;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.SqmJoinType;
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
@ -50,7 +50,6 @@ public class SqmEmbeddedValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
@Override
public SemanticPathPart resolvePathPart(
String name,
String currentContextKey,
boolean isTerminal,
SqmCreationState creationState) {
final SqmPathSource<?> subPathSource = getReferencedPathSource().findSubPathSource( name );

View File

@ -13,7 +13,7 @@ import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
import org.hibernate.query.sqm.produce.SqmCreationHelper;
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
/**
@ -31,7 +31,6 @@ public class SqmEntityValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
@Override
public SemanticPathPart resolvePathPart(
String name,
String currentContextKey,
boolean isTerminal,
SqmCreationState creationState) {
final SqmPathSource referencedPathSource = getReferencedPathSource();

View File

@ -13,7 +13,7 @@ import org.hibernate.query.NavigablePath;
import org.hibernate.query.PathException;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
@ -57,7 +57,6 @@ public class SqmIndexedCollectionAccessPath<T> extends AbstractSqmPath<T> implem
@Override
public SemanticPathPart resolvePathPart(
String name,
String currentContextKey,
boolean isTerminal,
SqmCreationState creationState) {
final SqmPathSource subPathSource = getReferencedPathSource().getElementPathSource().findSubPathSource( name );

View File

@ -11,7 +11,7 @@ import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
/**
@ -32,7 +32,6 @@ public class SqmMaxElementPath<T> extends AbstractSqmSpecificPluralPartPath<T> {
@Override
public SemanticPathPart resolvePathPart(
String name,
String currentContextKey,
boolean isTerminal,
SqmCreationState creationState) {
if ( getPluralAttribute().getElementPathSource().getSqmPathType() instanceof ManagedDomainType ) {

View File

@ -11,7 +11,7 @@ import org.hibernate.metamodel.model.domain.MapPersistentAttribute;
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
/**
@ -46,7 +46,6 @@ public class SqmMaxIndexPath<T> extends AbstractSqmSpecificPluralPartPath<T> {
@Override
public SemanticPathPart resolvePathPart(
String name,
String currentContextKey,
boolean isTerminal,
SqmCreationState creationState) {
return indexPathSource.createSqmPath( this, creationState );

View File

@ -11,7 +11,7 @@ import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
/**
@ -32,7 +32,6 @@ public class SqmMinElementPath<T> extends AbstractSqmSpecificPluralPartPath<T> {
@Override
public SemanticPathPart resolvePathPart(
String name,
String currentContextKey,
boolean isTerminal,
SqmCreationState creationState) {
if ( getPluralAttribute().getElementPathSource().getSqmPathType() instanceof ManagedDomainType ) {

View File

@ -11,7 +11,7 @@ import org.hibernate.metamodel.model.domain.MapPersistentAttribute;
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
/**
@ -46,7 +46,6 @@ public class SqmMinIndexPath<T> extends AbstractSqmSpecificPluralPartPath<T> {
@Override
public SemanticPathPart resolvePathPart(
String name,
String currentContextKey,
boolean isTerminal,
SqmCreationState creationState) {
return indexPathSource.createSqmPath( this, creationState );

View File

@ -15,7 +15,7 @@ import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.SqmExpressable;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.produce.SqmCreationHelper;
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.from.SqmRoot;
@ -88,7 +88,6 @@ public interface SqmPath<T> extends SqmExpression<T>, SemanticPathPart, JpaPath<
@Override
default SqmPath resolveIndexedAccess(
SqmExpression selector,
String currentContextKey,
boolean isTerminal,
SqmCreationState creationState) {
throw new SemanticException( "Non-plural path [" + currentContextKey + "] cannot be index-accessed" );

View File

@ -15,7 +15,7 @@ import org.hibernate.query.NavigablePath;
import org.hibernate.query.PathException;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
/**
@ -65,7 +65,6 @@ public class SqmPluralValuedSimplePath<E> extends AbstractSqmSimplePath<E> {
@SuppressWarnings("unchecked")
public SemanticPathPart resolvePathPart(
String name,
String currentContextKey,
boolean isTerminal,
SqmCreationState creationState) {
// this is a reference to a collection outside of the from-clause...

View File

@ -55,10 +55,9 @@ public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> imple
@Override
public SqmPath resolveIndexedAccess(
SqmExpression selector,
String currentContextKey,
boolean isTerminal,
SqmCreationState creationState) {
return getWrappedPath().resolveIndexedAccess( selector, currentContextKey, isTerminal, creationState );
return getWrappedPath().resolveIndexedAccess( selector, isTerminal, creationState );
}
@Override

View File

@ -0,0 +1,218 @@
/*
* 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 java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import javax.persistence.criteria.Expression;
import org.hibernate.query.SemanticException;
import org.hibernate.query.criteria.JpaSelection;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SqmExpressable;
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.descriptor.java.spi.EnumJavaDescriptor;
/**
* Specialized SQM literal defined by an enum reference. E.g.
* {@code ".. where p.sex = Sex.MALE"}
*
* @author Steve Ebersole
*/
public class SqmEnumLiteral implements SqmExpression<Enum>, SqmExpressable<Enum>, SemanticPathPart {
private final Enum enumValue;
private final EnumJavaDescriptor<Enum> referencedEnumTypeDescriptor;
private final String enumValueName;
private final NodeBuilder nodeBuilder;
private SqmExpressable<Enum> expressable;
public SqmEnumLiteral(
Enum enumValue,
EnumJavaDescriptor<Enum> referencedEnumTypeDescriptor,
String enumValueName,
NodeBuilder nodeBuilder) {
this.enumValue = enumValue;
this.referencedEnumTypeDescriptor = referencedEnumTypeDescriptor;
this.enumValueName = enumValueName;
this.nodeBuilder = nodeBuilder;
this.expressable = this;
}
public Enum getEnumValue() {
return enumValue;
}
public String getEnumValueName() {
return enumValueName;
}
@Override
public EnumJavaDescriptor<Enum> getExpressableJavaTypeDescriptor() {
return referencedEnumTypeDescriptor;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SemanticPathPart
@Override
public SemanticPathPart resolvePathPart(
String name,
boolean isTerminal,
SqmCreationState creationState) {
throw new SemanticException(
String.format(
Locale.ROOT,
"Static enum reference [%s#%s] cannot be de-referenced",
referencedEnumTypeDescriptor.getJavaType().getName(),
enumValueName
)
);
}
@Override
public SqmPath resolveIndexedAccess(
SqmExpression selector,
boolean isTerminal,
SqmCreationState creationState) {
throw new SemanticException(
String.format(
Locale.ROOT,
"Static enum reference [%s#%s] cannot be de-referenced",
referencedEnumTypeDescriptor.getJavaType().getName(),
enumValueName
)
);
}
@Override
public SqmExpressable<Enum> getNodeType() {
return expressable;
}
@Override
public void applyInferableType(SqmExpressable<?> type) {
//noinspection unchecked
this.expressable = (SqmExpressable) type;
}
@Override
public SqmExpression<Long> asLong() {
return nodeBuilder().literal( getExpressableJavaTypeDescriptor().toOrdinal( enumValue ).longValue() );
}
@Override
public SqmExpression<Integer> asInteger() {
return nodeBuilder().literal( getExpressableJavaTypeDescriptor().toOrdinal( enumValue ) );
}
@Override
public SqmExpression<Float> asFloat() {
return nodeBuilder().literal( getExpressableJavaTypeDescriptor().toOrdinal( enumValue ).floatValue() );
}
@Override
public SqmExpression<Double> asDouble() {
return nodeBuilder().literal( getExpressableJavaTypeDescriptor().toOrdinal( enumValue ).doubleValue() );
}
@Override
public SqmExpression<BigDecimal> asBigDecimal() {
throw new UnsupportedOperationException( "Enum literal cannot be cast to BigDecimal" );
}
@Override
public SqmExpression<BigInteger> asBigInteger() {
throw new UnsupportedOperationException( "Enum literal cannot be cast to BigInteger" );
}
@Override
public SqmExpression<String> asString() {
return nodeBuilder().literal( getExpressableJavaTypeDescriptor().toName( enumValue ) );
}
@Override
public <X> SqmExpression<X> as(Class<X> type) {
return nodeBuilder().cast( this, type );
}
@Override
public SqmPredicate isNull() {
return nodeBuilder().isNull( this );
}
@Override
public SqmPredicate isNotNull() {
return nodeBuilder().isNotNull( this );
}
@Override
public SqmPredicate in(Object... values) {
return nodeBuilder().in( this, values );
}
@Override
public SqmPredicate in(Expression<?>... values) {
return nodeBuilder().in( this, values );
}
@Override
public SqmPredicate in(Collection<?> values) {
return nodeBuilder().in( this, values );
}
@Override
public SqmPredicate in(Expression<Collection<?>> values) {
return nodeBuilder().in( this, values );
}
@Override
public <X> X accept(SemanticQueryWalker<X> walker) {
return walker.visitEnumLiteral( this );
}
@Override
public JavaTypeDescriptor<Enum> getJavaTypeDescriptor() {
return getExpressableJavaTypeDescriptor();
}
@Override
public NodeBuilder nodeBuilder() {
return nodeBuilder;
}
@Override
public List<? extends JpaSelection<?>> getSelectionItems() {
// per-JPA
throw new IllegalStateException( "Not a compound selection" );
}
@Override
public boolean isCompoundSelection() {
return false;
}
@Override
public JpaSelection<Enum> alias(String name) {
return null;
}
@Override
public String getAlias() {
return null;
}
}

View File

@ -0,0 +1,226 @@
/*
* 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 java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import javax.persistence.criteria.Expression;
import org.hibernate.query.SemanticException;
import org.hibernate.query.criteria.JpaSelection;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SqmExpressable;
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/**
* @author Steve Ebersole
*/
public class SqmFieldLiteral<T> implements SqmExpression<T>, SqmExpressable<T>, SemanticPathPart {
private final T value;
private final JavaTypeDescriptor<T> fieldOwnerJavaTypeDescriptor;
private final String fieldName;
private final NodeBuilder nodeBuilder;
private SqmExpressable<T> expressable;
public SqmFieldLiteral(
T value,
JavaTypeDescriptor<T> fieldOwnerJavaTypeDescriptor,
String fieldName,
NodeBuilder nodeBuilder) {
this.value = value;
this.fieldOwnerJavaTypeDescriptor = fieldOwnerJavaTypeDescriptor;
this.fieldName = fieldName;
this.nodeBuilder = nodeBuilder;
this.expressable = this;
}
public T getValue() {
return value;
}
public JavaTypeDescriptor<T> getFieldOwnerJavaTypeDescriptor() {
return fieldOwnerJavaTypeDescriptor;
}
public String getFieldName() {
return fieldName;
}
public NodeBuilder getNodeBuilder() {
return nodeBuilder;
}
@Override
public SqmExpressable<T> getNodeType() {
return expressable;
}
@Override
public void applyInferableType(SqmExpressable<?> type) {
//noinspection unchecked
this.expressable = (SqmExpressable) type;
}
@Override
public JavaTypeDescriptor<T> getExpressableJavaTypeDescriptor() {
return expressable.getExpressableJavaTypeDescriptor();
}
@Override
public JavaTypeDescriptor<T> getJavaTypeDescriptor() {
return getExpressableJavaTypeDescriptor();
}
@Override
public <X> X accept(SemanticQueryWalker<X> walker) {
return walker.visitFieldLiteral( this );
}
@Override
public NodeBuilder nodeBuilder() {
return nodeBuilder;
}
@Override
public SqmPredicate isNull() {
return nodeBuilder().isNull( this );
}
@Override
public SqmPredicate isNotNull() {
return nodeBuilder().isNotNull( this );
}
@Override
public SqmPredicate in(Object... values) {
return nodeBuilder().in( this, values );
}
@Override
public SqmPredicate in(Expression<?>... values) {
return nodeBuilder().in( this, values );
}
@Override
public SqmPredicate in(Collection<?> values) {
return nodeBuilder().in( this, values );
}
@Override
public SqmPredicate in(Expression<Collection<?>> values) {
return nodeBuilder().in( this, values );
}
@Override
public SqmExpression<Long> asLong() {
//noinspection unchecked
return (SqmExpression<Long>) this;
}
@Override
public SqmExpression<Integer> asInteger() {
//noinspection unchecked
return (SqmExpression<Integer>) this;
}
@Override
public SqmExpression<Float> asFloat() {
//noinspection unchecked
return (SqmExpression<Float>) this;
}
@Override
public SqmExpression<Double> asDouble() {
//noinspection unchecked
return (SqmExpression<Double>) this;
}
@Override
public SqmExpression<BigDecimal> asBigDecimal() {
//noinspection unchecked
return (SqmExpression<BigDecimal>) this;
}
@Override
public SqmExpression<BigInteger> asBigInteger() {
//noinspection unchecked
return (SqmExpression<BigInteger>) this;
}
@Override
public SqmExpression<String> asString() {
//noinspection unchecked
return (SqmExpression<String>) this;
}
@Override
public <X> SqmExpression<X> as(Class<X> type) {
return null;
}
@Override
public SemanticPathPart resolvePathPart(
String name,
boolean isTerminal,
SqmCreationState creationState) {
throw new SemanticException(
String.format(
Locale.ROOT,
"Static field reference [%s#%s] cannot be de-referenced",
fieldOwnerJavaTypeDescriptor.getJavaType().getName(),
fieldName
)
);
}
@Override
public SqmPath resolveIndexedAccess(
SqmExpression selector,
boolean isTerminal,
SqmCreationState creationState) {
throw new SemanticException(
String.format(
Locale.ROOT,
"Static field reference [%s#%s] cannot be de-referenced",
fieldOwnerJavaTypeDescriptor.getJavaType().getName(),
fieldName
)
);
}
@Override
public boolean isCompoundSelection() {
return false;
}
@Override
public List<? extends JpaSelection<?>> getSelectionItems() {
// per-JPA
throw new IllegalStateException( "Not a compound selection" );
}
@Override
public JpaSelection<T> alias(String name) {
return null;
}
@Override
public String getAlias() {
return null;
}
}

View File

@ -6,15 +6,19 @@
*/
package org.hibernate.query.sqm.tree.expression;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.SqmExpressable;
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
import org.hibernate.sql.ast.produce.metamodel.spi.EntityValuedExpressableType;
import org.hibernate.sql.ast.produce.metamodel.spi.ExpressableType;
import org.hibernate.query.hql.HqlInterpretationException;
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.sql.results.spi.DomainResult;
import org.hibernate.sql.results.spi.DomainResultCreationState;
import org.hibernate.sql.results.spi.DomainResultProducer;
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptor;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/**
* Represents an reference to an entity type as a literal. This is the JPA
@ -25,26 +29,28 @@ import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptor;
*
* @author Steve Ebersole
*/
public class SqmLiteralEntityType<T> extends AbstractSqmExpression<T> implements DomainResultProducer {
private final EntityValuedExpressableType<T> entityType;
public class SqmLiteralEntityType<T>
extends AbstractSqmExpression<T>
implements DomainResultProducer, SemanticPathPart {
private final EntityDomainType<T> entityType;
public SqmLiteralEntityType(EntityValuedExpressableType<T> entityType, NodeBuilder nodeBuilder) {
public SqmLiteralEntityType(EntityDomainType<T> entityType, NodeBuilder nodeBuilder) {
super( entityType, nodeBuilder );
this.entityType = entityType;
}
@Override
public JavaTypeDescriptor<T> getJavaTypeDescriptor() {
return getNodeType().getJavaTypeDescriptor();
return getNodeType().getExpressableJavaTypeDescriptor();
}
@Override
public EntityValuedExpressableType<T> getNodeType() {
public EntityDomainType<T> getNodeType() {
return entityType;
}
@Override
public void internalApplyInferableType(ExpressableType<?> type) {
public void internalApplyInferableType(SqmExpressable<?> type) {
}
@Override
@ -65,4 +71,20 @@ public class SqmLiteralEntityType<T> extends AbstractSqmExpression<T> implements
public String asLoggableText() {
return "TYPE(" + entityType + ")";
}
@Override
public SemanticPathPart resolvePathPart(
String name,
boolean isTerminal,
SqmCreationState creationState) {
throw new HqlInterpretationException( "Cannot dereference an entity name" );
}
@Override
public SqmPath resolveIndexedAccess(
SqmExpression selector,
boolean isTerminal,
SqmCreationState creationState) {
throw new HqlInterpretationException( "Cannot dereference an entity name" );
}
}

View File

@ -18,7 +18,6 @@ import java.util.Locale;
import java.util.Map;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.QueryException;
import org.hibernate.SQLQuery;
@ -30,7 +29,7 @@ import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.MySQL5Dialect;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder;
import org.hibernate.boot.spi.NamedNativeQueryMementoBuilder;
import org.hibernate.transform.BasicTransformerAdapter;
import org.hibernate.transform.DistinctRootEntityResultTransformer;
import org.hibernate.transform.Transformers;
@ -155,7 +154,7 @@ public class NativeSQLQueriesTest extends BaseCoreFunctionalTestCase {
@Test
public void testRegisteredNamedSQLQueryWithScalar()
{
final NamedSQLQueryDefinitionBuilder builder = new NamedSQLQueryDefinitionBuilder();
final NamedNativeQueryMementoBuilder builder = new NamedNativeQueryMementoBuilder();
builder.setName("namedQuery");
builder.setQuery("select count(*) AS c from ORGANIZATION");
builder.setQueryReturns(new NativeSQLQueryReturn[1]);