HHH-15316 - Session.createQuery() doesn't accept JpaCriteriaInsertSelect

This commit is contained in:
Steve Ebersole 2022-06-06 14:39:22 -05:00
parent 341267b133
commit 0adbf40c49
7 changed files with 150 additions and 10 deletions

View File

@ -49,6 +49,7 @@ import org.hibernate.procedure.ProcedureCall;
import org.hibernate.query.MutationQuery;
import org.hibernate.query.SelectionQuery;
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
import org.hibernate.query.criteria.JpaCriteriaInsertSelect;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.spi.QueryProducerImplementor;
import org.hibernate.query.sql.spi.NativeQueryImplementor;
@ -450,14 +451,22 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
@Override
public MutationQuery createMutationQuery(@SuppressWarnings("rawtypes") CriteriaUpdate updateQuery) {
//noinspection resource
return delegate().createMutationQuery( updateQuery );
}
@Override
public MutationQuery createMutationQuery(@SuppressWarnings("rawtypes") CriteriaDelete deleteQuery) {
//noinspection resource
return delegate().createMutationQuery( deleteQuery );
}
@Override
public MutationQuery createMutationQuery(@SuppressWarnings("rawtypes") JpaCriteriaInsertSelect insertSelect) {
//noinspection resource
return delegate().createMutationQuery( insertSelect );
}
@Override
public <T> QueryImplementor<T> createQuery(CriteriaQuery<T> criteriaQuery) {
return queryDelegate().createQuery( criteriaQuery );
@ -525,11 +534,13 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
@Override
public SelectionQuery<?> createNamedSelectionQuery(String name) {
//noinspection resource
return delegate().createNamedSelectionQuery( name );
}
@Override
public <R> SelectionQuery<R> createNamedSelectionQuery(String name, Class<R> resultType) {
//noinspection resource
return delegate().createNamedSelectionQuery( name, resultType );
}
@ -649,6 +660,7 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
return delegate.createStoredProcedureCall( procedureName, resultSetMappings );
}
@SuppressWarnings("rawtypes")
@Override
public SharedSessionBuilder sessionWithOptions() {
return delegate.sessionWithOptions();

View File

@ -38,6 +38,7 @@ import org.hibernate.query.NativeQuery;
import org.hibernate.query.Query;
import org.hibernate.query.SelectionQuery;
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
import org.hibernate.query.criteria.JpaCriteriaInsertSelect;
import org.hibernate.stat.SessionStatistics;
import jakarta.persistence.EntityGraph;
@ -476,6 +477,7 @@ public class SessionLazyDelegator implements Session {
return this.lazySession.get().getLobHelper();
}
@SuppressWarnings("rawtypes")
@Override
public SharedSessionBuilder sessionWithOptions() {
return this.lazySession.get().sessionWithOptions();
@ -511,6 +513,7 @@ public class SessionLazyDelegator implements Session {
return this.lazySession.get().createQuery( queryString, resultClass );
}
@SuppressWarnings("rawtypes")
@Override
@Deprecated
public Query createQuery(String queryString) {
@ -522,6 +525,7 @@ public class SessionLazyDelegator implements Session {
return this.lazySession.get().createNamedQuery( name, resultClass );
}
@SuppressWarnings("rawtypes")
@Override
@Deprecated
public Query createNamedQuery(String name) {
@ -533,12 +537,14 @@ public class SessionLazyDelegator implements Session {
return this.lazySession.get().createQuery( criteriaQuery );
}
@SuppressWarnings("rawtypes")
@Override
@Deprecated
public Query createQuery(CriteriaDelete deleteQuery) {
return this.lazySession.get().createQuery( deleteQuery );
}
@SuppressWarnings("rawtypes")
@Override
@Deprecated
public Query createQuery(CriteriaUpdate updateQuery) {
@ -605,7 +611,7 @@ public class SessionLazyDelegator implements Session {
return this.lazySession.get().createStoredProcedureQuery( procedureName );
}
@Override @SuppressWarnings({"rawtypes", "unchecked"})
@Override
public ProcedureCall createStoredProcedureQuery(String procedureName, Class... resultClasses) {
return this.lazySession.get().createStoredProcedureQuery( procedureName, resultClasses );
}
@ -640,6 +646,7 @@ public class SessionLazyDelegator implements Session {
return this.lazySession.get().doReturningWork( work );
}
@SuppressWarnings("rawtypes")
@Override
@Deprecated
public NativeQuery createNativeQuery(String sqlString) {
@ -656,6 +663,7 @@ public class SessionLazyDelegator implements Session {
return this.lazySession.get().createNativeQuery( sqlString, resultClass, tableAlias );
}
@SuppressWarnings("rawtypes")
@Override
@Deprecated
public NativeQuery createNativeQuery(String sqlString, String resultSetMappingName) {
@ -688,15 +696,20 @@ public class SessionLazyDelegator implements Session {
}
@Override
public MutationQuery createMutationQuery(CriteriaUpdate updateQuery) {
public MutationQuery createMutationQuery(@SuppressWarnings("rawtypes") CriteriaUpdate updateQuery) {
return this.lazySession.get().createMutationQuery( updateQuery );
}
@Override
public MutationQuery createMutationQuery(CriteriaDelete deleteQuery) {
public MutationQuery createMutationQuery(@SuppressWarnings("rawtypes") CriteriaDelete deleteQuery) {
return this.lazySession.get().createMutationQuery( deleteQuery );
}
@Override
public MutationQuery createMutationQuery(@SuppressWarnings("rawtypes") JpaCriteriaInsertSelect insertSelect) {
return this.lazySession.get().createMutationQuery( insertSelect );
}
@Override
public MutationQuery createNativeMutationQuery(String sqlString) {
return this.lazySession.get().createNativeMutationQuery( sqlString );
@ -717,18 +730,21 @@ public class SessionLazyDelegator implements Session {
return this.lazySession.get().createNamedMutationQuery( name );
}
@SuppressWarnings("rawtypes")
@Override
@Deprecated
public Query getNamedQuery(String queryName) {
return this.lazySession.get().getNamedQuery( queryName );
}
@SuppressWarnings("rawtypes")
@Override
@Deprecated
public NativeQuery getNamedNativeQuery(String name) {
return this.lazySession.get().getNamedNativeQuery( name );
}
@SuppressWarnings("rawtypes")
@Override
@Deprecated
public NativeQuery getNamedNativeQuery(String name, String resultSetMapping) {
@ -813,6 +829,7 @@ public class SessionLazyDelegator implements Session {
@Override
public <T> T unwrap(Class<T> cls) {
if ( cls.isAssignableFrom( Session.class ) ) {
//noinspection unchecked
return (T) this;
}
return this.lazySession.get().unwrap( cls );

View File

@ -15,13 +15,6 @@ import java.util.Locale;
import java.util.TimeZone;
import java.util.UUID;
import java.util.function.Function;
import jakarta.persistence.FlushModeType;
import jakarta.persistence.NamedNativeQuery;
import jakarta.persistence.TransactionRequiredException;
import jakarta.persistence.Tuple;
import jakarta.persistence.criteria.CriteriaDelete;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.CriteriaUpdate;
import org.hibernate.CacheMode;
import org.hibernate.EmptyInterceptor;
@ -68,6 +61,7 @@ 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.criteria.JpaCriteriaInsertSelect;
import org.hibernate.query.hql.spi.SqmQueryImplementor;
import org.hibernate.query.named.NamedObjectRepository;
import org.hibernate.query.named.NamedResultSetMappingMemento;
@ -86,6 +80,7 @@ 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;
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
import org.hibernate.query.sqm.tree.select.SqmQueryGroup;
import org.hibernate.query.sqm.tree.select.SqmQuerySpec;
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
@ -98,6 +93,14 @@ import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoo
import org.hibernate.resource.transaction.spi.TransactionCoordinator;
import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder;
import jakarta.persistence.FlushModeType;
import jakarta.persistence.NamedNativeQuery;
import jakarta.persistence.TransactionRequiredException;
import jakarta.persistence.Tuple;
import jakarta.persistence.criteria.CriteriaDelete;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.CriteriaUpdate;
import static java.lang.Boolean.TRUE;
/**
@ -1163,6 +1166,17 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
}
}
@Override
public MutationQuery createMutationQuery(@SuppressWarnings("rawtypes") JpaCriteriaInsertSelect insertSelect) {
checkOpen();
try {
return new QuerySqmImpl<>( (SqmInsertSelectStatement<?>) insertSelect, null, this );
}
catch ( RuntimeException e ) {
throw getExceptionConverter().convert( e );
}
}
@Override
@SuppressWarnings("UnnecessaryLocalVariable")
public ProcedureCall getNamedProcedureCall(String name) {

View File

@ -6,6 +6,8 @@
*/
package org.hibernate.query;
import org.hibernate.query.criteria.JpaCriteriaInsertSelect;
import jakarta.persistence.criteria.CriteriaDelete;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.CriteriaUpdate;
@ -208,6 +210,11 @@ public interface QueryProducer {
*/
MutationQuery createMutationQuery(@SuppressWarnings("rawtypes") CriteriaDelete deleteQuery);
/**
* Create a {@link MutationQuery} from the given insert-select criteria tree
*/
MutationQuery createMutationQuery(@SuppressWarnings("rawtypes") JpaCriteriaInsertSelect insertSelect);
/**
* Create a {@link NativeQuery} instance for the given native (SQL) statement
*

View File

@ -6,6 +6,8 @@
*/
package org.hibernate.query.criteria;
import org.hibernate.Incubating;
/**
* A representation of SqmInsertSelectStatement at the
* {@link org.hibernate.query.criteria} level, even though JPA does
@ -13,7 +15,20 @@ package org.hibernate.query.criteria;
*
* @see org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement
*
* @apiNote Incubating mainly for 2 purposes:<ul>
* <li>
* to decide how to handle the typing for the "selection part". Should it
* be {@code <T>} or {@code <X>}. For the time being we expose it as
* {@code <T>} because that is what was done (without intention) originally,
* and it is the easiest form to validate
* </li>
* <li>
* Would be better to expose non-SQM contracts here
* </li>
* </ul>
*
* @author Steve Ebersole
*/
@Incubating
public interface JpaCriteriaInsertSelect<T> extends JpaManipulationCriteria<T> {
}

View File

@ -10,6 +10,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.Incubating;
import org.hibernate.query.criteria.JpaCriteriaInsertSelect;
import org.hibernate.query.criteria.JpaPredicate;
import org.hibernate.query.sqm.NodeBuilder;
@ -26,6 +27,7 @@ import org.hibernate.query.sqm.tree.select.SqmQuerySpec;
/**
* @author Steve Ebersole
*/
@Incubating
public class SqmInsertSelectStatement<T> extends AbstractSqmInsertStatement<T> implements JpaCriteriaInsertSelect<T> {
private SqmQueryPart<T> selectQueryPart;

View File

@ -0,0 +1,73 @@
/*
* 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.query.criteria;
import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder;
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
/**
* @author Steve Ebersole
*/
@DomainModel(annotatedClasses = InsertSelectTests.AnEntity.class)
@SessionFactory
public class InsertSelectTests {
@Test
public void simpleTest(SessionFactoryScope scope) {
scope.inTransaction( (session) -> {
final SqmCriteriaNodeBuilder criteriaBuilder = (SqmCriteriaNodeBuilder) session.getCriteriaBuilder();
final SqmInsertSelectStatement<AnEntity> insertSelect = criteriaBuilder.createCriteriaInsertSelect( AnEntity.class );
final SqmSelectStatement<AnEntity> select = criteriaBuilder.createQuery( AnEntity.class );
insertSelect.setSelectQueryPart( select.getQuerySpec() );
select.from( AnEntity.class );
session.createMutationQuery( insertSelect ).executeUpdate();
} );
}
@SuppressWarnings("unused")
@Entity( name = "AnEntity" )
@Table( name = "AnEntity" )
public static class AnEntity {
@Id
@GeneratedValue
private Integer id;
@Basic
private String name;
private AnEntity() {
// for use by Hibernate
}
public AnEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}