HHH-18306 - Implicit instantiation for queries with single selection item broken
HHH-18401 - SelectionQuery needs better validation of query return type
This commit is contained in:
parent
3bf82e6d82
commit
39de0115f7
|
@ -828,12 +828,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
||||||
|
|
||||||
protected <R> HqlInterpretation<R> interpretHql(String hql, Class<R> resultType) {
|
protected <R> HqlInterpretation<R> interpretHql(String hql, Class<R> resultType) {
|
||||||
final QueryEngine queryEngine = getFactory().getQueryEngine();
|
final QueryEngine queryEngine = getFactory().getQueryEngine();
|
||||||
return queryEngine.getInterpretationCache()
|
return queryEngine.interpretHql( hql, resultType );
|
||||||
.resolveHqlInterpretation(
|
|
||||||
hql,
|
|
||||||
resultType,
|
|
||||||
queryEngine.getHqlTranslator()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void checkSelectionQuery(String hql, HqlInterpretation<?> hqlInterpretation) {
|
protected static void checkSelectionQuery(String hql, HqlInterpretation<?> hqlInterpretation) {
|
||||||
|
|
|
@ -407,17 +407,6 @@ public interface SelectionQuery<R> extends CommonQueryContract {
|
||||||
*/
|
*/
|
||||||
SelectionQuery<R> setFirstResult(int startPosition);
|
SelectionQuery<R> setFirstResult(int startPosition);
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Set the page of results to return.
|
|
||||||
// *
|
|
||||||
// * @param pageNumber the page to return, where pages are numbered from zero
|
|
||||||
// * @param pageSize the number of results per page
|
|
||||||
// *
|
|
||||||
// * @since 6.3
|
|
||||||
// */
|
|
||||||
// @Incubating
|
|
||||||
// SelectionQuery<R> setPage(int pageSize, int pageNumber);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the {@linkplain Page page} of results to return.
|
* Set the {@linkplain Page page} of results to return.
|
||||||
*
|
*
|
||||||
|
|
|
@ -19,19 +19,6 @@ import java.util.Spliterator;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import java.util.stream.StreamSupport;
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
import jakarta.persistence.CacheRetrieveMode;
|
|
||||||
import jakarta.persistence.CacheStoreMode;
|
|
||||||
import jakarta.persistence.EntityGraph;
|
|
||||||
import jakarta.persistence.FlushModeType;
|
|
||||||
import jakarta.persistence.LockModeType;
|
|
||||||
import jakarta.persistence.NoResultException;
|
|
||||||
import jakarta.persistence.Parameter;
|
|
||||||
import jakarta.persistence.TemporalType;
|
|
||||||
import jakarta.persistence.Tuple;
|
|
||||||
import jakarta.persistence.TupleElement;
|
|
||||||
import jakarta.persistence.criteria.CompoundSelection;
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
||||||
|
|
||||||
import org.hibernate.CacheMode;
|
import org.hibernate.CacheMode;
|
||||||
import org.hibernate.FlushMode;
|
import org.hibernate.FlushMode;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
@ -48,6 +35,10 @@ import org.hibernate.graph.spi.RootGraphImplementor;
|
||||||
import org.hibernate.jpa.internal.util.LockModeTypeHelper;
|
import org.hibernate.jpa.internal.util.LockModeTypeHelper;
|
||||||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.DomainType;
|
import org.hibernate.metamodel.model.domain.DomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.SimpleDomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.internal.EntitySqmPathSource;
|
||||||
import org.hibernate.query.BindableType;
|
import org.hibernate.query.BindableType;
|
||||||
import org.hibernate.query.IllegalQueryOperationException;
|
import org.hibernate.query.IllegalQueryOperationException;
|
||||||
import org.hibernate.query.QueryParameter;
|
import org.hibernate.query.QueryParameter;
|
||||||
|
@ -77,6 +68,19 @@ import org.hibernate.type.descriptor.java.JavaType;
|
||||||
import org.hibernate.type.descriptor.java.spi.PrimitiveJavaType;
|
import org.hibernate.type.descriptor.java.spi.PrimitiveJavaType;
|
||||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||||
|
|
||||||
|
import jakarta.persistence.CacheRetrieveMode;
|
||||||
|
import jakarta.persistence.CacheStoreMode;
|
||||||
|
import jakarta.persistence.EntityGraph;
|
||||||
|
import jakarta.persistence.FlushModeType;
|
||||||
|
import jakarta.persistence.LockModeType;
|
||||||
|
import jakarta.persistence.NoResultException;
|
||||||
|
import jakarta.persistence.Parameter;
|
||||||
|
import jakarta.persistence.TemporalType;
|
||||||
|
import jakarta.persistence.Tuple;
|
||||||
|
import jakarta.persistence.TupleElement;
|
||||||
|
import jakarta.persistence.criteria.CompoundSelection;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
import static java.util.Spliterators.spliteratorUnknownSize;
|
import static java.util.Spliterators.spliteratorUnknownSize;
|
||||||
import static org.hibernate.CacheMode.fromJpaModes;
|
import static org.hibernate.CacheMode.fromJpaModes;
|
||||||
import static org.hibernate.FlushMode.fromJpaFlushMode;
|
import static org.hibernate.FlushMode.fromJpaFlushMode;
|
||||||
|
@ -84,12 +88,12 @@ import static org.hibernate.cfg.AvailableSettings.JAKARTA_SHARED_CACHE_RETRIEVE_
|
||||||
import static org.hibernate.cfg.AvailableSettings.JAKARTA_SHARED_CACHE_STORE_MODE;
|
import static org.hibernate.cfg.AvailableSettings.JAKARTA_SHARED_CACHE_STORE_MODE;
|
||||||
import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_RETRIEVE_MODE;
|
import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_RETRIEVE_MODE;
|
||||||
import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_STORE_MODE;
|
import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_STORE_MODE;
|
||||||
import static org.hibernate.jpa.QueryHints.HINT_CACHEABLE;
|
import static org.hibernate.jpa.HibernateHints.HINT_CACHEABLE;
|
||||||
import static org.hibernate.jpa.QueryHints.HINT_CACHE_MODE;
|
import static org.hibernate.jpa.HibernateHints.HINT_CACHE_MODE;
|
||||||
import static org.hibernate.jpa.QueryHints.HINT_CACHE_REGION;
|
import static org.hibernate.jpa.HibernateHints.HINT_CACHE_REGION;
|
||||||
import static org.hibernate.jpa.QueryHints.HINT_FETCH_SIZE;
|
import static org.hibernate.jpa.HibernateHints.HINT_FETCH_SIZE;
|
||||||
import static org.hibernate.jpa.QueryHints.HINT_FOLLOW_ON_LOCKING;
|
import static org.hibernate.jpa.HibernateHints.HINT_FOLLOW_ON_LOCKING;
|
||||||
import static org.hibernate.jpa.QueryHints.HINT_READONLY;
|
import static org.hibernate.jpa.HibernateHints.HINT_READ_ONLY;
|
||||||
import static org.hibernate.query.sqm.internal.SqmUtil.isHqlTuple;
|
import static org.hibernate.query.sqm.internal.SqmUtil.isHqlTuple;
|
||||||
import static org.hibernate.query.sqm.internal.SqmUtil.isSelectionAssignableToResultType;
|
import static org.hibernate.query.sqm.internal.SqmUtil.isSelectionAssignableToResultType;
|
||||||
|
|
||||||
|
@ -255,7 +259,8 @@ public abstract class AbstractSelectionQuery<R>
|
||||||
protected abstract String getQueryString();
|
protected abstract String getQueryString();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used during handling of Criteria queries
|
* Used to validate that the specified query return type is valid (i.e. the user
|
||||||
|
* did not pass {@code Integer.class} when the selection is an entity)
|
||||||
*/
|
*/
|
||||||
protected void visitQueryReturnType(
|
protected void visitQueryReturnType(
|
||||||
SqmQueryPart<R> queryPart,
|
SqmQueryPart<R> queryPart,
|
||||||
|
@ -298,11 +303,13 @@ public abstract class AbstractSelectionQuery<R>
|
||||||
SqmQuerySpec<T> querySpec,
|
SqmQuerySpec<T> querySpec,
|
||||||
Class<T> expectedResultClass,
|
Class<T> expectedResultClass,
|
||||||
SessionFactoryImplementor sessionFactory) {
|
SessionFactoryImplementor sessionFactory) {
|
||||||
if ( !isResultTypeAlwaysAllowed( expectedResultClass ) ) {
|
if ( isResultTypeAlwaysAllowed( expectedResultClass ) ) {
|
||||||
|
// the result-class is always safe to use (Object, ...)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final List<SqmSelection<?>> selections = querySpec.getSelectClause().getSelections();
|
final List<SqmSelection<?>> selections = querySpec.getSelectClause().getSelections();
|
||||||
if ( selections.size() == 1 ) {
|
if ( selections.size() == 1 ) {
|
||||||
// we have one item in the select list,
|
|
||||||
// the type has to match (no instantiation)
|
|
||||||
final SqmSelection<?> sqmSelection = selections.get( 0 );
|
final SqmSelection<?> sqmSelection = selections.get( 0 );
|
||||||
final SqmSelectableNode<?> selectableNode = sqmSelection.getSelectableNode();
|
final SqmSelectableNode<?> selectableNode = sqmSelection.getSelectableNode();
|
||||||
if ( selectableNode.isCompoundSelection() ) {
|
if ( selectableNode.isCompoundSelection() ) {
|
||||||
|
@ -314,7 +321,7 @@ public abstract class AbstractSelectionQuery<R>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
verifySelectionType( expectedResultClass, sessionFactory, sqmSelection.getSelectableNode() );
|
verifySingularSelectionType( expectedResultClass, sessionFactory, sqmSelection );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( expectedResultClass.isArray() ) {
|
else if ( expectedResultClass.isArray() ) {
|
||||||
|
@ -323,28 +330,50 @@ public abstract class AbstractSelectionQuery<R>
|
||||||
verifySelectionType( componentType, sessionFactory, selection.getSelectableNode() );
|
verifySelectionType( componentType, sessionFactory, selection.getSelectableNode() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// else, let's assume we can instantiate it!
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> void verifySelectionType(
|
/**
|
||||||
|
* Special case for a single, non-compound selection-item. It is essentially
|
||||||
|
* a special case of {@linkplain #verifySelectionType} which additionally
|
||||||
|
* handles the case where the type of the selection-item can be used to
|
||||||
|
* instantiate the result-class (result-class has a matching constructor).
|
||||||
|
*
|
||||||
|
* @apiNote We don't want to hoist this into {@linkplain #verifySelectionType}
|
||||||
|
* itself because this can only happen for the root non-compound case, and we
|
||||||
|
* want to avoid the try/catch otherwise
|
||||||
|
*/
|
||||||
|
private static <T> void verifySingularSelectionType(
|
||||||
Class<T> expectedResultClass,
|
Class<T> expectedResultClass,
|
||||||
SessionFactoryImplementor sessionFactory,
|
SessionFactoryImplementor sessionFactory,
|
||||||
SqmSelection<?> sqmSelection) {
|
SqmSelection<?> sqmSelection) {
|
||||||
// special case for parameters in the select list
|
final SqmSelectableNode<?> selectableNode = sqmSelection.getSelectableNode();
|
||||||
final SqmSelectableNode<?> selection = sqmSelection.getSelectableNode();
|
try {
|
||||||
if ( selection instanceof SqmParameter ) {
|
verifySelectionType( expectedResultClass, sessionFactory, selectableNode );
|
||||||
final SqmParameter<?> sqmParameter = (SqmParameter<?>) selection;
|
}
|
||||||
final SqmExpressible<?> nodeType = sqmParameter.getNodeType();
|
catch (QueryTypeMismatchException mismatchException) {
|
||||||
// we may not yet know a selection type
|
// Check for special case of a single selection item and implicit instantiation.
|
||||||
if ( nodeType == null || nodeType.getExpressibleJavaType() == null ) {
|
// See if the selected type can be used to instantiate the expected-type
|
||||||
// we can't verify the result type up front
|
final JavaType<?> javaTypeDescriptor = selectableNode.getJavaTypeDescriptor();
|
||||||
return;
|
if ( javaTypeDescriptor != null ) {
|
||||||
|
final Class<?> selectedJavaType = javaTypeDescriptor.getJavaTypeClass();
|
||||||
|
// ignore the exception if the expected type has a constructor accepting the selected item type
|
||||||
|
if ( hasMatchingConstructor( expectedResultClass, selectedJavaType ) ) {
|
||||||
|
// ignore it
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw mismatchException;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !sessionFactory.getSessionFactoryOptions().getJpaCompliance().isJpaQueryComplianceEnabled() ) {
|
private static <T> boolean hasMatchingConstructor(Class<T> expectedResultClass, Class<?> selectedJavaType) {
|
||||||
verifyResultType( expectedResultClass, selection.getExpressible() );
|
try {
|
||||||
|
expectedResultClass.getDeclaredConstructor( selectedJavaType );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (NoSuchMethodException e) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,24 +413,58 @@ public abstract class AbstractSelectionQuery<R>
|
||||||
|| expectedResultClass == Tuple.class;
|
|| expectedResultClass == Tuple.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static <T> void verifyResultType(Class<T> resultClass, @Nullable SqmExpressible<?> sqmExpressible) {
|
protected static <T> void verifyResultType(Class<T> resultClass, @Nullable SqmExpressible<?> selectionExpressible) {
|
||||||
if ( sqmExpressible != null ) {
|
if ( selectionExpressible == null ) {
|
||||||
final JavaType<?> expressibleJavaType = sqmExpressible.getExpressibleJavaType();
|
// nothing we can validate
|
||||||
assert expressibleJavaType != null;
|
return;
|
||||||
final Class<?> javaTypeClass = expressibleJavaType.getJavaTypeClass();
|
}
|
||||||
if ( javaTypeClass != Object.class && !resultClass.isAssignableFrom( javaTypeClass ) ) {
|
|
||||||
if ( expressibleJavaType instanceof PrimitiveJavaType ) {
|
final JavaType<?> selectionExpressibleJavaType = selectionExpressible.getExpressibleJavaType();
|
||||||
final PrimitiveJavaType<?> javaType = (PrimitiveJavaType<?>) expressibleJavaType;
|
assert selectionExpressibleJavaType != null;
|
||||||
if ( javaType.getPrimitiveClass() != resultClass ) {
|
|
||||||
throwQueryTypeMismatchException( resultClass, sqmExpressible );
|
final Class<?> selectionExpressibleJavaTypeClass = selectionExpressibleJavaType.getJavaTypeClass();
|
||||||
|
if ( selectionExpressibleJavaTypeClass == Object.class ) {
|
||||||
|
|
||||||
|
}
|
||||||
|
if ( selectionExpressibleJavaTypeClass != Object.class ) {
|
||||||
|
// performs a series of opt-out checks for validity... each if branch and return indicates a valid case
|
||||||
|
if ( resultClass.isAssignableFrom( selectionExpressibleJavaTypeClass ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( selectionExpressibleJavaType instanceof PrimitiveJavaType ) {
|
||||||
|
final PrimitiveJavaType<?> primitiveJavaType = (PrimitiveJavaType<?>) selectionExpressibleJavaType;
|
||||||
|
if ( primitiveJavaType.getPrimitiveClass() == resultClass ) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( !isMatchingDateType( javaTypeClass, resultClass, sqmExpressible ) ) {
|
|
||||||
throwQueryTypeMismatchException( resultClass, sqmExpressible );
|
if ( isMatchingDateType( selectionExpressibleJavaTypeClass, resultClass, selectionExpressible ) ) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// else special case, we are good
|
|
||||||
|
if ( isEntityIdType( selectionExpressible, resultClass ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throwQueryTypeMismatchException( resultClass, selectionExpressible );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static <T> boolean isEntityIdType(SqmExpressible<?> selectionExpressible, Class<T> resultClass) {
|
||||||
|
if ( selectionExpressible instanceof IdentifiableDomainType ) {
|
||||||
|
final IdentifiableDomainType<?> identifiableDomainType = (IdentifiableDomainType<?>) selectionExpressible;
|
||||||
|
final SimpleDomainType<?> idType = identifiableDomainType.getIdType();
|
||||||
|
return resultClass.isAssignableFrom( idType.getBindableJavaType() );
|
||||||
|
}
|
||||||
|
else if ( selectionExpressible instanceof EntitySqmPathSource ) {
|
||||||
|
final EntitySqmPathSource<?> entityPath = (EntitySqmPathSource<?>) selectionExpressible;
|
||||||
|
final EntityDomainType<?> entityType = entityPath.getSqmPathType();
|
||||||
|
final SimpleDomainType<?> idType = entityType.getIdType();
|
||||||
|
return resultClass.isAssignableFrom( idType.getBindableJavaType() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case for date because we always report java.util.Date as expression type
|
// Special case for date because we always report java.util.Date as expression type
|
||||||
|
@ -785,7 +848,7 @@ public abstract class AbstractSelectionQuery<R>
|
||||||
super.collectHints( hints );
|
super.collectHints( hints );
|
||||||
|
|
||||||
if ( isReadOnly() ) {
|
if ( isReadOnly() ) {
|
||||||
hints.put( HINT_READONLY, true );
|
hints.put( HINT_READ_ONLY, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
putIfNotNull( hints, HINT_FETCH_SIZE, getFetchSize() );
|
putIfNotNull( hints, HINT_FETCH_SIZE, getFetchSize() );
|
||||||
|
|
|
@ -49,5 +49,9 @@ public interface QueryEngine {
|
||||||
HqlTranslator getHqlTranslator();
|
HqlTranslator getHqlTranslator();
|
||||||
|
|
||||||
SqmTranslatorFactory getSqmTranslatorFactory();
|
SqmTranslatorFactory getSqmTranslatorFactory();
|
||||||
|
|
||||||
|
default <R> HqlInterpretation<R> interpretHql(String hql, Class<R> resultType) {
|
||||||
|
return getInterpretationCache().resolveHqlInterpretation( hql, resultType, getHqlTranslator() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,11 +107,11 @@ public class SqmSelectionQueryImpl<R> extends AbstractSqmSelectionQuery<R>
|
||||||
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
|
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
|
||||||
|
|
||||||
this.expectedResultType = expectedResultType;
|
this.expectedResultType = expectedResultType;
|
||||||
// visitQueryReturnType( sqm.getQueryPart(), expectedResultType, getSessionFactory() );
|
visitQueryReturnType( sqm.getQueryPart(), expectedResultType, getSessionFactory() );
|
||||||
this.resultType = determineResultType( sqm );
|
this.resultType = determineResultType( sqm );
|
||||||
|
this.tupleMetadata = buildTupleMetadata( sqm, expectedResultType );
|
||||||
|
|
||||||
setComment( hql );
|
setComment( hql );
|
||||||
this.tupleMetadata = buildTupleMetadata( sqm, expectedResultType );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Class<?> determineResultType(SqmSelectStatement<?> sqm) {
|
private Class<?> determineResultType(SqmSelectStatement<?> sqm) {
|
||||||
|
|
|
@ -30,7 +30,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
@DomainModel( annotatedClasses = SimpleEntity.class )
|
@DomainModel( annotatedClasses = {SimpleEntity.class, Dto.class, Dto2.class } )
|
||||||
@SessionFactory
|
@SessionFactory
|
||||||
public class BasicCriteriaResultTests {
|
public class BasicCriteriaResultTests {
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
|
|
|
@ -21,7 +21,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
@DomainModel( annotatedClasses = SimpleEntity.class )
|
@DomainModel( annotatedClasses = {SimpleEntity.class, Dto.class, Dto2.class } )
|
||||||
@SessionFactory
|
@SessionFactory
|
||||||
public class BasicHqlResultTests {
|
public class BasicHqlResultTests {
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* 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.results;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.Imported;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@Imported
|
||||||
|
public class Dto {
|
||||||
|
private final Integer key;
|
||||||
|
private final String text;
|
||||||
|
|
||||||
|
public Dto(Integer key, String text) {
|
||||||
|
this.key = key;
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.orm.test.query.results;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.Imported;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@Imported
|
||||||
|
public class Dto2 {
|
||||||
|
private final String text;
|
||||||
|
|
||||||
|
public Dto2(String text) {
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* 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.results;
|
||||||
|
|
||||||
|
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
|
||||||
|
import org.hibernate.query.criteria.JpaCriteriaQuery;
|
||||||
|
import org.hibernate.query.criteria.JpaRoot;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.FailureExpected;
|
||||||
|
import org.hibernate.testing.orm.junit.Jira;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@DomainModel(annotatedClasses = {SimpleEntity.class, SimpleComposite.class, Dto.class, Dto2.class})
|
||||||
|
@SessionFactory
|
||||||
|
@SuppressWarnings("JUnitMalformedDeclaration")
|
||||||
|
public class ImplicitInstantiationTests {
|
||||||
|
@BeforeEach
|
||||||
|
void prepareTestData(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
session.persist( new SimpleEntity( 1, "first", new SimpleComposite( "value1", "value2" ) ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void dropTestData(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
session.createMutationQuery( "delete SimpleEntity" ).executeUpdate();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCreateQuery(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final Dto rtn = session.createQuery( Queries.ID_NAME, Dto.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.getKey() ).isEqualTo( 1 );
|
||||||
|
assertThat( rtn.getText() ).isEqualTo( "first" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final Dto rtn = session.createQuery( Queries.ID_COMP_VAL, Dto.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.getKey() ).isEqualTo( 1 );
|
||||||
|
assertThat( rtn.getText() ).isEqualTo( "value1" );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCreateSelectionQuery(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final Dto rtn = session.createSelectionQuery( Queries.ID_NAME, Dto.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.getKey() ).isEqualTo( 1 );
|
||||||
|
assertThat( rtn.getText() ).isEqualTo( "first" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final Dto rtn = session.createSelectionQuery( Queries.ID_COMP_VAL, Dto.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.getKey() ).isEqualTo( 1 );
|
||||||
|
assertThat( rtn.getText() ).isEqualTo( "value1" );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCriteria(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final HibernateCriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
|
||||||
|
|
||||||
|
final JpaCriteriaQuery<Dto> criteria = criteriaBuilder.createQuery( Dto.class );
|
||||||
|
final JpaRoot<SimpleEntity> root = criteria.from( SimpleEntity.class );
|
||||||
|
criteria.multiselect( root.get( "id" ), root.get( "name" ) );
|
||||||
|
final Dto rtn = session.createQuery( criteria ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.getKey() ).isEqualTo( 1 );
|
||||||
|
assertThat( rtn.getText() ).isEqualTo( "first" );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Jira( "https://hibernate.atlassian.net/browse/HHH-18306" )
|
||||||
|
void testCreateQuerySingleSelectItem(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final Dto2 rtn = session.createQuery( Queries.NAME, Dto2.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.getText() ).isEqualTo( "first" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final Dto2 rtn = session.createQuery( Queries.COMP_VAL, Dto2.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.getText() ).isEqualTo( "value1" );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Jira( "https://hibernate.atlassian.net/browse/HHH-18306" )
|
||||||
|
void testCreateSelectionQuerySingleSelectItem(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final Dto2 rtn = session.createSelectionQuery( Queries.NAME, Dto2.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.getText() ).isEqualTo( "first" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final Dto2 rtn = session.createSelectionQuery( Queries.COMP_VAL, Dto2.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.getText() ).isEqualTo( "value1" );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Jira( "https://hibernate.atlassian.net/browse/HHH-18306" )
|
||||||
|
void testCriteriaSingleSelectItem(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final HibernateCriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
|
||||||
|
|
||||||
|
final JpaCriteriaQuery<Dto2> criteria = criteriaBuilder.createQuery( Dto2.class );
|
||||||
|
final JpaRoot<SimpleEntity> root = criteria.from( SimpleEntity.class );
|
||||||
|
criteria.multiselect( root.get( "name" ) );
|
||||||
|
final Dto2 rtn = session.createQuery( criteria ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.getText() ).isEqualTo( "first" );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,147 @@
|
||||||
|
/*
|
||||||
|
* 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.results;
|
||||||
|
|
||||||
|
import org.hibernate.query.QueryTypeMismatchException;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.Jira;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@Jira( "https://hibernate.atlassian.net/browse/HHH-18401" )
|
||||||
|
@DomainModel(annotatedClasses = {SimpleEntity.class, SimpleComposite.class, Dto.class, Dto2.class})
|
||||||
|
@SessionFactory
|
||||||
|
@SuppressWarnings("JUnitMalformedDeclaration")
|
||||||
|
public class InvalidReturnTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCreateQuery(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
try {
|
||||||
|
session.createQuery( Queries.ENTITY, SimpleComposite.class );
|
||||||
|
fail( "Expecting a QueryTypeMismatchException" );
|
||||||
|
}
|
||||||
|
catch (QueryTypeMismatchException expected) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
session.createQuery( Queries.ENTITY, Dto.class );
|
||||||
|
fail( "Expecting a QueryTypeMismatchException" );
|
||||||
|
}
|
||||||
|
catch (QueryTypeMismatchException expected) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
session.createQuery( Queries.ENTITY_NO_SELECT, SimpleComposite.class );
|
||||||
|
fail( "Expecting a QueryTypeMismatchException" );
|
||||||
|
}
|
||||||
|
catch (QueryTypeMismatchException expected) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
session.createQuery( Queries.COMPOSITE, SimpleEntity.class );
|
||||||
|
fail( "Expecting a QueryTypeMismatchException" );
|
||||||
|
}
|
||||||
|
catch (QueryTypeMismatchException expected) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
session.createQuery( Queries.ID_NAME_DTO, SimpleEntity.class );
|
||||||
|
fail( "Expecting a QueryTypeMismatchException" );
|
||||||
|
}
|
||||||
|
catch (QueryTypeMismatchException expected) {
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCreateSelectionQuery(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
try {
|
||||||
|
session.createSelectionQuery( Queries.ENTITY, SimpleComposite.class );
|
||||||
|
fail( "Expecting a QueryTypeMismatchException" );
|
||||||
|
}
|
||||||
|
catch (QueryTypeMismatchException expected) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
session.createSelectionQuery( Queries.ENTITY_NO_SELECT, Dto.class );
|
||||||
|
fail( "Expecting a QueryTypeMismatchException" );
|
||||||
|
}
|
||||||
|
catch (QueryTypeMismatchException expected) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
session.createSelectionQuery( Queries.ENTITY_NO_SELECT, SimpleComposite.class );
|
||||||
|
fail( "Expecting a QueryTypeMismatchException" );
|
||||||
|
}
|
||||||
|
catch (QueryTypeMismatchException expected) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
session.createSelectionQuery( Queries.COMPOSITE, SimpleEntity.class );
|
||||||
|
fail( "Expecting a QueryTypeMismatchException" );
|
||||||
|
}
|
||||||
|
catch (QueryTypeMismatchException expected) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
session.createSelectionQuery( Queries.ID_NAME_DTO, SimpleEntity.class );
|
||||||
|
fail( "Expecting a QueryTypeMismatchException" );
|
||||||
|
}
|
||||||
|
catch (QueryTypeMismatchException expected) {
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testNamedQuery(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
try {
|
||||||
|
session.createNamedQuery( Queries.NAMED_ENTITY, SimpleComposite.class );
|
||||||
|
fail( "Expecting a QueryTypeMismatchException" );
|
||||||
|
}
|
||||||
|
catch (QueryTypeMismatchException expected) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
session.createNamedQuery( Queries.NAMED_ENTITY_NO_SELECT, Dto.class );
|
||||||
|
fail( "Expecting a QueryTypeMismatchException" );
|
||||||
|
}
|
||||||
|
catch (QueryTypeMismatchException expected) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
session.createNamedQuery( Queries.NAMED_ENTITY_NO_SELECT, SimpleComposite.class );
|
||||||
|
fail( "Expecting a QueryTypeMismatchException" );
|
||||||
|
}
|
||||||
|
catch (QueryTypeMismatchException expected) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
session.createNamedQuery( Queries.NAMED_COMPOSITE, SimpleEntity.class );
|
||||||
|
fail( "Expecting a QueryTypeMismatchException" );
|
||||||
|
}
|
||||||
|
catch (QueryTypeMismatchException expected) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
session.createNamedQuery( Queries.NAMED_ID_NAME_DTO, SimpleEntity.class );
|
||||||
|
fail( "Expecting a QueryTypeMismatchException" );
|
||||||
|
}
|
||||||
|
catch (QueryTypeMismatchException expected) {
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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.results;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class Queries {
|
||||||
|
public static final String ENTITY = "select e from SimpleEntity e";
|
||||||
|
public static final String ENTITY_NO_SELECT = "from SimpleEntity e";
|
||||||
|
|
||||||
|
public static final String COMPOSITE = "select e.composite from SimpleEntity e";
|
||||||
|
public static final String NAME = "select e.name from SimpleEntity e";
|
||||||
|
public static final String COMP_VAL = "select e.composite.value1 from SimpleEntity e";
|
||||||
|
|
||||||
|
public static final String ID_NAME = "select e.id, e.name from SimpleEntity e";
|
||||||
|
public static final String ID_COMP_VAL = "select e.id, e.composite.value1 from SimpleEntity e";
|
||||||
|
|
||||||
|
public static final String ID_NAME_DTO = "select new Dto(e.id, e.name) from SimpleEntity e";
|
||||||
|
public static final String ID_COMP_VAL_DTO = "select new Dto(e.id, e.composite.value1) from SimpleEntity e";
|
||||||
|
|
||||||
|
public static final String NAME_DTO = "select new Dto2(e.name) from SimpleEntity e";
|
||||||
|
public static final String COMP_VAL_DTO = "select new Dto2(e.composite.value1) from SimpleEntity e";
|
||||||
|
|
||||||
|
public static final String NAMED_ENTITY = "entity";
|
||||||
|
public static final String NAMED_ENTITY_NO_SELECT = "entity-no-select";
|
||||||
|
public static final String NAMED_COMPOSITE = "composite";
|
||||||
|
public static final String NAMED_NAME = "name";
|
||||||
|
public static final String NAMED_COMP_VAL = "comp-val";
|
||||||
|
public static final String NAMED_ID_NAME = "id-name";
|
||||||
|
public static final String NAMED_ID_COMP_VAL = "id-comp-val";
|
||||||
|
public static final String NAMED_ID_NAME_DTO = "id-name-dto";
|
||||||
|
public static final String NAMED_ID_COMP_VAL_DTO = "id-comp-val-dto";
|
||||||
|
public static final String NAMED_NAME_DTO = "name-dto";
|
||||||
|
public static final String NAMED_COMP_VAL_DTO = "comp-val-dto";
|
||||||
|
}
|
|
@ -7,8 +7,8 @@
|
||||||
package org.hibernate.orm.test.query.results;
|
package org.hibernate.orm.test.query.results;
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.NamedQuery;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,6 +16,17 @@ import jakarta.persistence.Table;
|
||||||
*/
|
*/
|
||||||
@Entity(name = "SimpleEntity")
|
@Entity(name = "SimpleEntity")
|
||||||
@Table(name = "simple_entity")
|
@Table(name = "simple_entity")
|
||||||
|
@NamedQuery(name= Queries.NAMED_ENTITY, query = Queries.ENTITY)
|
||||||
|
@NamedQuery(name= Queries.NAMED_ENTITY_NO_SELECT, query = Queries.ENTITY_NO_SELECT)
|
||||||
|
@NamedQuery(name= Queries.NAMED_COMPOSITE, query = Queries.COMPOSITE)
|
||||||
|
@NamedQuery(name= Queries.NAMED_NAME, query = Queries.NAME)
|
||||||
|
@NamedQuery(name= Queries.NAMED_COMP_VAL, query = Queries.COMP_VAL)
|
||||||
|
@NamedQuery(name= Queries.NAMED_ID_NAME, query = Queries.ID_NAME)
|
||||||
|
@NamedQuery(name= Queries.NAMED_ID_COMP_VAL, query = Queries.ID_COMP_VAL)
|
||||||
|
@NamedQuery(name= Queries.NAMED_ID_NAME_DTO, query = Queries.ID_NAME_DTO)
|
||||||
|
@NamedQuery(name= Queries.NAMED_ID_COMP_VAL_DTO, query = Queries.ID_COMP_VAL_DTO)
|
||||||
|
@NamedQuery(name= Queries.NAMED_NAME_DTO, query = Queries.NAME_DTO)
|
||||||
|
@NamedQuery(name= Queries.NAMED_COMP_VAL_DTO, query = Queries.COMP_VAL_DTO)
|
||||||
public class SimpleEntity {
|
public class SimpleEntity {
|
||||||
@Id
|
@Id
|
||||||
public Integer id;
|
public Integer id;
|
||||||
|
|
|
@ -0,0 +1,202 @@
|
||||||
|
/*
|
||||||
|
* 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.results;
|
||||||
|
|
||||||
|
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
|
||||||
|
import org.hibernate.query.criteria.JpaCriteriaQuery;
|
||||||
|
import org.hibernate.query.criteria.JpaRoot;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.Jira;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@Jira( "https://hibernate.atlassian.net/browse/HHH-18401" )
|
||||||
|
@DomainModel(annotatedClasses = {SimpleEntity.class, SimpleComposite.class, Dto.class, Dto2.class})
|
||||||
|
@SessionFactory
|
||||||
|
@SuppressWarnings("JUnitMalformedDeclaration")
|
||||||
|
public class TypedQueryCreationTests {
|
||||||
|
@BeforeEach
|
||||||
|
void prepareTestData(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
session.persist( new SimpleEntity( 1, "first", new SimpleComposite( "value1", "value2" ) ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void dropTestData(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
session.createMutationQuery( "delete SimpleEntity" ).executeUpdate();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCreateQuery(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final SimpleEntity rtn = session.createQuery( Queries.ENTITY, SimpleEntity.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.id ).isEqualTo( 1 );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final SimpleEntity rtn = session.createQuery( Queries.ENTITY_NO_SELECT, SimpleEntity.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.id ).isEqualTo( 1 );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final SimpleComposite rtn = session.createQuery( Queries.COMPOSITE, SimpleComposite.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.value1 ).isEqualTo( "value1" );
|
||||||
|
assertThat( rtn.value2 ).isEqualTo( "value2" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final Dto rtn = session.createQuery( Queries.ID_NAME_DTO, Dto.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.getKey() ).isEqualTo( 1 );
|
||||||
|
assertThat( rtn.getText() ).isEqualTo( "first" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final Dto rtn = session.createQuery( Queries.ID_COMP_VAL_DTO, Dto.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.getKey() ).isEqualTo( 1 );
|
||||||
|
assertThat( rtn.getText() ).isEqualTo( "value1" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final String rtn = session.createQuery( Queries.NAME, String.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn ).isEqualTo( "first" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final String rtn = session.createQuery( Queries.COMP_VAL, String.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn ).isEqualTo( "value1" );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCreateSelectionQuery(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final SimpleEntity rtn = session.createSelectionQuery( Queries.ENTITY, SimpleEntity.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.id ).isEqualTo( 1 );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final SimpleEntity rtn = session.createSelectionQuery( Queries.ENTITY_NO_SELECT, SimpleEntity.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.id ).isEqualTo( 1 );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final SimpleComposite rtn = session.createSelectionQuery( Queries.COMPOSITE, SimpleComposite.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.value1 ).isEqualTo( "value1" );
|
||||||
|
assertThat( rtn.value2 ).isEqualTo( "value2" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final Dto rtn = session.createSelectionQuery( Queries.ID_NAME_DTO, Dto.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.getKey() ).isEqualTo( 1 );
|
||||||
|
assertThat( rtn.getText() ).isEqualTo( "first" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final Dto rtn = session.createSelectionQuery( Queries.ID_COMP_VAL_DTO, Dto.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.getKey() ).isEqualTo( 1 );
|
||||||
|
assertThat( rtn.getText() ).isEqualTo( "value1" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final String rtn = session.createSelectionQuery( Queries.NAME, String.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn ).isEqualTo( "first" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final String rtn = session.createSelectionQuery( Queries.COMP_VAL, String.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn ).isEqualTo( "value1" );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCreateNamedQuery(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final SimpleEntity rtn = session.createNamedQuery( Queries.NAMED_ENTITY, SimpleEntity.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.id ).isEqualTo( 1 );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final SimpleEntity rtn = session.createNamedQuery( Queries.NAMED_ENTITY_NO_SELECT, SimpleEntity.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.id ).isEqualTo( 1 );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final SimpleComposite rtn = session.createNamedQuery( Queries.NAMED_COMPOSITE, SimpleComposite.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.value1 ).isEqualTo( "value1" );
|
||||||
|
assertThat( rtn.value2 ).isEqualTo( "value2" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final Dto rtn = session.createNamedQuery( Queries.NAMED_ID_NAME_DTO, Dto.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.getKey() ).isEqualTo( 1 );
|
||||||
|
assertThat( rtn.getText() ).isEqualTo( "first" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final Dto rtn = session.createNamedQuery( Queries.NAMED_ID_COMP_VAL_DTO, Dto.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.getKey() ).isEqualTo( 1 );
|
||||||
|
assertThat( rtn.getText() ).isEqualTo( "value1" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final String rtn = session.createNamedQuery( Queries.NAMED_NAME, String.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn ).isEqualTo( "first" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final String rtn = session.createNamedQuery( Queries.NAMED_COMP_VAL, String.class ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn ).isEqualTo( "value1" );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCriteria(SessionFactoryScope sessions) {
|
||||||
|
sessions.inTransaction( (session) -> {
|
||||||
|
final HibernateCriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
|
||||||
|
|
||||||
|
final JpaCriteriaQuery<SimpleEntity> criteria = criteriaBuilder.createQuery( SimpleEntity.class );
|
||||||
|
final JpaRoot<SimpleEntity> root = criteria.from( SimpleEntity.class );
|
||||||
|
criteria.select( root );
|
||||||
|
final SimpleEntity rtn = session.createQuery( criteria ).getSingleResultOrNull();
|
||||||
|
assertThat( rtn ).isNotNull();
|
||||||
|
assertThat( rtn.id ).isEqualTo( 1 );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue