Skip to content

HHH-19364 QuerySpecification with base criteria query #10047

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -667,11 +667,26 @@ public <T> SelectionSpecification<T> createSelectionSpecification(Class<T> rootE
return delegate.createSelectionSpecification( rootEntityType );
}

@Override
public <T> SelectionSpecification<T> createSelectionSpecification(CriteriaQuery<T> criteria) {
return delegate.createSelectionSpecification( criteria );
}

@Override
public <T> MutationSpecification<T> createMutationSpecification(String hql, Class<T> mutationTarget) {
return delegate.createMutationSpecification( hql, mutationTarget );
}

@Override
public <T> MutationSpecification<T> createMutationSpecification(CriteriaUpdate<T> criteriaUpdate) {
return delegate.createMutationSpecification( criteriaUpdate );
}

@Override
public <T> MutationSpecification<T> createMutationSpecification(CriteriaDelete<T> criteriaDelete) {
return delegate.createMutationSpecification( criteriaDelete );
}

@Override
public MutationQuery createNativeMutationQuery(String sqlString) {
return delegate.createNativeMutationQuery( sqlString );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -760,11 +760,26 @@ public <T> SelectionSpecification<T> createSelectionSpecification(Class<T> rootE
return this.lazySession.get().createSelectionSpecification( rootEntityType );
}

@Override
public <T> SelectionSpecification<T> createSelectionSpecification(CriteriaQuery<T> criteria) {
return this.lazySession.get().createSelectionSpecification( criteria );
}

@Override
public <T> MutationSpecification<T> createMutationSpecification(String hql, Class<T> mutationTarget) {
return this.lazySession.get().createMutationSpecification( hql, mutationTarget );
}

@Override
public <T> MutationSpecification<T> createMutationSpecification(CriteriaUpdate<T> criteriaUpdate) {
return this.lazySession.get().createMutationSpecification( criteriaUpdate );
}

@Override
public <T> MutationSpecification<T> createMutationSpecification(CriteriaDelete<T> criteriaDelete) {
return this.lazySession.get().createMutationSpecification( criteriaDelete );
}

@SuppressWarnings("rawtypes")
@Override
@Deprecated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,26 @@ public <T> SelectionSpecification<T> createSelectionSpecification(Class<T> rootE
return delegate.createSelectionSpecification( rootEntityType );
}

@Override
public <T> SelectionSpecification<T> createSelectionSpecification(CriteriaQuery<T> criteria) {
return delegate.createSelectionSpecification( criteria );
}

@Override
public <T> MutationSpecification<T> createMutationSpecification(String hql, Class<T> mutationTarget) {
return delegate.createMutationSpecification( hql, mutationTarget );
}

@Override
public <T> MutationSpecification<T> createMutationSpecification(CriteriaUpdate<T> criteriaUpdate) {
return delegate.createMutationSpecification( criteriaUpdate );
}

@Override
public <T> MutationSpecification<T> createMutationSpecification(CriteriaDelete<T> criteriaDelete) {
return delegate.createMutationSpecification( criteriaDelete );
}

@Override
public MutationQuery createNativeMutationQuery(String sqlString) {
return delegate.createNativeMutationQuery( sqlString );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1270,11 +1270,26 @@ public <T> SelectionSpecification<T> createSelectionSpecification(Class<T> rootE
return new SelectionSpecificationImpl<>( rootEntityType, this );
}

@Override
public <T> SelectionSpecification<T> createSelectionSpecification(CriteriaQuery<T> criteria) {
return new SelectionSpecificationImpl<>( criteria, this );
}

@Override
public <T> MutationSpecification<T> createMutationSpecification(String hql, Class<T> mutationTarget) {
return new MutationSpecificationImpl<>( hql, mutationTarget, this );
}

@Override
public <T> MutationSpecification<T> createMutationSpecification(CriteriaDelete<T> criteriaDelete) {
return new MutationSpecificationImpl<>( criteriaDelete, this );
}

@Override
public <T> MutationSpecification<T> createMutationSpecification(CriteriaUpdate<T> criteriaUpdate) {
return new MutationSpecificationImpl<>( criteriaUpdate, this );
}

protected <T> NativeQueryImplementor<T> createNativeQueryImplementor(String queryName, NamedNativeQueryMemento<T> memento) {
final NativeQueryImplementor<T> query = memento.toQuery( this );
final Boolean isUnequivocallySelect = query.isSelectQuery();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,8 @@ public interface QueryProducer {
*
* @throws IllegalSelectQueryException The given HQL is expected to be a {@code select} query. This method will
* throw an exception if not.
*
* @since 7.0
*/
@Incubating
<T> SelectionSpecification<T> createSelectionSpecification(String hql, Class<T> resultType)
Expand All @@ -530,10 +532,27 @@ <T> SelectionSpecification<T> createSelectionSpecification(String hql, Class<T>
*
* @param <T> The entity type which is the root of the query.
* {@code resultType} and {@code <T>} are both expected to refer to a singular query root.
*
* @since 7.0
*/
@Incubating
<T> SelectionSpecification<T> createSelectionSpecification(Class<T> rootEntityType);

/**
* Returns a specification reference which can be used to programmatically,
* iteratively build a {@linkplain SelectionQuery} for the given criteria query,
* allowing the addition of {@linkplain SelectionSpecification#addOrdering sorting}
* and {@linkplain SelectionSpecification#addRestriction restrictions}.
*
* @param criteria The criteria query
*
* @param <T> The entity type which is the root of the query.
*
* @since 7.0
*/
@Incubating
<T> SelectionSpecification<T> createSelectionSpecification(CriteriaQuery<T> criteria);

/**
* Returns a specification reference which can be used to programmatically,
* iteratively build a {@linkplain MutationQuery} based on a base HQL statement,
Expand All @@ -547,11 +566,41 @@ <T> SelectionSpecification<T> createSelectionSpecification(String hql, Class<T>
*
* @throws IllegalMutationQueryException Only {@code update} and {@code delete} are supported;
* this method will throw an exception if the given HQL query is not an {@code update} or {@code delete}.
*
* @since 7.0
*/
@Incubating
<T> MutationSpecification<T> createMutationSpecification(String hql, Class<T> mutationTarget)
throws IllegalMutationQueryException;

/**
* Returns a specification reference which can be used to programmatically,
* iteratively build a {@linkplain MutationQuery} based on the given criteria update,
* allowing the addition of {@linkplain MutationSpecification#addRestriction restrictions}.
*
* @param criteriaUpdate The criteria update query
*
* @param <T> The root entity type for the mutation (the "target").
*
* @since 7.0
*/
@Incubating
<T> MutationSpecification<T> createMutationSpecification(CriteriaUpdate<T> criteriaUpdate);

/**
* Returns a specification reference which can be used to programmatically,
* iteratively build a {@linkplain MutationQuery} based on the given criteria delete,
* allowing the addition of {@linkplain MutationSpecification#addRestriction restrictions}.
*
* @param criteriaDelete The criteria delete query
*
* @param <T> The root entity type for the mutation (the "target").
*
* @since 7.0
*/
@Incubating
<T> MutationSpecification<T> createMutationSpecification(CriteriaDelete<T> criteriaDelete);

/**
* Create a {@link Query} instance for the named query.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,6 @@
* every {@link jakarta.persistence.FetchType#EAGER eager} {@code @ManyToOne} or
* {@code @OneToOne} association belonging to an entity returned by the query.
* <p>
* The method {@link #addRestriction(Restriction)} allows application of additional
* {@linkplain Restriction filtering} to the query results. The static factory
* methods of {@code Restriction} are used to express filtering criteria of various
* kinds.
* <p>
* Finally, two alternative approaches to pagination are available:
* <ol>
* <li>
Expand All @@ -114,10 +109,9 @@
* {@link #setFirstResult(int)} and {@link #setMaxResults(int)}.
* <pre>
* session.createSelectionQuery("from Book", Book.class)
* .addRestriction(Restriction.contains(Book_.title, "hibernate", false))
* .setOrder(Order.desc(Book_.title))
* .setPage(Page.first(50))
* .getResultList() );
* .getResultList();
* </pre>
* <li>
* On the other hand, {@link KeyedPage} and {@link KeyedResultList}, along with
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,23 @@
import org.hibernate.query.restriction.Restriction;

/**
* Specialization of QuerySpecification for building
* Specialization of {@link QuerySpecification} for programmatic customization of
* {@linkplain MutationQuery mutation queries}.
* Once all {@linkplain #addRestriction restrictions} are defined, call
* {@linkplain #createQuery()} to obtain the executable form.
* <p>
* The method {@link #addRestriction(Restriction)} allows application of additional
* {@linkplain Restriction filtering} to the mutated entity. The static factory
* methods of {@link Restriction} are used to express filtering criteria of various
* kinds.
* <p>
* Once all {@linkplain #addRestriction restrictions} are specified, call
* {@linkplain #createQuery()} to obtain an {@linkplain SelectionQuery an
* executable mutation query object}.
*
* @param <T> The entity type which is the target of the mutation.
*
* @author Steve Ebersole
*
* @since 7.0
*/
@Incubating
public interface MutationSpecification<T> extends QuerySpecification<T> {
Expand All @@ -38,5 +47,6 @@ default Root<T> getMutationTarget() {
/**
* Finalize the building and create the {@linkplain SelectionQuery} instance.
*/
@Override
MutationQuery createQuery();
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
* @apiNote Query specifications only support a {@linkplain #getRoot() single root}.
*
* @author Steve Ebersole
*
* @since 7.0
*/
@Incubating
public interface QuerySpecification<T> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,40 @@
import java.util.List;

/**
* Specialization of QuerySpecification for building
* {@linkplain SelectionQuery selection queries} supporting ordering
* in addition to restrictions.
* Specialization of {@link QuerySpecification} for programmatic customization of
* {@linkplain SelectionQuery selection queries} with ordering and restriction criteria.
* <ul>
* <li>The method {@link #addRestriction(Restriction)} allows application of additional
* {@linkplain Restriction filtering} to the query results. The static factory methods
* of {@link Restriction} are used to express filtering criteria of various kinds.
* <li>Refinement or replacement of the query sorting criteria is possible via the methods
* {@link #addOrdering(Order)} and {@link #setOrdering(List)}, together with the static
* factory methods of {@link Order}.
* </ul>
* <p>
* Once all {@linkplain #addOrdering sorting} and {@linkplain #addRestriction restrictions}
* are defined, call {@linkplain #createQuery()} to obtain the executable form.
* are specified, call {@linkplain #createQuery()} to obtain an {@linkplain SelectionQuery
* executable selection query object}.
* <pre>
* session.createSelectionSpecification("from Book", Book.class)
* .addRestriction(Restriction.contains(Book_.title, "hibernate", false))
* .setOrdering(Order.desc(Book_.title))
* .createQuery() // obtain a SelectionQuery
* .setPage(Page.first(50))
* .getResultList();
* </pre>
* <p>
* A {@code SelectionSpecification} always represents a query which returns a singe root
* entity. The restriction and ordering criteria are interpreted as applying to the field
* and properties of this root entity.
*
* @param <T> The entity type returned by the query
*
* @see QueryProducer#createSelectionSpecification(String, Class)
*
* @author Steve Ebersole
*
* @since 7.0
*/
@Incubating
public interface SelectionSpecification<T> extends QuerySpecification<T> {
Expand Down Expand Up @@ -73,5 +98,6 @@ public interface SelectionSpecification<T> extends QuerySpecification<T> {
/**
* Covariant override.
*/
@Override
SelectionQuery<T> createQuery();
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
package org.hibernate.query.programmatic.internal;

import jakarta.persistence.criteria.CommonAbstractCriteria;
import jakarta.persistence.criteria.CriteriaDelete;
import jakarta.persistence.criteria.CriteriaUpdate;
import jakarta.persistence.criteria.Root;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.query.programmatic.MutationSpecification;
import org.hibernate.query.IllegalMutationQueryException;
Expand All @@ -17,8 +20,10 @@
import org.hibernate.query.sqm.internal.QuerySqmImpl;
import org.hibernate.query.sqm.internal.SqmUtil;
import org.hibernate.query.sqm.tree.SqmDeleteOrUpdateStatement;
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
import org.hibernate.query.sqm.tree.from.SqmRoot;
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;

import java.util.Locale;

Expand All @@ -40,10 +45,28 @@ public MutationSpecificationImpl(
Class<T> mutationTarget,
SharedSessionContractImplementor session) {
this.session = session;
this.sqmStatement = resolveSqmTree( hql, session );
this.sqmStatement = resolveSqmTree( hql, session.getFactory() );
this.mutationTargetRoot = resolveSqmRoot( this.sqmStatement, mutationTarget );
}

public MutationSpecificationImpl(
CriteriaUpdate<T> criteriaQuery,
SharedSessionContractImplementor session) {
this.session = session;
this.sqmStatement = (SqmUpdateStatement<T>) criteriaQuery;
this.mutationTargetRoot = resolveSqmRoot( sqmStatement,
sqmStatement.getTarget().getManagedType().getJavaType() );
}

public MutationSpecificationImpl(
CriteriaDelete<T> criteriaQuery,
SharedSessionContractImplementor session) {
this.session = session;
this.sqmStatement = (SqmDeleteStatement<T>) criteriaQuery;
this.mutationTargetRoot = resolveSqmRoot( sqmStatement,
sqmStatement.getTarget().getManagedType().getJavaType() );
}

@Override
public Root<T> getRoot() {
return mutationTargetRoot;
Expand Down Expand Up @@ -76,8 +99,8 @@ public MutationQuery createQuery() {
*/
private static <T> SqmDeleteOrUpdateStatement<T> resolveSqmTree(
String hql,
SharedSessionContractImplementor session) {
final QueryEngine queryEngine = session.getFactory().getQueryEngine();
SessionFactoryImplementor sessionFactory) {
final QueryEngine queryEngine = sessionFactory.getQueryEngine();
final HqlInterpretation<T> hqlInterpretation = queryEngine
.getInterpretationCache()
.resolveHqlInterpretation( hql, null, queryEngine.getHqlTranslator() );
Expand Down
Loading