Implemented NamedQuery creation from Criteria

This commit is contained in:
Andrea Boriero 2022-01-31 17:00:42 +01:00 committed by Andrea Boriero
parent bd5b05cbe3
commit eb572376a9
19 changed files with 414 additions and 224 deletions

View File

@ -55,11 +55,11 @@ import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Table;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.internal.NamedObjectRepositoryImpl;
import org.hibernate.query.named.NamedObjectRepository;
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.type.spi.TypeConfiguration;
@ -346,8 +346,8 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
);
}
private Map<String, NamedHqlQueryMemento> buildNamedHqlMementos(SessionFactoryImplementor sessionFactory) {
final HashMap<String, NamedHqlQueryMemento> map = new HashMap<>();
private Map<String, NamedSqmQueryMemento> buildNamedSqmMementos(SessionFactoryImplementor sessionFactory) {
final HashMap<String, NamedSqmQueryMemento> map = new HashMap<>();
if ( namedQueryMap != null ) {
namedQueryMap.forEach( (key, value) -> map.put( key, value.resolve( sessionFactory ) ) );
}

View File

@ -15,7 +15,7 @@ import org.hibernate.boot.spi.AbstractNamedQueryDefinition;
import org.hibernate.boot.query.NamedHqlQueryDefinition;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
/**
* @author Steve Ebersole
@ -67,7 +67,7 @@ public class NamedHqlQueryDefinitionImpl extends AbstractNamedQueryDefinition im
}
@Override
public NamedHqlQueryMemento resolve(SessionFactoryImplementor factory) {
public NamedSqmQueryMemento resolve(SessionFactoryImplementor factory) {
return new NamedHqlQueryMementoImpl(
getRegistrationName(),
hqlString,

View File

@ -11,7 +11,7 @@ import java.util.Map;
import org.hibernate.boot.internal.NamedHqlQueryDefinitionImpl;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
/**
* Boot-time descriptor of a named HQL query, as defined in
@ -27,7 +27,7 @@ public interface NamedHqlQueryDefinition extends NamedQueryDefinition {
String getHqlString();
@Override
NamedHqlQueryMemento resolve(SessionFactoryImplementor factory);
NamedSqmQueryMemento resolve(SessionFactoryImplementor factory);
class Builder extends AbstractNamedQueryBuilder<Builder> {
private String hqlString;

View File

@ -68,8 +68,8 @@ import org.hibernate.query.QueryTypeMismatchException;
import org.hibernate.query.SelectionQuery;
import org.hibernate.query.UnknownNamedQueryException;
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.hql.spi.SqmQueryImplementor;
import org.hibernate.query.named.NamedObjectRepository;
import org.hibernate.query.named.NamedResultSetMappingMemento;
import org.hibernate.query.spi.HqlInterpretation;
import org.hibernate.query.spi.QueryEngine;
@ -82,6 +82,7 @@ import org.hibernate.query.sqm.SqmSelectionQuery;
import org.hibernate.query.sqm.internal.QuerySqmImpl;
import org.hibernate.query.sqm.internal.SqmSelectionQueryImpl;
import org.hibernate.query.sqm.internal.SqmUtil;
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
import org.hibernate.query.sqm.tree.SqmDmlStatement;
import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
@ -872,12 +873,12 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
// this method can be called for either a named HQL query or a named native query
// first see if it is a named HQL query
final NamedHqlQueryMemento namedHqlDescriptor = getFactory().getQueryEngine()
final NamedSqmQueryMemento namedHqlDescriptor = getFactory().getQueryEngine()
.getNamedObjectRepository()
.getHqlQueryMemento( queryName );
.getSqmQueryMemento( queryName );
if ( namedHqlDescriptor != null ) {
return createNamedHqlSelectionQuery( namedHqlDescriptor, expectedResultType );
return createNamedSqmSelectionQuery( namedHqlDescriptor, expectedResultType );
}
@ -906,13 +907,13 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
);
}
private <R> SqmSelectionQueryImpl<R> createNamedHqlSelectionQuery(
NamedHqlQueryMemento memento,
private <R> SqmSelectionQuery<R> createNamedSqmSelectionQuery(
NamedSqmQueryMemento memento,
Class<R> expectedResultType) {
final SqmSelectionQueryImpl<R> selectionQuery = new SqmSelectionQueryImpl<>( memento, expectedResultType, this );
final SqmSelectionQuery<R> selectionQuery = memento.toSelectionQuery( expectedResultType, this );
if ( StringHelper.isEmpty( memento.getComment() ) ) {
selectionQuery.setComment( "Named HQL query : " + memento.getRegistrationName() );
selectionQuery.setComment( "Named query : " + memento.getRegistrationName() );
}
else {
selectionQuery.setComment( memento.getComment() );
@ -958,7 +959,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
final SqmQueryImplementor query = memento.toQuery( this, resultType );
if ( StringHelper.isEmpty( query.getComment() ) ) {
query.setComment( "dynamic HQL query" );
query.setComment( "dynamic query" );
}
applyQuerySettingsAndHints( query );
if ( memento.getLockOptions() != null ) {
@ -1002,7 +1003,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
@SuppressWarnings("rawtypes")
protected QueryImplementor buildNamedQuery(
String queryName,
Function<NamedHqlQueryMemento, SqmQueryImplementor> namedHqlHandler,
Function<NamedSqmQueryMemento, SqmQueryImplementor> namedSqmHandler,
Function<NamedNativeQueryMemento, NativeQueryImplementor> namedNativeHandler) {
checkOpen();
pulseTransactionCoordinator();
@ -1011,17 +1012,17 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
// this method can be called for either a named HQL query or a named native query
// first see if it is a named HQL query
final NamedHqlQueryMemento namedHqlDescriptor = getFactory().getQueryEngine()
.getNamedObjectRepository()
.getHqlQueryMemento( queryName );
final NamedObjectRepository namedObjectRepository = getFactory().getQueryEngine()
.getNamedObjectRepository();
if ( namedHqlDescriptor != null ) {
return namedHqlHandler.apply( namedHqlDescriptor );
final NamedSqmQueryMemento namedSqmQueryMemento = namedObjectRepository.getSqmQueryMemento( queryName );
if ( namedSqmQueryMemento != null ) {
return namedSqmHandler.apply( namedSqmQueryMemento );
}
// otherwise, see if it is a named native query
final NamedNativeQueryMemento namedNativeDescriptor = getFactory().getQueryEngine()
.getNamedObjectRepository()
final NamedNativeQueryMemento namedNativeDescriptor = namedObjectRepository
.getNativeQueryMemento( queryName );
if ( namedNativeDescriptor != null ) {
@ -1086,17 +1087,17 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
public MutationQuery createNamedMutationQuery(String queryName) {
return buildNamedQuery(
queryName,
(hqlMemento) -> {
final SqmQueryImplementor<?> query = hqlMemento.toQuery( this );
(sqmMemento) -> {
final SqmQueryImplementor<?> query = sqmMemento.toQuery( this );
final SqmStatement<?> sqmStatement = query.getSqmStatement();
if ( !( sqmStatement instanceof SqmDmlStatement ) ) {
throw new IllegalMutationQueryException(
"Expecting a named mutation query (" + queryName + "), but found `" + hqlMemento.getHqlString() + "`"
"Expecting a named mutation query (" + queryName + "), but found a select statement"
);
}
if ( hqlMemento.getLockOptions() != null && ! hqlMemento.getLockOptions().isEmpty() ) {
if ( sqmMemento.getLockOptions() != null && ! sqmMemento.getLockOptions().isEmpty() ) {
throw new IllegalNamedQueryOptionsException(
"Named mutation query `" + queryName + "` specified lock-options"
);

View File

@ -106,10 +106,12 @@ import org.hibernate.proxy.LazyInitializer;
import org.hibernate.query.QueryLogging;
import org.hibernate.query.hql.spi.SqmQueryImplementor;
import org.hibernate.query.named.NamedObjectRepository;
import org.hibernate.query.named.NamedQueryMemento;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.sql.spi.NativeQueryImplementor;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
import org.hibernate.resource.jdbc.spi.StatementInspector;
import org.hibernate.resource.transaction.backend.jta.internal.synchronization.ExceptionMapper;
@ -871,9 +873,11 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
}
else {
namedObjectRepository.registerHqlQueryMemento(
final NamedQueryMemento namedQueryMemento = ( (SqmQueryImplementor<?>) hibernateQuery ).toMemento(
name );
namedObjectRepository.registerSqmQueryMemento(
name,
( (SqmQueryImplementor<?>) hibernateQuery ).toMemento( name )
(NamedSqmQueryMemento) namedQueryMemento
);
}
return;

View File

@ -0,0 +1,134 @@
/*
* 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.criteria.internal;
import java.io.Serializable;
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.spi.SqmQueryImplementor;
import org.hibernate.query.named.AbstractNamedQueryMemento;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.SqmSelectionQuery;
import org.hibernate.query.sqm.internal.QuerySqmImpl;
import org.hibernate.query.sqm.internal.SqmSelectionQueryImpl;
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
import org.hibernate.query.sqm.tree.SqmStatement;
public class NamedCriteriaQueryMementoImpl extends AbstractNamedQueryMemento implements NamedSqmQueryMemento, Serializable {
private final SqmStatement sqmStatement;
private final Integer firstResult;
private final Integer maxResults;
private final LockOptions lockOptions;
private final Map<String, String> parameterTypes;
public NamedCriteriaQueryMementoImpl(
String name,
SqmStatement sqmStatement,
Integer firstResult,
Integer maxResults,
Boolean cacheable,
String cacheRegion,
CacheMode cacheMode,
FlushMode flushMode,
Boolean readOnly,
LockOptions lockOptions,
Integer timeout,
Integer fetchSize,
String comment,
Map<String, String> parameterTypes,
Map<String, Object> hints) {
super( name, cacheable, cacheRegion, cacheMode, flushMode, readOnly, timeout, fetchSize, comment, hints );
this.sqmStatement = sqmStatement;
this.firstResult = firstResult;
this.maxResults = maxResults;
this.lockOptions = lockOptions;
this.parameterTypes = parameterTypes;
}
@Override
public void validate(QueryEngine queryEngine) {
}
@Override
public <T> SqmQueryImplementor<T> toQuery(SharedSessionContractImplementor session, Class<T> resultType) {
return new QuerySqmImpl<>( this, resultType, session );
}
@Override
public <T> SqmQueryImplementor<T> toQuery(SharedSessionContractImplementor session) {
return toQuery(session, null);
}
@Override
public <T> SqmSelectionQuery<T> toSelectionQuery(Class<T> resultType, SharedSessionContractImplementor session) {
return new SqmSelectionQueryImpl<>(
this,
resultType,
session
);
}
@Override
public String getHqlString() {
return QuerySqmImpl.CRITERIA_HQL_STRING;
}
@Override
public SqmStatement getSqmStatement() {
return sqmStatement;
}
@Override
public Integer getFirstResult() {
return firstResult;
}
@Override
public Integer getMaxResults() {
return maxResults;
}
@Override
public LockOptions getLockOptions() {
return lockOptions;
}
@Override
public Map<String, String> getParameterTypes() {
return parameterTypes;
}
@Override
public NamedSqmQueryMemento makeCopy(String name) {
return new NamedCriteriaQueryMementoImpl(
name,
sqmStatement,
firstResult,
maxResults,
getCacheable(),
getCacheRegion(),
getCacheMode(),
getFlushMode(),
getReadOnly(),
lockOptions,
getTimeout(),
getFetchSize(),
getComment(),
parameterTypes,
getHints()
);
}
}

View File

@ -13,11 +13,14 @@ import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockOptions;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.hql.spi.SqmQueryImplementor;
import org.hibernate.query.named.AbstractNamedQueryMemento;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.SqmSelectionQuery;
import org.hibernate.query.sqm.internal.QuerySqmImpl;
import org.hibernate.query.sqm.internal.SqmSelectionQueryImpl;
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
import org.hibernate.query.sqm.tree.SqmStatement;
import org.jboss.logging.Logger;
@ -30,7 +33,7 @@ import org.jboss.logging.Logger;
* @author Gavin King
* @author Steve Ebersole
*/
public class NamedHqlQueryMementoImpl extends AbstractNamedQueryMemento implements NamedHqlQueryMemento, Serializable {
public class NamedHqlQueryMementoImpl extends AbstractNamedQueryMemento implements NamedSqmQueryMemento, Serializable {
private static final Logger log = Logger.getLogger( NamedHqlQueryMementoImpl.class );
private final String hqlString;
@ -102,7 +105,7 @@ public class NamedHqlQueryMementoImpl extends AbstractNamedQueryMemento implemen
}
@Override
public NamedHqlQueryMemento makeCopy(String name) {
public NamedSqmQueryMemento makeCopy(String name) {
return new NamedHqlQueryMementoImpl(
name,
hqlString,
@ -124,7 +127,7 @@ public class NamedHqlQueryMementoImpl extends AbstractNamedQueryMemento implemen
@Override
public void validate(QueryEngine queryEngine) {
queryEngine.getHqlTranslator().translate( getHqlString() );
queryEngine.getHqlTranslator().translate( hqlString );
}
@Override
@ -132,6 +135,20 @@ public class NamedHqlQueryMementoImpl extends AbstractNamedQueryMemento implemen
return toQuery( session, null );
}
@Override
public <T> SqmSelectionQuery<T> toSelectionQuery(Class<T> resultType, SharedSessionContractImplementor session) {
return new SqmSelectionQueryImpl<>(
this,
resultType,
session
);
}
@Override
public SqmStatement getSqmStatement() {
return null;
}
@Override
public <T> SqmQueryImplementor<T> toQuery(SharedSessionContractImplementor session, Class<T> resultType) {
return new QuerySqmImpl<>( this, resultType, session );

View File

@ -14,6 +14,6 @@
*
* @see org.hibernate.query.hql.HqlTranslator
* @see org.hibernate.query.hql.spi.SqmQueryImplementor
* @see org.hibernate.query.hql.spi.NamedHqlQueryMemento
* @see org.hibernate.query.sqm.spi.NamedSqmQueryMemento
*/
package org.hibernate.query.hql;

View File

@ -1,128 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.query.hql.spi;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.LockOptions;
import org.hibernate.boot.query.NamedHqlQueryDefinition;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
import org.hibernate.query.named.AbstractNamedQueryMemento;
import org.hibernate.query.named.NameableQuery;
import org.hibernate.query.named.NamedQueryMemento;
/**
* NamedQueryMemento for HQL queries
*
* @author Steve Ebersole
*/
public interface NamedHqlQueryMemento extends NamedQueryMemento {
/**
* Informational access to the HQL query string
*/
String getHqlString();
/**
* Convert the memento into a typed executable query
*/
<T> SqmQueryImplementor<T> toQuery(SharedSessionContractImplementor session, Class<T> resultType);
/**
* Convert the memento into an untyped executable query
*/
<T> SqmQueryImplementor<T> toQuery(SharedSessionContractImplementor session);
Integer getFirstResult();
Integer getMaxResults();
LockOptions getLockOptions();
Map<String, String> getParameterTypes();
@Override
NamedHqlQueryMemento makeCopy(String name);
/**
* Delegate used in creating named HQL query mementos.
*
* @see NamedHqlQueryDefinition
* @see NameableQuery#toMemento
*/
class Builder extends AbstractNamedQueryMemento.AbstractBuilder<Builder> {
protected String hqlString;
protected LockOptions lockOptions;
protected Integer firstResult;
protected Integer maxResults;
protected Map<String,String> parameterTypes;
public Builder(String name) {
super( name );
}
@Override
protected Builder getThis() {
return this;
}
public Builder setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
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<String,String> 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,
hqlString,
firstResult,
maxResults,
cacheable,
cacheRegion,
cacheMode,
flushMode,
readOnly,
lockOptions,
timeout,
fetchSize,
comment,
parameterTypes,
hints
);
}
}
}

View File

@ -23,6 +23,7 @@ import org.hibernate.query.QueryParameter;
import org.hibernate.query.ResultListTransformer;
import org.hibernate.query.TupleTransformer;
import org.hibernate.query.named.NameableQuery;
import org.hibernate.query.named.NamedQueryMemento;
import org.hibernate.query.spi.ParameterMetadataImplementor;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.spi.SqmQuery;
@ -41,7 +42,7 @@ import jakarta.persistence.TemporalType;
*/
public interface SqmQueryImplementor<R> extends QueryImplementor<R>, SqmQuery, NameableQuery {
@Override
NamedHqlQueryMemento toMemento(String name);
NamedQueryMemento toMemento(String name);
@Override
ParameterMetadataImplementor getParameterMetadata();

View File

@ -19,13 +19,13 @@ import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.named.NamedObjectRepository;
import org.hibernate.query.named.NamedQueryMemento;
import org.hibernate.query.named.NamedResultSetMappingMemento;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryInterpretationCache;
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
import org.jboss.logging.Logger;
@ -35,17 +35,17 @@ import org.jboss.logging.Logger;
public class NamedObjectRepositoryImpl implements NamedObjectRepository {
private static final Logger log = Logger.getLogger( NamedObjectRepository.class );
private final Map<String, NamedHqlQueryMemento> hqlMementoMap;
private final Map<String, NamedSqmQueryMemento> sqmMementoMap;
private final Map<String, NamedNativeQueryMemento> sqlMementoMap;
private final Map<String, NamedCallableQueryMemento> callableMementoMap;
private final Map<String, NamedResultSetMappingMemento> resultSetMappingMementoMap;
public NamedObjectRepositoryImpl(
Map<String,NamedHqlQueryMemento> hqlMementoMap,
Map<String,NamedSqmQueryMemento> sqmMementoMap,
Map<String,NamedNativeQueryMemento> sqlMementoMap,
Map<String,NamedCallableQueryMemento> callableMementoMap,
Map<String,NamedResultSetMappingMemento> resultSetMappingMementoMap) {
this.hqlMementoMap = hqlMementoMap;
this.sqmMementoMap = sqmMementoMap;
this.sqlMementoMap = sqlMementoMap;
this.callableMementoMap = callableMementoMap;
this.resultSetMappingMementoMap = resultSetMappingMementoMap;
@ -53,25 +53,24 @@ public class NamedObjectRepositoryImpl implements NamedObjectRepository {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HQL mementos
// Named SQM Memento
@Override
public NamedHqlQueryMemento getHqlQueryMemento(String queryName) {
return hqlMementoMap.get( queryName );
public NamedSqmQueryMemento getSqmQueryMemento(String queryName) {
return sqmMementoMap.get( queryName );
}
@Override
public void visitHqlQueryMementos(Consumer<NamedHqlQueryMemento> action) {
hqlMementoMap.values().forEach( action );
public void visitSqmQueryMementos(Consumer<NamedSqmQueryMemento> action) {
sqmMementoMap.values().forEach( action );
}
@Override
public synchronized void registerHqlQueryMemento(String name, NamedHqlQueryMemento descriptor) {
hqlMementoMap.put( name, descriptor );
public void registerSqmQueryMemento(String name, NamedSqmQueryMemento descriptor) {
sqmMementoMap.put( name, descriptor );
sqlMementoMap.remove( name );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SQL mementos
@ -88,7 +87,7 @@ public class NamedObjectRepositoryImpl implements NamedObjectRepository {
@Override
public synchronized void registerNativeQueryMemento(String name, NamedNativeQueryMemento descriptor) {
sqlMementoMap.put( name, descriptor );
hqlMementoMap.remove( name );
sqmMementoMap.remove( name );
}
@ -138,11 +137,11 @@ public class NamedObjectRepositoryImpl implements NamedObjectRepository {
SessionFactoryImplementor sessionFactory,
MetadataImplementor bootMetamodel,
String registrationName) {
NamedQueryMemento namedQuery = hqlMementoMap.get( registrationName );
NamedQueryMemento namedQuery = sqlMementoMap.get( registrationName );
if ( namedQuery != null ) {
return namedQuery;
}
namedQuery = sqlMementoMap.get( registrationName );
namedQuery = sqmMementoMap.get( registrationName );
if ( namedQuery != null ) {
return namedQuery;
}
@ -152,8 +151,8 @@ public class NamedObjectRepositoryImpl implements NamedObjectRepository {
}
final NamedHqlQueryDefinition namedHqlQueryDefinition = bootMetamodel.getNamedHqlQueryMapping( registrationName );
if ( namedHqlQueryDefinition != null ) {
final NamedHqlQueryMemento resolved = namedHqlQueryDefinition.resolve( sessionFactory );
hqlMementoMap.put( namedHqlQueryDefinition.getRegistrationName(), resolved );
final NamedSqmQueryMemento resolved = namedHqlQueryDefinition.resolve( sessionFactory );
sqmMementoMap.put( namedHqlQueryDefinition.getRegistrationName(), resolved );
return resolved;
}
final NamedNativeQueryDefinition namedNativeQueryDefinition = bootMetamodel.getNamedNativeQueryMapping( registrationName );
@ -178,8 +177,8 @@ public class NamedObjectRepositoryImpl implements NamedObjectRepository {
BootstrapContext bootstrapContext) {
bootMetamodel.visitNamedHqlQueryDefinitions(
namedHqlQueryDefinition -> {
final NamedHqlQueryMemento resolved = namedHqlQueryDefinition.resolve( sessionFactory );
hqlMementoMap.put( namedHqlQueryDefinition.getRegistrationName(), resolved );
final NamedSqmQueryMemento resolved = namedHqlQueryDefinition.resolve( sessionFactory );
sqmMementoMap.put( namedHqlQueryDefinition.getRegistrationName(), resolved );
}
);
@ -218,8 +217,8 @@ public class NamedObjectRepositoryImpl implements NamedObjectRepository {
final boolean cachingEnabled = interpretationCache.isEnabled();
// Check named HQL queries
log.debugf( "Checking %s named HQL queries", hqlMementoMap.size() );
for ( NamedHqlQueryMemento hqlMemento : hqlMementoMap.values() ) {
log.debugf( "Checking %s named HQL queries", sqmMementoMap.size() );
for ( NamedSqmQueryMemento hqlMemento : sqmMementoMap.values() ) {
try {
log.debugf( "Checking named HQL query: %s", hqlMemento.getRegistrationName() );
String queryString = hqlMemento.getHqlString();
@ -277,7 +276,7 @@ public class NamedObjectRepositoryImpl implements NamedObjectRepository {
@Override
public void close() {
hqlMementoMap.clear();
sqmMementoMap.clear();
sqlMementoMap.clear();
callableMementoMap.clear();
resultSetMappingMementoMap.clear();

View File

@ -15,9 +15,9 @@ import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
/**
* Repository for references to named things related with queries. This includes
@ -30,11 +30,11 @@ import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
public interface NamedObjectRepository {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Named HQL Memento
// Named SQM Memento
NamedHqlQueryMemento getHqlQueryMemento(String queryName);
void visitHqlQueryMementos(Consumer<NamedHqlQueryMemento> action);
void registerHqlQueryMemento(String name, NamedHqlQueryMemento descriptor);
NamedSqmQueryMemento getSqmQueryMemento(String queryName);
void visitSqmQueryMementos(Consumer<NamedSqmQueryMemento> action);
void registerSqmQueryMemento(String name, NamedSqmQueryMemento descriptor);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -48,11 +48,11 @@ import org.hibernate.query.QueryParameter;
import org.hibernate.query.QueryTypeMismatchException;
import org.hibernate.query.SelectionQuery;
import org.hibernate.query.criteria.JpaSelection;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.internal.ScrollableResultsIterator;
import org.hibernate.query.named.NamedQueryMemento;
import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.from.SqmRoot;
@ -127,7 +127,7 @@ public abstract class AbstractSelectionQuery<R>
return null;
}
protected void applyOptions(NamedHqlQueryMemento memento) {
protected void applyOptions(NamedSqmQueryMemento memento) {
applyOptions( (NamedQueryMemento) memento );
if ( memento.getFirstResult() != null ) {

View File

@ -7,7 +7,6 @@
package org.hibernate.query.sqm.internal;
import java.io.Serializable;
import java.sql.Types;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
@ -16,7 +15,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;
@ -26,7 +24,6 @@ import jakarta.persistence.LockModeType;
import jakarta.persistence.Parameter;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.TemporalType;
import jakarta.persistence.Tuple;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
@ -47,8 +44,6 @@ import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.collections.IdentitySet;
import org.hibernate.metamodel.model.domain.BasicDomainType;
import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.BindableType;
@ -57,17 +52,17 @@ import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
import org.hibernate.query.Query;
import org.hibernate.query.QueryLogging;
import org.hibernate.query.QueryParameter;
import org.hibernate.query.QueryTypeMismatchException;
import org.hibernate.query.ResultListTransformer;
import org.hibernate.query.SemanticException;
import org.hibernate.query.TupleTransformer;
import org.hibernate.query.criteria.internal.NamedCriteriaQueryMementoImpl;
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
import org.hibernate.query.hql.internal.QuerySplitter;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.hql.spi.SqmQueryImplementor;
import org.hibernate.query.internal.DelegatingDomainQueryExecutionContext;
import org.hibernate.query.internal.ParameterMetadataImpl;
import org.hibernate.query.internal.QueryParameterBindingsImpl;
import org.hibernate.query.named.NamedQueryMemento;
import org.hibernate.query.spi.AbstractSelectionQuery;
import org.hibernate.query.spi.DomainQueryExecutionContext;
import org.hibernate.query.spi.HqlInterpretation;
@ -80,8 +75,6 @@ import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.query.spi.SelectQueryPlan;
import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.internal.SqmInterpretationsKey.InterpretationsKeySource;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
@ -93,19 +86,15 @@ import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.from.SqmRoot;
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
import org.hibernate.query.sqm.tree.insert.SqmInsertStatement;
import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement;
import org.hibernate.query.sqm.tree.insert.SqmValues;
import org.hibernate.query.sqm.tree.select.SqmQueryGroup;
import org.hibernate.query.sqm.tree.select.SqmQueryPart;
import org.hibernate.query.sqm.tree.select.SqmQuerySpec;
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
import org.hibernate.query.sqm.tree.select.SqmSelection;
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
import org.hibernate.sql.results.internal.TupleMetadata;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import static org.hibernate.jpa.HibernateHints.HINT_CACHEABLE;
import static org.hibernate.jpa.HibernateHints.HINT_CACHE_MODE;
@ -150,7 +139,7 @@ public class QuerySqmImpl<R>
* Creates a Query instance from a named HQL memento
*/
public QuerySqmImpl(
NamedHqlQueryMemento memento,
NamedHqlQueryMementoImpl memento,
Class<R> resultType,
SharedSessionContractImplementor session) {
super( session );
@ -176,10 +165,20 @@ public class QuerySqmImpl<R>
validateStatement( sqm, resultType );
setComment( hql );
applyOptions( memento );
this.tupleMetadata = buildTupleMetadata( sqm, resultType );
}
public QuerySqmImpl(
NamedCriteriaQueryMementoImpl memento,
Class<R> resultType,
SharedSessionContractImplementor session) {
this( memento.getSqmStatement(), resultType, session );
applyOptions( memento );
}
/**
* Form used for HQL queries
*/
@ -1008,9 +1007,33 @@ public class QuerySqmImpl<R>
// Named query externalization
@Override
public NamedHqlQueryMemento toMemento(String name) {
public NamedQueryMemento toMemento(String name) {
if ( CRITERIA_HQL_STRING.equals( getQueryString() ) ) {
throw new UnsupportedOperationException( "Criteria-based Query cannot be saved as a named query" );
final SqmStatement sqmStatement ;
if ( !getSession().isJpaCriteriaCopyComplianceEnabled() ) {
sqmStatement = getSqmStatement().copy( SqmCopyContext.simpleContext() );
}
else {
// the statement has already been copied
sqmStatement = getSqmStatement();
}
return new NamedCriteriaQueryMementoImpl(
name,
sqmStatement,
getFirstResult(),
getMaxResults(),
isCacheable(),
getCacheRegion(),
getCacheMode(),
getHibernateFlushMode(),
isReadOnly(),
getLockOptions(),
getTimeout(),
getFetchSize(),
getComment(),
Collections.emptyMap(),
getHints()
);
}
return new NamedHqlQueryMementoImpl(

View File

@ -12,7 +12,6 @@ import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.Supplier;
import jakarta.persistence.FlushModeType;
@ -34,12 +33,11 @@ import org.hibernate.internal.util.collections.IdentitySet;
import org.hibernate.jpa.internal.util.FlushModeTypeHelper;
import org.hibernate.jpa.internal.util.LockModeTypeHelper;
import org.hibernate.query.BindableType;
import org.hibernate.query.IllegalSelectQueryException;
import org.hibernate.query.QueryLogging;
import org.hibernate.query.QueryParameter;
import org.hibernate.query.QueryTypeMismatchException;
import org.hibernate.query.criteria.internal.NamedCriteriaQueryMementoImpl;
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
import org.hibernate.query.hql.internal.QuerySplitter;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.internal.DelegatingDomainQueryExecutionContext;
import org.hibernate.query.internal.ParameterMetadataImpl;
import org.hibernate.query.internal.QueryParameterBindingsImpl;
@ -56,6 +54,7 @@ import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.query.spi.SelectQueryPlan;
import org.hibernate.query.sqm.SqmSelectionQuery;
import org.hibernate.query.sqm.internal.SqmInterpretationsKey.InterpretationsKeySource;
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
@ -114,7 +113,7 @@ public class SqmSelectionQueryImpl<R> extends AbstractSelectionQuery<R> implemen
}
public SqmSelectionQueryImpl(
NamedHqlQueryMemento memento,
NamedHqlQueryMementoImpl memento,
Class<R> resultType,
SharedSessionContractImplementor session) {
super( session );
@ -145,6 +144,14 @@ public class SqmSelectionQueryImpl<R> extends AbstractSelectionQuery<R> implemen
this.tupleMetadata = buildTupleMetadata( sqm, resultType );
}
public SqmSelectionQueryImpl(
NamedCriteriaQueryMementoImpl memento,
Class<R> resultType,
SharedSessionContractImplementor session) {
this( (SqmSelectStatement<R>) memento.getSqmStatement(), session);
applyOptions( memento );
}
public SqmSelectionQueryImpl(
SqmSelectStatement<R> criteria,
SharedSessionContractImplementor session) {

View File

@ -0,0 +1,44 @@
/*
* 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.spi;
import java.util.Map;
import org.hibernate.LockOptions;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.query.hql.spi.SqmQueryImplementor;
import org.hibernate.query.named.NamedQueryMemento;
import org.hibernate.query.sqm.SqmSelectionQuery;
import org.hibernate.query.sqm.tree.SqmStatement;
public interface NamedSqmQueryMemento extends NamedQueryMemento {
<T> SqmQueryImplementor<T> toQuery(SharedSessionContractImplementor session, Class<T> resultType);
/**
* Convert the memento into an untyped executable query
*/
<T> SqmQueryImplementor<T> toQuery(SharedSessionContractImplementor session);
<T> SqmSelectionQuery<T> toSelectionQuery(Class<T> resultType, SharedSessionContractImplementor session);
String getHqlString();
SqmStatement getSqmStatement();
Integer getFirstResult();
Integer getMaxResults();
LockOptions getLockOptions();
Map<String, String> getParameterTypes();
@Override
NamedSqmQueryMemento makeCopy(String name);
}

View File

@ -0,0 +1,88 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.orm.test.jpa.compliance;
import java.util.List;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jpa;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Root;
import static org.junit.jupiter.api.Assertions.assertEquals;
@Jpa(
annotatedClasses = NamedQueryTest.Person.class
)
public class NamedQueryTest {
@BeforeEach
public void setup(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
Person person1 = new Person( 1, "Andrea" );
Person person2 = new Person( 2, "Alberto" );
entityManager.persist( person1 );
entityManager.persist( person2 );
}
);
}
@Test
public void testNameQueryCreationFromCritera(EntityManagerFactoryScope scope) {
final EntityManagerFactory entityManagerFactory = scope.getEntityManagerFactory();
scope.inEntityManager(
entityManager -> {
final CriteriaBuilder criteriaBuilder = entityManagerFactory.getCriteriaBuilder();
final CriteriaQuery<Integer> query = criteriaBuilder.createQuery( Integer.class );
final Root<Person> person = query.from( Person.class );
query.select( person.get( "id" ) );
query.where( criteriaBuilder.equal( person.get( "name" ), "Alberto" ) );
entityManagerFactory.addNamedQuery( "criteria_query", entityManager.createQuery( query ) );
List<Integer> ids = entityManager.createNamedQuery( "criteria_query", Integer.class )
.getResultList();
assertEquals( 1, ids.size() );
assertEquals( 2, ids.get( 0 ) );
}
);
}
@Entity(name = "Person")
@Table(name = "PERSON_TABLE")
public static class Person {
@Id
private Integer id;
private String name;
public Person() {
}
public Person(Integer id, String name) {
this.id = id;
this.name = name;
}
}
}

View File

@ -13,7 +13,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.orm.test.jpa.Distributor;
import org.hibernate.orm.test.jpa.Item;
import org.hibernate.orm.test.jpa.Wallet;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jpa;
@ -108,9 +108,9 @@ public class AddNamedQueryTest {
// first, lets check the underlying stored query def
SessionFactoryImplementor sfi = scope.getEntityManagerFactory()
.unwrap( SessionFactoryImplementor.class );
NamedHqlQueryMemento def = sfi.getQueryEngine()
NamedSqmQueryMemento def = sfi.getQueryEngine()
.getNamedObjectRepository()
.getHqlQueryMemento( name );
.getSqmQueryMemento( name );
assertEquals( LockMode.OPTIMISTIC, def.getLockOptions().getLockMode() );
// then lets create a query by name and check its setting
@ -139,9 +139,9 @@ public class AddNamedQueryTest {
// first, lets check the underlying stored query def
SessionFactoryImplementor sfi = scope.getEntityManagerFactory()
.unwrap( SessionFactoryImplementor.class );
NamedHqlQueryMemento def = sfi.getQueryEngine()
NamedSqmQueryMemento def = sfi.getQueryEngine()
.getNamedObjectRepository()
.getHqlQueryMemento( name );
.getSqmQueryMemento( name );
assertEquals( FlushMode.COMMIT, def.getFlushMode() );
// then lets create a query by name and check its setting

View File

@ -10,9 +10,9 @@ import jakarta.persistence.FlushModeType;
import org.hibernate.CacheMode;
import org.hibernate.query.Query;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.named.NamedObjectRepository;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
@ -35,10 +35,10 @@ public class SimpleNamedQueryTests {
.getQueryEngine()
.getNamedObjectRepository();
final NamedHqlQueryMemento simpleMemento = namedObjectRepository.getHqlQueryMemento( "simple" );
final NamedSqmQueryMemento simpleMemento = namedObjectRepository.getSqmQueryMemento( "simple" );
assertThat( simpleMemento, notNullValue() );
final NamedHqlQueryMemento restrictedMemento = namedObjectRepository.getHqlQueryMemento( "restricted" );
final NamedSqmQueryMemento restrictedMemento = namedObjectRepository.getSqmQueryMemento( "restricted" );
assertThat( restrictedMemento, notNullValue() );
}
@ -54,10 +54,10 @@ public class SimpleNamedQueryTests {
.getQueryEngine()
.getNamedObjectRepository();
final NamedHqlQueryMemento simpleMemento = namedObjectRepository.getHqlQueryMemento( "simple" );
final NamedSqmQueryMemento simpleMemento = namedObjectRepository.getSqmQueryMemento( "simple" );
assertThat( simpleMemento, notNullValue() );
final NamedHqlQueryMemento restrictedMemento = namedObjectRepository.getHqlQueryMemento( "restricted" );
final NamedSqmQueryMemento restrictedMemento = namedObjectRepository.getSqmQueryMemento( "restricted" );
assertThat( restrictedMemento, notNullValue() );
}