diff --git a/gradle/libraries.gradle b/gradle/libraries.gradle index 0d1839fb8a..522a25c9b9 100644 --- a/gradle/libraries.gradle +++ b/gradle/libraries.gradle @@ -191,6 +191,7 @@ ext { jakarta_weld: "org.jboss.weld.se:weld-se-shaded:${jakartaWeldVersion}", assertj: "org.assertj:assertj-core:${assertjVersion}", + assertj_api: "org.assertj:assertj-core-api:${assertjVersion}", // Shrinkwrap shrinkwrap_api: "org.jboss.shrinkwrap:shrinkwrap-api:${shrinkwrapVersion}", diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/RowSelection.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/RowSelection.java index 0bbb3980ba..edf71d64a5 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/RowSelection.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/RowSelection.java @@ -6,9 +6,18 @@ */ package org.hibernate.engine.spi; +import org.hibernate.query.spi.QueryOptions; + /** + * Encapsulates details related to the creation and execution of + * a JDBC statement + * + * Differs from {@link QueryOptions} in that this contract describes options + * * Represents a selection criteria for rows in a JDBC {@link java.sql.ResultSet} * + * + * * @author Gavin King * @deprecated todo (6.0): remove in favor of Limit within QueryOptions? */ diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java b/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java index 1e5370fd6b..05c9852ac4 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java @@ -855,7 +855,7 @@ public class ProcedureCallImpl return this; } - // todo (5.3) : all of the parameter stuff here can be done in AbstractProducedQuery + // todo (5.3) : all of the parameter stuff here can be done in AbstractQuery // using #getParameterMetadata and #getQueryParameterBindings for abstraction. // this "win" is to define these in one place diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java b/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java deleted file mode 100644 index 229ec8639e..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractProducedQuery.java +++ /dev/null @@ -1,1602 +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 . - */ -package org.hibernate.query.internal; - -import java.io.Serializable; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.OffsetDateTime; -import java.time.ZonedDateTime; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; -import javax.persistence.CacheRetrieveMode; -import javax.persistence.CacheStoreMode; -import javax.persistence.FlushModeType; -import javax.persistence.LockModeType; -import javax.persistence.NoResultException; -import javax.persistence.Parameter; -import javax.persistence.TemporalType; - -import org.hibernate.CacheMode; -import org.hibernate.FlushMode; -import org.hibernate.HibernateException; -import org.hibernate.LockMode; -import org.hibernate.LockOptions; -import org.hibernate.NonUniqueResultException; -import org.hibernate.NotYetImplementedFor6Exception; -import org.hibernate.PropertyNotFoundException; -import org.hibernate.QueryParameterException; -import org.hibernate.ScrollMode; -import org.hibernate.TypeMismatchException; -import org.hibernate.dialect.Dialect; -import org.hibernate.engine.query.spi.EntityGraphQueryHint; -import org.hibernate.engine.spi.ExceptionConverter; -import org.hibernate.engine.spi.QueryParameters; -import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.graph.GraphSemantic; -import org.hibernate.graph.RootGraph; -import org.hibernate.graph.spi.RootGraphImplementor; -import org.hibernate.internal.EntityManagerMessageLogger; -import org.hibernate.internal.HEMLogging; -import org.hibernate.jpa.QueryHints; -import org.hibernate.jpa.internal.util.ConfigurationHelper; -import org.hibernate.jpa.internal.util.FlushModeTypeHelper; -import org.hibernate.jpa.internal.util.LockModeTypeHelper; -import org.hibernate.metamodel.model.domain.AllowableParameterType; -import org.hibernate.property.access.spi.BuiltInPropertyAccessStrategies; -import org.hibernate.property.access.spi.Getter; -import org.hibernate.property.access.spi.PropertyAccess; -import org.hibernate.query.ParameterMetadata; -import org.hibernate.query.Query; -import org.hibernate.query.QueryParameter; -import org.hibernate.query.TypedParameterValue; -import org.hibernate.query.spi.MutableQueryOptions; -import org.hibernate.query.spi.QueryImplementor; -import org.hibernate.query.spi.QueryParameterBinding; -import org.hibernate.query.spi.QueryParameterBindings; -import org.hibernate.query.spi.QueryParameterImplementor; -import org.hibernate.query.spi.ScrollableResultsImplementor; -import org.hibernate.query.spi.StreamDecorator; -import org.hibernate.transform.ResultTransformer; - -import org.jboss.logging.Logger; - -import static org.hibernate.LockOptions.WAIT_FOREVER; -import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_LOCK_SCOPE; -import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_LOCK_TIMEOUT; -import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE; -import static org.hibernate.cfg.AvailableSettings.JAKARTA_JPA_SHARED_CACHE_STORE_MODE; -import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_SCOPE; -import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_TIMEOUT; -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.jpa.AvailableSettings.ALIAS_SPECIFIC_LOCK_MODE; -import static org.hibernate.jpa.QueryHints.HINT_CACHEABLE; -import static org.hibernate.jpa.QueryHints.HINT_CACHE_MODE; -import static org.hibernate.jpa.QueryHints.HINT_CACHE_REGION; -import static org.hibernate.jpa.QueryHints.HINT_COMMENT; -import static org.hibernate.jpa.QueryHints.HINT_FETCHGRAPH; -import static org.hibernate.jpa.QueryHints.HINT_FETCH_SIZE; -import static org.hibernate.jpa.QueryHints.HINT_FLUSH_MODE; -import static org.hibernate.jpa.QueryHints.HINT_FOLLOW_ON_LOCKING; -import static org.hibernate.jpa.QueryHints.HINT_LOADGRAPH; -import static org.hibernate.jpa.QueryHints.HINT_NATIVE_SPACES; -import static org.hibernate.jpa.QueryHints.HINT_READONLY; -import static org.hibernate.jpa.QueryHints.HINT_TIMEOUT; -import static org.hibernate.jpa.QueryHints.JAKARTA_HINT_FETCHGRAPH; -import static org.hibernate.jpa.QueryHints.JAKARTA_HINT_LOADGRAPH; -import static org.hibernate.jpa.QueryHints.JAKARTA_SPEC_HINT_TIMEOUT; -import static org.hibernate.jpa.QueryHints.SPEC_HINT_TIMEOUT; - -/** - * @author Steve Ebersole - */ -public abstract class AbstractProducedQuery implements QueryImplementor { - private static final EntityManagerMessageLogger MSG_LOGGER = HEMLogging.messageLogger( AbstractProducedQuery.class ); - private static final Logger LOGGER = Logger.getLogger( AbstractProducedQuery.class ); - - private final SharedSessionContractImplementor producer; - private final ParameterMetadata parameterMetadata; - - private ResultTransformer resultTransformer; - private MutableQueryOptions queryOptions = new QueryOptionsImpl(); - - private EntityGraphQueryHint entityGraphQueryHint; - - private Object optionalObject; - private Serializable optionalId; - private String optionalEntityName; - - private Boolean passDistinctThrough; - - public AbstractProducedQuery( - SharedSessionContractImplementor producer, - ParameterMetadata parameterMetadata) { - this.producer = producer; - this.parameterMetadata = parameterMetadata; - } - - @Override - public MutableQueryOptions getQueryOptions() { - return queryOptions; - } - - @Override - public FlushMode getHibernateFlushMode() { - return getQueryOptions().getFlushMode(); - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setHibernateFlushMode(FlushMode flushMode) { - getQueryOptions().setFlushMode( flushMode ); - return this; - } - - @Override - public FlushModeType getFlushMode() { - getSession().checkOpen(); - return getHibernateFlushMode() == null - ? getSession().getFlushMode() - : FlushModeTypeHelper.getFlushModeType( getHibernateFlushMode() ); - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setFlushMode(FlushModeType flushModeType) { - getSession().checkOpen(); - setHibernateFlushMode( FlushModeTypeHelper.getFlushMode( flushModeType ) ); - return this; - } - - @Override - public CacheMode getCacheMode() { - return getQueryOptions().getCacheMode(); - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setCacheMode(CacheMode cacheMode) { - getQueryOptions().setCacheMode( cacheMode ); - return this; - } - - @Override - public boolean isCacheable() { - return getQueryOptions().isResultCachingEnabled(); - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setCacheable(boolean cacheable) { - getQueryOptions().setResultCachingEnabled( cacheable ); - return this; - } - - @Override - public String getCacheRegion() { - return getQueryOptions().getResultCacheRegionName(); - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setCacheRegion(String cacheRegion) { - getQueryOptions().setResultCacheRegionName( cacheRegion ); - return this; - } - - @Override - public Integer getTimeout() { - return queryOptions.getTimeout(); - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setTimeout(int timeout) { - queryOptions.setTimeout( timeout ); - return this; - } - - @Override - public Integer getFetchSize() { - return queryOptions.getFetchSize(); - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setFetchSize(int fetchSize) { - queryOptions.setFetchSize( fetchSize ); - return this; - } - - @Override - public boolean isReadOnly() { - return getQueryOptions().isReadOnly() == null - ? getSession().isDefaultReadOnly() - : getQueryOptions().isReadOnly(); - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setReadOnly(boolean readOnly) { - getQueryOptions().setReadOnly( readOnly ); - return this; - } - - @Override - public LockOptions getLockOptions() { - return getQueryOptions().getLockOptions(); - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setLockOptions(LockOptions lockOptions) { - getQueryOptions().getLockOptions().setLockMode( lockOptions.getLockMode() ); - getQueryOptions().getLockOptions().setScope( lockOptions.getScope() ); - getQueryOptions().getLockOptions().setTimeOut( lockOptions.getTimeOut() ); - getQueryOptions().getLockOptions().setFollowOnLocking( lockOptions.getFollowOnLocking() ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setLockMode(String alias, LockMode lockMode) { - getQueryOptions().getLockOptions().setAliasSpecificLockMode( alias, lockMode ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setLockMode(LockModeType lockModeType) { - getSession().checkOpen(); - if ( !LockModeType.NONE.equals( lockModeType ) ) { - if ( !isSelect() ) { - throw new IllegalStateException( "Illegal attempt to set lock mode on a non-SELECT query" ); - } - } - getQueryOptions().getLockOptions().setLockMode( LockModeTypeHelper.getLockMode( lockModeType ) ); - return this; - } - - @Override - public String getComment() { - return getQueryOptions().getComment(); - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setComment(String comment) { - getQueryOptions().setComment( comment ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor addQueryHint(String hint) { - getQueryOptions().addDatabaseHint( hint ); - return this; - } - - @Override - public ParameterMetadata getParameterMetadata() { - return parameterMetadata; - } - - @Override - public QueryImplementor setParameter(Parameter param, Instant value, TemporalType temporalType) { - locateBinding( param ).setBindValue( value, temporalType ); - return this; - } - - @Override - public QueryImplementor setParameter(Parameter param, LocalDateTime value, TemporalType temporalType) { - locateBinding( param ).setBindValue( value, temporalType ); - return this; - } - - @Override - public QueryImplementor setParameter(Parameter param, ZonedDateTime value, TemporalType temporalType) { - locateBinding( param ).setBindValue( value, temporalType ); - return this; - } - - @Override - public QueryImplementor setParameter(Parameter param, OffsetDateTime value, TemporalType temporalType) { - locateBinding( param ).setBindValue( value, temporalType ); - return this; - } - - @Override - public QueryImplementor setParameter(String name, Instant value, TemporalType temporalType) { - locateBinding( name ).setBindValue( value, temporalType ); - return this; - } - - @Override - public QueryImplementor setParameter(String name, LocalDateTime value, TemporalType temporalType) { - locateBinding( name ).setBindValue( value, temporalType ); - return this; - } - - @Override - public QueryImplementor setParameter(String name, ZonedDateTime value, TemporalType temporalType) { - locateBinding( name ).setBindValue( value, temporalType ); - return this; - } - - @Override - public QueryImplementor setParameter(String name, OffsetDateTime value, TemporalType temporalType) { - locateBinding( name ).setBindValue( value, temporalType ); - return this; - } - - @Override - public QueryImplementor setParameter(int position, Instant value, TemporalType temporalType) { - locateBinding( position ).setBindValue( value, temporalType ); - return this; - } - - @Override - public QueryImplementor setParameter(int position, LocalDateTime value, TemporalType temporalType) { - locateBinding( position ).setBindValue( value, temporalType ); - return this; - } - - @Override - public QueryImplementor setParameter(int position, ZonedDateTime value, TemporalType temporalType) { - locateBinding( position ).setBindValue( value, temporalType ); - return this; - } - - @Override - public QueryImplementor setParameter(int position, OffsetDateTime value, TemporalType temporalType) { - final QueryParameterBinding binding = getQueryParameterBindings().getBinding( - getParameterMetadata().getQueryParameter( position ) - ); - - binding.setBindValue( value, temporalType ); - - return this; - } - - @Override - @SuppressWarnings("unchecked") - public

QueryImplementor setParameter(QueryParameter

parameter, P value) { - getQueryParameterBindings().getBinding( parameter ).setBindValue( value ); - return this; - } - - @SuppressWarnings("unchecked") - private

QueryParameterBinding

locateBinding(Parameter

parameter) { - if ( parameter instanceof QueryParameterImplementor ) { - return getQueryParameterBindings().getBinding( (QueryParameterImplementor) parameter ); - } - else if ( parameter.getName() != null ) { - return (QueryParameterBinding) getQueryParameterBindings().getBinding( parameter.getName() ); - } - else if ( parameter.getPosition() != null ) { - return (QueryParameterBinding) getQueryParameterBindings().getBinding( parameter.getPosition() ); - } - - throw getExceptionConverter().convert( - new IllegalArgumentException( "Could not resolve binding for given parameter reference [" + parameter + "]" ) - ); - } - - private

QueryParameterBinding

locateBinding(String name) { - //noinspection unchecked - return (QueryParameterBinding) getQueryParameterBindings().getBinding( name ); - } - - private

QueryParameterBinding

locateBinding(int position) { - //noinspection unchecked - return (QueryParameterBinding) getQueryParameterBindings().getBinding( position ); - } - - @Override - @SuppressWarnings("unchecked") - public

QueryImplementor setParameter(Parameter

parameter, P value) { - getSession().checkOpen(); - if ( value instanceof TypedParameterValue ) { - setParameter( - parameter, - ( (TypedParameterValue) value ).getValue(), - ( (TypedParameterValue) value ).getType() - ); - } - else { - locateBinding( parameter ).setBindValue( value ); - } - - return this; - } - - @SuppressWarnings("unchecked") - private

void setParameter(Parameter

parameter, Object value, AllowableParameterType type) { - if ( parameter instanceof QueryParameter ) { - setParameter( (QueryParameter) parameter, value, type ); - } - else if ( value == null ) { - locateBinding( parameter ).setBindValue( null, type ); - } - else { - locateBinding( parameter ).setBindValue( (P) value, type ); - } - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameter(String name, Object value) { - getSession().checkOpen(); - if ( value instanceof TypedParameterValue ) { - final TypedParameterValue typedValueWrapper = (TypedParameterValue) value; - setParameter( name, typedValueWrapper.getValue(), typedValueWrapper.getType() ); - } - else if ( value instanceof Collection && !isRegisteredAsBasicType( value.getClass() ) ) { - setParameterList( name, (Collection) value ); - } - else { - getQueryParameterBindings().getBinding( name ).setBindValue( value ); - } - - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameter(int position, Object value) { - getSession().checkOpen(); - if ( value instanceof TypedParameterValue ) { - final TypedParameterValue typedParameterValue = (TypedParameterValue) value; - setParameter( position, typedParameterValue.getValue(), typedParameterValue.getType() ); - } - else if ( value instanceof Collection && !isRegisteredAsBasicType( value.getClass() ) ) { - setParameterList( position, (Collection) value ); - } - else { - getQueryParameterBindings().getBinding( position ).setBindValue( value ); - } - return this; - } - - @Override - @SuppressWarnings("unchecked") - public

QueryImplementor setParameter(QueryParameter

parameter, P value, AllowableParameterType type) { - getQueryParameterBindings().getBinding( parameter ).setBindValue( value, type ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameter(String name, Object value, AllowableParameterType type) { - getQueryParameterBindings().getBinding( name ).setBindValue( value, type ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameter(int position, Object value, AllowableParameterType type) { - getQueryParameterBindings().getBinding( position ).setBindValue( value, type ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public

QueryImplementor setParameter(QueryParameter

parameter, P value, TemporalType temporalType) { - getQueryParameterBindings().getBinding( parameter ).setBindValue( value, temporalType ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameter(String name, Object value, TemporalType temporalType) { - getQueryParameterBindings().getBinding( name ).setBindValue( value, temporalType ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameter(int position, Object value, TemporalType temporalType) { - getQueryParameterBindings().getBinding( position ).setBindValue( value, temporalType ); - return this; - } - - @Override - public

QueryImplementor setParameterList(QueryParameter

parameter, Collection

values) { - getQueryParameterBindings().getBinding( parameter ).setBindValues( values ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameterList(String name, Collection values) { - getQueryParameterBindings().getBinding( name ).setBindValues( values ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameterList(int position, Collection values) { - getQueryParameterBindings().getBinding( position ).setBindValues( values ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameterList(String name, Collection values, AllowableParameterType type) { - getQueryParameterBindings().getBinding( name ).setBindValues( values, type ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameterList(int position, Collection values, AllowableParameterType type) { - getQueryParameterBindings().getBinding( position ).setBindValues( values, type ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameterList(String name, Object[] values, AllowableParameterType type) { - getQueryParameterBindings().getBinding( name ).setBindValues( Arrays.asList( values ), type ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameterList(int position, Object[] values, AllowableParameterType type) { - getQueryParameterBindings().getBinding( position ).setBindValues( Arrays.asList( values ), type ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameterList(String name, Object[] values) { - getQueryParameterBindings().getBinding( name ).setBindValues( Arrays.asList( values ) ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameterList(int position, Object[] values) { - getQueryParameterBindings().getBinding( position ).setBindValues( Arrays.asList( values ) ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameter(Parameter param, Calendar value, TemporalType temporalType) { - getSession().checkOpen(); - getQueryParameterBindings().getBinding( (QueryParameter) param ).setBindValue( value, temporalType ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameter(Parameter param, Date value, TemporalType temporalType) { - getSession().checkOpen(); - getQueryParameterBindings().getBinding( (QueryParameter) param ).setBindValue( value, temporalType ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameter(String name, Calendar value, TemporalType temporalType) { - getSession().checkOpen(); - getQueryParameterBindings().getBinding( name ).setBindValue( value, temporalType ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameter(String name, Date value, TemporalType temporalType) { - getSession().checkOpen(); - getQueryParameterBindings().getBinding( name ).setBindValue( value, temporalType ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameter(int position, Calendar value, TemporalType temporalType) { - getSession().checkOpen(); - getQueryParameterBindings().getBinding( position ).setBindValue( value, temporalType ); - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setParameter(int position, Date value, TemporalType temporalType) { - getSession().checkOpen(); - getQueryParameterBindings().getBinding( position ).setBindValue( value, temporalType ); - return this; - } - - @Override - public Set> getParameters() { - getSession().checkOpen( false ); - //noinspection unchecked - return (Set) getParameterMetadata().getRegistrations(); - } - - @Override - public QueryParameter getParameter(String name) { - getSession().checkOpen( false ); - try { - return getParameterMetadata().getQueryParameter( name ); - } - catch ( HibernateException e ) { - throw getExceptionConverter().convert( e ); - } - } - - @Override - @SuppressWarnings("unchecked") - public QueryParameter getParameter(String name, Class type) { - getSession().checkOpen( false ); - try { - final QueryParameter parameter = getParameterMetadata().getQueryParameter( name ); - if ( !parameter.getParameterType().isAssignableFrom( type ) ) { - throw new IllegalArgumentException( - "The type [" + parameter.getParameterType().getName() + - "] associated with the parameter corresponding to name [" + name + - "] is not assignable to requested Java type [" + type.getName() + "]" - ); - } - return parameter; - } - catch ( HibernateException e ) { - throw getExceptionConverter().convert( e ); - } - } - - @Override - public QueryParameter getParameter(int position) { - getSession().checkOpen( false ); - try { - return parameterMetadata.getQueryParameter( position ); - } - catch (HibernateException e) { - throw getExceptionConverter().convert( e ); - } - } - - @Override - @SuppressWarnings("unchecked") - public QueryParameter getParameter(int position, Class type) { - getSession().checkOpen( false ); - try { - final QueryParameter parameter = getParameterMetadata().getQueryParameter( position ); - if ( !parameter.getParameterType().isAssignableFrom( type ) ) { - throw new IllegalArgumentException( - "The type [" + parameter.getParameterType().getName() + - "] associated with the parameter corresponding to position [" + position + - "] is not assignable to requested Java type [" + type.getName() + "]" - ); - } - return parameter; - } - catch ( HibernateException e ) { - throw getExceptionConverter().convert( e ); - } - } - - @Override - public boolean isBound(Parameter parameter) { - getSession().checkOpen(); - return getQueryParameterBindings().getBinding( (QueryParameterImplementor) parameter ).isBound(); - } - - @Override - public T getParameterValue(Parameter parameter) { - LOGGER.tracef( "#getParameterValue(%s)", parameter ); - - getSession().checkOpen( false ); - - if ( !getParameterMetadata().containsReference( (QueryParameter) parameter ) ) { - throw new IllegalArgumentException( "Parameter reference [" + parameter + "] did not come from this query" ); - } - - final QueryParameterBinding binding = getQueryParameterBindings().getBinding( (QueryParameter) parameter ); - LOGGER.debugf( "Checking whether parameter reference [%s] is bound : %s", parameter, binding.isBound() ); - if ( !binding.isBound() ) { - throw new IllegalStateException( "Parameter value not yet bound : " + parameter.toString() ); - } - return binding.getBindValue(); - } - - @Override - public Object getParameterValue(String name) { - getSession().checkOpen( false ); - - final QueryParameterBinding binding; - try { - binding = getQueryParameterBindings().getBinding( name ); - } - catch (QueryParameterException e) { - throw new IllegalArgumentException( "Could not resolve parameter by name - " + name, e ); - } - - LOGGER.debugf( "Checking whether named parameter [%s] is bound : %s", name, binding.isBound() ); - if ( !binding.isBound() ) { - throw new IllegalStateException( "Parameter value not yet bound : " + name ); - } - return binding.getBindValue(); - } - - @Override - public Object getParameterValue(int position) { - getSession().checkOpen( false ); - - final QueryParameterBinding binding; - try { - binding = getQueryParameterBindings().getBinding( position ); - } - catch (QueryParameterException e) { - throw new IllegalArgumentException( "Could not resolve parameter by position - " + position, e ); - } - - LOGGER.debugf( "Checking whether positional parameter [%s] is bound : %s", (Integer) position, (Boolean) binding.isBound() ); - if ( !binding.isBound() ) { - throw new IllegalStateException( "Parameter value not yet bound : " + position ); - } - return binding.getBindValue(); - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setProperties(Object bean) { - final Class clazz = bean.getClass(); - parameterMetadata.visitRegistrations( - queryParameter -> { - final String parameterName = queryParameter.getName(); - if ( parameterName != null ) { - try { - final PropertyAccess propertyAccess = BuiltInPropertyAccessStrategies.BASIC.getStrategy().buildPropertyAccess( - clazz, - parameterName - ); - final Getter getter = propertyAccess.getGetter(); - final Class retType = getter.getReturnTypeClass(); - final Object object = getter.get( bean ); - if ( Collection.class.isAssignableFrom( retType ) ) { - setParameterList( parameterName, (Collection) object ); - } - else if ( retType.isArray() ) { - setParameterList( parameterName, (Object[]) object ); - } - else { - setParameter( parameterName, object, determineType( parameterName, retType ) ); - } - } - catch (PropertyNotFoundException e) { - // ignore - } - } - } - ); - - return this; - } - - protected AllowableParameterType determineType(String namedParam, Class retType) { - AllowableParameterType type = getQueryParameterBindings().getBinding( namedParam ).getBindType(); - if ( type == null ) { - type = getParameterMetadata().getQueryParameter( namedParam ).getHibernateType(); - } - if ( type == null ) { - type = getSession().getFactory().resolveParameterBindType( retType ); - } - return type; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setProperties(Map map) { - parameterMetadata.visitRegistrations( - queryParameter -> { - final String parameterName = queryParameter.getName(); - if ( parameterName != null ) { - final Object value = map.get( parameterName ); - - if ( value == null ) { - if ( map.containsKey( parameterName ) ) { - setParameter( parameterName, null, determineType( parameterName, null ) ); - } - } - else { - Class retType = value.getClass(); - if ( Collection.class.isAssignableFrom( retType ) ) { - setParameterList( parameterName, (Collection) value ); - } - else if ( retType.isArray() ) { - setParameterList( parameterName, (Object[]) value ); - } - else { - setParameter( parameterName, value, determineType( parameterName, retType ) ); - } - } - } - } - ); - - return this; - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setResultTransformer(ResultTransformer transformer) { - this.resultTransformer = transformer; - return this; - } - - @Override - public int getMaxResults() { - getSession().checkOpen(); - // to be JPA compliant this method returns an int - specifically the "magic number" Integer.MAX_VALUE defined by the spec. - // For access to the Integer (for checking), use #getQueryOptions#getMaxRows instead - return queryOptions.getMaxRows() == null ? Integer.MAX_VALUE : queryOptions.getMaxRows(); - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setMaxResults(int maxResult) { - getSession().checkOpen(); - - if ( maxResult < 0 ) { - throw new IllegalArgumentException( "max-results cannot be negative" ); - } - else { - queryOptions.getLimit().setMaxRows( maxResult ); - } - return this; - } - - @Override - public int getFirstResult() { - getSession().checkOpen(); - // to be JPA compliant this method returns an int - specifically the "magic number" 0 (ZERO) defined by the spec. - // For access to the Integer (for checking), use #getQueryOptions#getFirstRow instead - return queryOptions.getFirstRow() == null ? 0 : queryOptions.getFirstRow(); - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setFirstResult(int startPosition) { - getSession().checkOpen(); - if ( startPosition < 0 ) { - throw new IllegalArgumentException( "first-result value cannot be negative : " + startPosition ); - } - queryOptions.getLimit().setFirstRow( startPosition ); - return this; - } - - @SuppressWarnings( {"UnusedDeclaration"}) - public Set getSupportedHints() { - return QueryHints.getDefinedHints(); - } - - @Override - public Map getHints() { - // Technically this should rollback, but that's insane :) - // If the TCK ever adds a check for this, we may need to change this behavior - getSession().checkOpen( false ); - - final Map hints = new HashMap<>(); - collectBaselineHints( hints ); - collectHints( hints ); - return hints; - } - - protected void collectBaselineHints(Map hints) { - // nothing to do in this form - } - - protected void collectHints(Map hints) { - final MutableQueryOptions queryOptions = getQueryOptions(); - final Integer queryTimeout = queryOptions.getTimeout(); - if ( queryTimeout != null ) { - hints.put( HINT_TIMEOUT, queryTimeout ); - hints.put( SPEC_HINT_TIMEOUT, queryTimeout * 1000 ); - hints.put( JAKARTA_SPEC_HINT_TIMEOUT, queryTimeout * 1000 ); - } - - final LockOptions lockOptions = getLockOptions(); - final int lockOptionsTimeOut = lockOptions.getTimeOut(); - if ( lockOptionsTimeOut != WAIT_FOREVER ) { - hints.put( JPA_LOCK_TIMEOUT, lockOptionsTimeOut ); - hints.put( JAKARTA_JPA_LOCK_TIMEOUT, lockOptionsTimeOut ); - } - - if ( lockOptions.getScope() ) { - hints.put( JPA_LOCK_SCOPE, lockOptions.getScope() ); - hints.put( JAKARTA_JPA_LOCK_SCOPE, lockOptions.getScope() ); - } - - if ( lockOptions.hasAliasSpecificLockModes() && canApplyAliasSpecificLockModeHints() ) { - for ( Map.Entry entry : lockOptions.getAliasSpecificLocks() ) { - hints.put( - ALIAS_SPECIFIC_LOCK_MODE + '.' + entry.getKey(), - entry.getValue().name() - ); - } - } - - putIfNotNull( hints, HINT_COMMENT, getComment() ); - putIfNotNull( hints, HINT_FETCH_SIZE, queryOptions.getFetchSize() ); - putIfNotNull( hints, HINT_FLUSH_MODE, getHibernateFlushMode() ); - - final CacheMode cacheMode = getQueryOptions().getCacheMode(); - if ( cacheMode != null ) { - putIfNotNull( hints, HINT_CACHE_MODE, cacheMode ); - putIfNotNull( hints, JPA_SHARED_CACHE_RETRIEVE_MODE, cacheMode.getJpaRetrieveMode() ); - putIfNotNull( hints, JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE, cacheMode.getJpaRetrieveMode( ) ); - putIfNotNull( hints, JPA_SHARED_CACHE_STORE_MODE, cacheMode.getJpaStoreMode() ); - putIfNotNull( hints, JAKARTA_JPA_SHARED_CACHE_STORE_MODE, cacheMode.getJpaStoreMode() ); - } - - if ( isCacheable() ) { - hints.put( HINT_CACHEABLE, true ); - putIfNotNull( hints, HINT_CACHE_REGION, getCacheRegion() ); - } - - if ( isReadOnly() ) { - hints.put( HINT_READONLY, true ); - } - - if ( entityGraphQueryHint != null ) { - hints.put( entityGraphQueryHint.getSemantic().getJpaHintName(), entityGraphQueryHint.getGraph() ); - } - } - - protected void putIfNotNull(Map hints, String hintName, Enum hintValue) { - // centralized spot to handle the decision whether to put enums directly into the hints map - // or whether to put the enum name - if ( hintValue != null ) { - hints.put( hintName, hintValue ); -// hints.put( hintName, hintValue.name() ); - } - } - - protected void putIfNotNull(Map hints, String hintName, Object hintValue) { - if ( hintValue != null ) { - hints.put( hintName, hintValue ); - } - } - - @Override - @SuppressWarnings("unchecked") - public QueryImplementor setHint(String hintName, Object value) { - getSession().checkOpen( true ); - boolean applied = false; - try { - if ( HINT_TIMEOUT.equals( hintName ) ) { - applied = applyTimeoutHint( ConfigurationHelper.getInteger( value ) ); - } - else if ( SPEC_HINT_TIMEOUT.equals( hintName ) || JAKARTA_SPEC_HINT_TIMEOUT.equals( hintName ) ) { - // convert milliseconds to seconds - int timeout = (int)Math.round( ConfigurationHelper.getInteger( value ).doubleValue() / 1000.0 ); - applied = applyTimeoutHint( timeout ); - } - else if ( JPA_LOCK_TIMEOUT.equals( hintName ) || JAKARTA_JPA_LOCK_TIMEOUT.equals( hintName ) ) { - applied = applyLockTimeoutHint( ConfigurationHelper.getInteger( value ) ); - } - else if ( HINT_COMMENT.equals( hintName ) ) { - applied = applyCommentHint( (String) value ); - } - else if ( HINT_FETCH_SIZE.equals( hintName ) ) { - applied = applyFetchSizeHint( ConfigurationHelper.getInteger( value ) ); - } - else if ( HINT_CACHEABLE.equals( hintName ) ) { - applied = applyCacheableHint( ConfigurationHelper.getBoolean( value ) ); - } - else if ( HINT_CACHE_REGION.equals( hintName ) ) { - applied = applyCacheRegionHint( (String) value ); - } - else if ( HINT_READONLY.equals( hintName ) ) { - applied = applyReadOnlyHint( ConfigurationHelper.getBoolean( value ) ); - } - else if ( HINT_FLUSH_MODE.equals( hintName ) ) { - applied = applyFlushModeHint( ConfigurationHelper.getFlushMode( value ) ); - } - else if ( HINT_CACHE_MODE.equals( hintName ) ) { - applied = applyCacheModeHint( ConfigurationHelper.getCacheMode( value ) ); - } - else if ( JPA_SHARED_CACHE_RETRIEVE_MODE.equals( hintName ) || JAKARTA_JPA_SHARED_CACHE_RETRIEVE_MODE.equals( hintName ) ) { - final CacheRetrieveMode retrieveMode = value != null ? CacheRetrieveMode.valueOf( value.toString() ) : null; - applied = applyJpaCacheRetrieveMode( retrieveMode ); - } - else if ( JPA_SHARED_CACHE_STORE_MODE.equals( hintName ) || JAKARTA_JPA_SHARED_CACHE_STORE_MODE.equals( hintName ) ) { - final CacheStoreMode storeMode = value != null ? CacheStoreMode.valueOf( value.toString() ) : null; - applied = applyJpaCacheStoreMode( storeMode ); - } - else if ( HINT_NATIVE_SPACES.equals( hintName ) ) { - applied = applyQuerySpaces( value ); - } - else if ( QueryHints.HINT_NATIVE_LOCKMODE.equals( hintName ) ) { - applied = applyNativeQueryLockMode( value ); - } - else if ( hintName.startsWith( ALIAS_SPECIFIC_LOCK_MODE ) ) { - if ( canApplyAliasSpecificLockModeHints() ) { - // extract the alias - final String alias = hintName.substring( ALIAS_SPECIFIC_LOCK_MODE.length() + 1 ); - // determine the LockMode - try { - final LockMode lockMode = LockModeTypeHelper.interpretLockMode( value ); - applyAliasSpecificLockModeHint( alias, lockMode ); - } - catch ( Exception e ) { - MSG_LOGGER.unableToDetermineLockModeValue( hintName, value ); - applied = false; - } - } - else { - applied = false; - } - } - else if ( HINT_FETCHGRAPH.equals( hintName ) - || HINT_LOADGRAPH.equals( hintName ) - || JAKARTA_HINT_FETCHGRAPH.equals( hintName ) - || JAKARTA_HINT_LOADGRAPH.equals( hintName ) ) { - if ( value instanceof RootGraph ) { - applyGraph( (RootGraph) value, GraphSemantic.fromJpaHintName( hintName ) ); - } - else { - MSG_LOGGER.warnf( "The %s hint was set, but the value was not an EntityGraph!", hintName ); - } - applied = true; - } - else if ( HINT_FOLLOW_ON_LOCKING.equals( hintName ) ) { - applied = applyFollowOnLockingHint( ConfigurationHelper.getBoolean( value ) ); - } - else if ( QueryHints.HINT_PASS_DISTINCT_THROUGH.equals( hintName ) ) { - applied = applyPassDistinctThrough( ConfigurationHelper.getBoolean( value ) ); - } - else { - MSG_LOGGER.ignoringUnrecognizedQueryHint( hintName ); - } - } - catch ( ClassCastException e ) { - throw new IllegalArgumentException( "Value for hint" ); - } - - if ( !applied ) { - handleUnrecognizedHint( hintName, value ); - } - - return this; - } - - protected boolean applyQuerySpaces(Object value) { - throw new IllegalStateException( - "Illegal attempt to apply native-query spaces to a non-native query" - ); - } - - protected void handleUnrecognizedHint(String hintName, Object value) { - MSG_LOGGER.debugf( "Skipping unsupported query hint [%s]", hintName ); - } - - protected boolean applyJpaCacheRetrieveMode(CacheRetrieveMode mode) { - getQueryOptions().setCacheRetrieveMode( mode ); - return true; - } - - protected boolean applyJpaCacheStoreMode(CacheStoreMode mode) { - getQueryOptions().setCacheStoreMode( mode ); - return true; - } - - protected boolean applyNativeQueryLockMode(Object value) { - if ( !isNativeQuery() ) { - throw new IllegalStateException( - "Illegal attempt to set lock mode on non-native query via hint; use Query#setLockMode instead" - ); - } - - return false; - } - - /** - * Apply the query timeout hint. - * - * @param timeout The timeout (in seconds!) specified as a hint - * - * @return {@code true} if the hint was "applied" - */ - protected boolean applyTimeoutHint(int timeout) { - setTimeout( timeout ); - return true; - } - - /** - * Apply the lock timeout (in seconds!) hint - * - * @param timeout The timeout (in seconds!) specified as a hint - * - * @return {@code true} if the hint was "applied" - */ - protected boolean applyLockTimeoutHint(int timeout) { - getLockOptions().setTimeOut( timeout ); - return true; - } - - /** - * Apply the comment hint. - * - * @param comment The comment specified as a hint - * - * @return {@code true} if the hint was "applied" - */ - protected boolean applyCommentHint(String comment) { - setComment( comment ); - return true; - } - - /** - * Apply the fetch size hint - * - * @param fetchSize The fetch size specified as a hint - * - * @return {@code true} if the hint was "applied" - */ - protected boolean applyFetchSizeHint(int fetchSize) { - setFetchSize( fetchSize ); - return true; - } - - /** - * Apply the cacheable (true/false) hint. - * - * @param isCacheable The value specified as hint - * - * @return {@code true} if the hint was "applied" - */ - protected boolean applyCacheableHint(boolean isCacheable) { - setCacheable( isCacheable ); - return true; - } - - /** - * Apply the cache region hint - * - * @param regionName The name of the cache region specified as a hint - * - * @return {@code true} if the hint was "applied" - */ - protected boolean applyCacheRegionHint(String regionName) { - setCacheRegion( regionName ); - return true; - } - - /** - * Apply the read-only (true/false) hint. - * - * @param isReadOnly The value specified as hint - * - * @return {@code true} if the hint was "applied" - */ - protected boolean applyReadOnlyHint(boolean isReadOnly) { - setReadOnly( isReadOnly ); - return true; - } - - /** - * Apply the CacheMode hint. - * - * @param cacheMode The CacheMode value specified as a hint. - * - * @return {@code true} if the hint was "applied" - */ - protected boolean applyCacheModeHint(CacheMode cacheMode) { - setCacheMode( cacheMode ); - return true; - } - - /** - * Apply the FlushMode hint. - * - * @param flushMode The FlushMode value specified as hint - * - * @return {@code true} if the hint was "applied" - */ - protected boolean applyFlushModeHint(FlushMode flushMode) { - setHibernateFlushMode( flushMode ); - return true; - } - - /** - * Can alias-specific lock modes be applied? - * - * @return {@code true} indicates they can be applied, {@code false} otherwise. - */ - protected boolean canApplyAliasSpecificLockModeHints() { - // only procedure/function calls cannot i believe - return true; - } - - protected boolean applyLockModeTypeHint(LockModeType lockModeType) { - getLockOptions().setLockMode( LockModeTypeHelper.getLockMode( lockModeType ) ); - return true; - } - - protected boolean applyHibernateLockModeHint(LockMode lockMode) { - getLockOptions().setLockMode( lockMode ); - return true; - } - - /** - * Apply the alias specific lock modes. Assumes {@link #canApplyAliasSpecificLockModeHints()} has already been - * called and returned {@code true}. - * - * @param alias The alias to apply the 'lockMode' to. - * @param lockMode The LockMode to apply. - */ - protected void applyAliasSpecificLockModeHint(String alias, LockMode lockMode) { - getLockOptions().setAliasSpecificLockMode( alias, lockMode ); - } - - @Override - public Query applyGraph(RootGraph graph, GraphSemantic semantic) { - if ( semantic == null ) { - this.entityGraphQueryHint = null; - } - else { - if ( graph == null ) { - throw new IllegalStateException( "Semantic was non-null, but graph was null" ); - } - - applyGraph( (RootGraphImplementor) graph, semantic ); - } - - return this; - } - - /** - * Used from HEM code as a (hopefully temporary) means to apply a custom query plan - * in regards to a JPA entity graph. - * - * @param hint The entity graph hint object - * - * @deprecated (5.4) Use {@link #applyGraph} instead - */ - @Deprecated - protected void applyEntityGraphQueryHint(EntityGraphQueryHint hint) { - this.entityGraphQueryHint = hint; - } - - /** - * Apply the follow-on-locking hint. - * - * @param followOnLocking The follow-on-locking strategy. - */ - protected boolean applyFollowOnLockingHint(Boolean followOnLocking) { - getLockOptions().setFollowOnLocking( followOnLocking ); - return true; - } - - /** - * Apply the follow-on-locking hint. - * - * @param passDistinctThrough the query passes {@code distinct} to the database - */ - protected boolean applyPassDistinctThrough(boolean passDistinctThrough) { - this.passDistinctThrough = passDistinctThrough; - return true; - } - - /** - * Is the query represented here a native (SQL) query? - * - * @return {@code true} if it is a native query; {@code false} otherwise - */ - protected abstract boolean isNativeQuery(); - - @Override - public LockModeType getLockMode() { - getSession().checkOpen( false ); - if ( !isSelect() ) { - throw new IllegalStateException( "Illegal attempt to get lock mode on a non-SELECT query" ); - } - return LockModeTypeHelper.getLockModeType( getQueryOptions().getLockOptions().getLockMode() ); - } - - @Override - @SuppressWarnings("unchecked") - public T unwrap(Class cls) { - if ( cls.isInstance( getSession() ) ) { - return (T) getSession(); - } - if ( cls.isInstance( getParameterMetadata() ) ) { - return (T) getParameterMetadata(); - } - if ( cls.isInstance( getQueryParameterBindings() ) ) { - return (T) getQueryParameterBindings(); - } - if ( cls.isInstance( this ) ) { - return (T) this; - } - - throw new HibernateException( "Could not unwrap this [" + toString() + "] as requested Java type [" + cls.getName() + "]" ); -// throw new IllegalArgumentException( "Could not unwrap this [" + toString() + "] as requested Java type [" + cls.getName() + "]" ); - } - - public QueryParameters getQueryParameters() { - throw new NotYetImplementedFor6Exception( getClass() ); -// final String expandedQuery = getQueryParameterBindings().expandListValuedParameters( getQueryString(), getSession() ); -// return makeQueryParametersForExecution( expandedQuery ); - } - -// protected QueryParameters makeQueryParametersForExecution(String hql) { -// final HQLQueryPlan entityGraphHintedQueryPlan; -// if ( entityGraphQueryHint == null) { -// entityGraphHintedQueryPlan = null; -// } -// else { -// final SharedSessionContractImplementor producer = getProducer(); -// entityGraphHintedQueryPlan = new HQLQueryPlan( -// hql, -// false, -// producer.getLoadQueryInfluencers().getEnabledFilters(), -// producer.getFactory(), -// entityGraphQueryHint -// ); -// } -// -// QueryParameters queryParameters = new QueryParameters( -// getQueryParameterBindings(), -// getLockOptions(), -// queryOptions, -// true, -// isReadOnly(), -// cacheable, -// cacheRegion, -// comment, -// dbHints, -// null, -// optionalObject, -// optionalEntityName, -// optionalId, -// resultTransformer -// ); -// -// appendQueryPlanToQueryParameters( hql, queryParameters, entityGraphHintedQueryPlan ); -// -// if ( passDistinctThrough != null ) { -// queryParameters.setPassDistinctThrough( passDistinctThrough ); -// } -// return queryParameters; -// } - -// protected void appendQueryPlanToQueryParameters( -// String hql, -// QueryParameters queryParameters, -// HQLQueryPlan queryPlan) { -// if ( queryPlan != null ) { -// queryParameters.setQueryPlan( queryPlan ); -// } -// } - - private FlushMode sessionFlushMode; - private CacheMode sessionCacheMode; - - protected void beforeQuery() { - if ( optionalId == null ) { - getQueryParameterBindings().validate(); - } - - assert sessionFlushMode == null; - assert sessionCacheMode == null; - - final FlushMode flushMode = getQueryOptions().getFlushMode(); - if ( flushMode != null ) { - sessionFlushMode = getSession().getHibernateFlushMode(); - getSession().setHibernateFlushMode( flushMode ); - } - - final CacheMode effectiveCacheMode = CacheMode.fromJpaModes( queryOptions.getCacheRetrieveMode(), queryOptions.getCacheStoreMode() ); - if( effectiveCacheMode != null) { - sessionCacheMode = getSession().getCacheMode(); - getSession().setCacheMode( effectiveCacheMode ); - } - if ( entityGraphQueryHint != null && entityGraphQueryHint.getSemantic() == GraphSemantic.FETCH ) { - getSession().setEnforcingFetchGraph( true ); - } - } - - protected void afterQuery() { - if ( sessionFlushMode != null ) { - getSession().setHibernateFlushMode( sessionFlushMode ); - sessionFlushMode = null; - } - if ( sessionCacheMode != null ) { - getSession().setCacheMode( sessionCacheMode ); - sessionCacheMode = null; - } - getSession().setEnforcingFetchGraph( false ); - } - - @Override - public ScrollableResultsImplementor scroll() { - final Dialect dialect = getSession().getJdbcServices().getJdbcEnvironment().getDialect(); - return scroll( dialect.defaultScrollMode() ); - } - - @Override - public Stream stream() { - if (getMaxResults() == 0){ - final Spliterator spliterator = Spliterators.emptySpliterator(); - return StreamSupport.stream( spliterator, false ); - } - final ScrollableResultsImplementor scrollableResults = scroll( ScrollMode.FORWARD_ONLY ); - final ScrollableResultsIterator iterator = new ScrollableResultsIterator<>( scrollableResults ); - final Spliterator spliterator = Spliterators.spliteratorUnknownSize( iterator, Spliterator.NONNULL ); - - return new StreamDecorator<>( - StreamSupport.stream( spliterator, false ), - iterator::close - ); - } - - @Override - public Optional uniqueResultOptional() { - return Optional.ofNullable( uniqueResult() ); - } - - @Override - public List list() { - beforeQuery(); - try { - return doList(); - } - catch (TypeMismatchException e) { - throw new IllegalArgumentException( e ); - } - catch (HibernateException he) { - throw getExceptionConverter().convert( he, getLockOptions() ); - } - finally { - afterQuery(); - } - } - - protected boolean isCallable() { - return false; - } - - @SuppressWarnings("unchecked") - protected List doList() { - throw new NotYetImplementedFor6Exception( getClass() ); - -// if ( getMaxResults() == 0 ) { -// return Collections.EMPTY_LIST; -// } -// if ( lockOptions.getLockMode() != null && lockOptions.getLockMode() != LockMode.NONE ) { -// if ( !getSession().isTransactionInProgress() ) { -// throw new TransactionRequiredException( "no transaction is in progress" ); -// } -// } -// -// final String expandedQuery = getQueryParameterBindings().expandListValuedParameters( getQueryString(), getSession() ); -// return getSession().list( -// expandedQuery, -// makeQueryParametersForExecution( expandedQuery ) -// ); - } - - protected abstract QueryParameterBindings getQueryParameterBindings(); - - @Override - public R uniqueResult() { - return uniqueElement( list() ); - } - - @Override - public R getSingleResult() { - try { - final List list = list(); - if ( list.size() == 0 ) { - throw new NoResultException( "No entity found for query" ); - } - return uniqueElement( list ); - } - catch ( HibernateException e ) { - throw getExceptionConverter().convert( e, getLockOptions() ); - } - } - - public static R uniqueElement(List list) throws NonUniqueResultException { - int size = list.size(); - if ( size == 0 ) { - return null; - } - R first = list.get( 0 ); - for ( int i = 1; i < size; i++ ) { - if ( list.get( i ) != first ) { - throw new NonUniqueResultException( list.size() ); - } - } - return first; - } - - @Override - public int executeUpdate() throws HibernateException { - getSession().checkTransactionNeededForUpdateOperation( "Executing an update/delete query" ); - - beforeQuery(); - try { - return doExecuteUpdate(); - } - catch( TypeMismatchException e ) { - throw new IllegalArgumentException( e ); - } - catch ( HibernateException e) { - throw getExceptionConverter().convert( e ); - } - finally { - afterQuery(); - } - } - - protected int doExecuteUpdate() { - throw new NotYetImplementedFor6Exception( getClass() ); - -// final String expandedQuery = getQueryParameterBindings().expandListValuedParameters( getQueryString(), getSession() ); -// return getSession().executeUpdate( -// expandedQuery, -// makeQueryParametersForExecution( expandedQuery ) -// ); - } - - protected String resolveEntityName(Object val) { - if ( val == null ) { - throw new IllegalArgumentException( "entity for parameter binding cannot be null" ); - } - return getSession().bestGuessEntityName( val ); - } - - @Override - public void setOptionalEntityName(String optionalEntityName) { - this.optionalEntityName = optionalEntityName; - } - - @Override - public void setOptionalId(Serializable optionalId) { - this.optionalId = optionalId; - } - - @Override - public void setOptionalObject(Object optionalObject) { - this.optionalObject = optionalObject; - } - - protected boolean isSelect() { - throw new NotYetImplementedFor6Exception( getClass() ); - -// return getSession().getFactory().getQueryInterpretationCache() -// .getHQLQueryPlan( getQueryString(), false, Collections.emptyMap() ) -// .isSelect(); - } - - protected ExceptionConverter getExceptionConverter(){ - return producer.getExceptionConverter(); - } - - private boolean isRegisteredAsBasicType(Class cl) { - return producer.getFactory().getTypeConfiguration().getBasicTypeRegistry().getRegisteredType( cl.getName() ) != null; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/QuerySqmImpl.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/QuerySqmImpl.java index 1ac1daba2d..90112289af 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/QuerySqmImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/QuerySqmImpl.java @@ -525,8 +525,9 @@ public class QuerySqmImpl @Override protected List doList() { SqmUtil.verifyIsSelectStatement( getSqmStatement() ); - getSession().prepareForQueryExecution( requiresTxn( getLockOptions().findGreatestLockMode() ) ); final SqmSelectStatement selectStatement = (SqmSelectStatement) getSqmStatement(); + + getSession().prepareForQueryExecution( requiresTxn( getLockOptions().findGreatestLockMode() ) ); final boolean containsCollectionFetches = selectStatement.containsCollectionFetches(); final boolean hasLimit = queryOptions.hasLimit(); final boolean needsDistincting = containsCollectionFetches && ( @@ -535,7 +536,7 @@ public class QuerySqmImpl hasLimit ); final ExecutionContext executionContextToUse; - if ( queryOptions.hasLimit() && containsCollectionFetches ) { + if ( hasLimit && containsCollectionFetches ) { boolean fail = getSessionFactory().getSessionFactoryOptions().isFailOnPaginationOverCollectionFetchEnabled(); if (fail) { throw new HibernateException( diff --git a/hibernate-core/src/main/java/org/hibernate/sql/exec/spi/StatementOptions.java b/hibernate-core/src/main/java/org/hibernate/sql/exec/spi/StatementOptions.java new file mode 100644 index 0000000000..104a88b4a4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/sql/exec/spi/StatementOptions.java @@ -0,0 +1,61 @@ +/* + * 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.sql.exec.spi; + +/** + * Options for the creation of a JDBC statement + * + * @author Steve Ebersole + */ +public class StatementOptions { + public static final StatementOptions NONE = new StatementOptions( -1, -1, -1, -1 ); + + private final Integer firstRow; + private final Integer maxRows; + private final Integer timeoutInMilliseconds; + private final Integer fetchSize; + + public StatementOptions( + Integer firstRow, + Integer maxRows, + Integer timeoutInMilliseconds, + Integer fetchSize) { + this.firstRow = firstRow; + this.maxRows = maxRows; + this.timeoutInMilliseconds = timeoutInMilliseconds; + this.fetchSize = fetchSize; + } + + public boolean hasLimit() { + return ( firstRow != null && firstRow > 0 ) + || ( maxRows != null && maxRows > 0 ); + } + + public Integer getFirstRow() { + return firstRow; + } + + public Integer getMaxRows() { + return maxRows; + } + + public boolean hasTimeout() { + return timeoutInMilliseconds != null && timeoutInMilliseconds > 0; + } + + public Integer getTimeoutInMilliseconds() { + return timeoutInMilliseconds; + } + + public boolean hasFetchSize() { + return fetchSize != null && fetchSize > 0; + } + + public Integer getFetchSize() { + return fetchSize; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/RowProcessingStateStandardImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/RowProcessingStateStandardImpl.java index d7d76c5bb8..c001b8248f 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/RowProcessingStateStandardImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/RowProcessingStateStandardImpl.java @@ -15,6 +15,7 @@ import org.hibernate.query.spi.QueryOptions; import org.hibernate.query.spi.QueryParameterBindings; import org.hibernate.sql.exec.spi.Callback; import org.hibernate.sql.exec.spi.ExecutionContext; +import org.hibernate.sql.exec.spi.StatementOptions; import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.collection.CollectionInitializer; import org.hibernate.sql.results.graph.entity.EntityFetch; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/insertordering/BaseInsertOrderingTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/insertordering/BaseInsertOrderingTest.java index 38d20ed645..b87b9afb5b 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/insertordering/BaseInsertOrderingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/insertordering/BaseInsertOrderingTest.java @@ -7,7 +7,7 @@ import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Environment; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; -import org.hibernate.orm.test.util.jdbc.PreparedStatementSpyConnectionProvider; +import org.hibernate.testing.orm.jdbc.PreparedStatementSpyConnectionProvider; import org.hibernate.testing.orm.junit.BaseSessionFactoryFunctionalTest; import org.hibernate.testing.orm.junit.DialectFeatureChecks; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jdbc/internal/AggressiveReleaseTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jdbc/internal/AggressiveReleaseTest.java index 735f56ea9f..1b43e4ebfc 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jdbc/internal/AggressiveReleaseTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jdbc/internal/AggressiveReleaseTest.java @@ -21,7 +21,7 @@ import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode; import org.hibernate.testing.boot.BasicTestingJdbcServiceImpl; import org.hibernate.testing.orm.junit.BaseSessionFactoryFunctionalTest; import org.hibernate.testing.orm.junit.RequiresDialect; -import org.hibernate.orm.test.util.jdbc.PreparedStatementSpyConnectionProvider; +import org.hibernate.testing.orm.jdbc.PreparedStatementSpyConnectionProvider; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jdbc/internal/SessionJdbcBatchTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jdbc/internal/SessionJdbcBatchTest.java index b6394be2e3..895af48cfa 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jdbc/internal/SessionJdbcBatchTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jdbc/internal/SessionJdbcBatchTest.java @@ -20,7 +20,7 @@ import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; -import org.hibernate.orm.test.util.jdbc.PreparedStatementSpyConnectionProvider; +import org.hibernate.testing.orm.jdbc.PreparedStatementSpyConnectionProvider; import org.junit.Test; import static org.junit.Assert.assertEquals; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/ejb3configuration/DisableDiscardPersistenceContextOnCloseTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/ejb3configuration/DisableDiscardPersistenceContextOnCloseTest.java index baf1c56d40..434c63c4bc 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/ejb3configuration/DisableDiscardPersistenceContextOnCloseTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/ejb3configuration/DisableDiscardPersistenceContextOnCloseTest.java @@ -17,7 +17,7 @@ import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; import org.hibernate.testing.orm.junit.Jpa; import org.hibernate.testing.orm.junit.RequiresDialectFeature; import org.hibernate.testing.orm.junit.Setting; -import org.hibernate.orm.test.util.jdbc.PreparedStatementSpyConnectionProvider; +import org.hibernate.testing.orm.jdbc.PreparedStatementSpyConnectionProvider; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/ejb3configuration/EnableDiscardPersistenceContextOnCloseTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/ejb3configuration/EnableDiscardPersistenceContextOnCloseTest.java index 3786df9fc9..ed8335bf29 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/ejb3configuration/EnableDiscardPersistenceContextOnCloseTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/ejb3configuration/EnableDiscardPersistenceContextOnCloseTest.java @@ -16,7 +16,7 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; import org.hibernate.testing.orm.junit.Jpa; import org.hibernate.testing.orm.junit.Setting; -import org.hibernate.orm.test.util.jdbc.PreparedStatementSpyConnectionProvider; +import org.hibernate.testing.orm.jdbc.PreparedStatementSpyConnectionProvider; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/ejb3configuration/PreparedStatementSpyConnectionProviderSettingValueProvider.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/ejb3configuration/PreparedStatementSpyConnectionProviderSettingValueProvider.java index 35689c6f79..994445ed43 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/ejb3configuration/PreparedStatementSpyConnectionProviderSettingValueProvider.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/ejb3configuration/PreparedStatementSpyConnectionProviderSettingValueProvider.java @@ -7,7 +7,7 @@ package org.hibernate.orm.test.jpa.ejb3configuration; import org.hibernate.testing.orm.jpa.NonStringValueSettingProvider; -import org.hibernate.orm.test.util.jdbc.PreparedStatementSpyConnectionProvider; +import org.hibernate.testing.orm.jdbc.PreparedStatementSpyConnectionProvider; /** * @author Jan Schatteman diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/StatementIsClosedAfterALockExceptionTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/StatementIsClosedAfterALockExceptionTest.java index a69ec6f374..f07b2df059 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/StatementIsClosedAfterALockExceptionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/StatementIsClosedAfterALockExceptionTest.java @@ -14,7 +14,7 @@ import javax.persistence.LockModeType; import org.hibernate.Session; import org.hibernate.dialect.CockroachDialect; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; -import org.hibernate.orm.test.util.jdbc.PreparedStatementSpyConnectionProvider; +import org.hibernate.testing.orm.jdbc.PreparedStatementSpyConnectionProvider; import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.SkipForDialect; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/QueryApiTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/QueryApiTests.java new file mode 100644 index 0000000000..1348e0496d --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/QueryApiTests.java @@ -0,0 +1,90 @@ +/* + * 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; + +import java.time.LocalDate; + +import org.hibernate.query.IllegalQueryOperationException; + +import org.hibernate.testing.orm.domain.StandardDomainModel; +import org.hibernate.testing.orm.domain.contacts.Contact; +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.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.fail; + +/** + * @author Steve Ebersole + */ +@DomainModel( standardModels = StandardDomainModel.CONTACTS ) +@SessionFactory +public class QueryApiTests { + + @Test + public void testInvalidExecuteUpdateCall(SessionFactoryScope scope) { + try { + scope.inTransaction( (session) -> { + session.createQuery( "select c from Contact c" ).executeUpdate(); + } ); + fail( "Expecting failure" ); + } + catch (IllegalStateException ise) { + assertThat( ise.getCause() ).isNotNull(); + assertThat( ise.getCause() ).isInstanceOf( IllegalQueryOperationException.class ); + } + } + + @Test + public void testInvalidSelectQueryCall(SessionFactoryScope scope) { + try { + scope.inTransaction( (session) -> { + session.createQuery( "delete Contact" ).list(); + } ); + fail( "Expecting failure" ); + } + catch (IllegalStateException ise) { + assertThat( ise.getCause() ).isNotNull(); + assertThat( ise.getCause() ).isInstanceOf( IllegalQueryOperationException.class ); + } + + try { + scope.inTransaction( (session) -> { + session.createQuery( "delete Contact" ).uniqueResult(); + } ); + fail( "Expecting failure" ); + } + catch (IllegalStateException ise) { + assertThat( ise.getCause() ).isNotNull(); + assertThat( ise.getCause() ).isInstanceOf( IllegalQueryOperationException.class ); + } + } + + @BeforeEach + public void prepareTestData(SessionFactoryScope scope) { + scope.inTransaction( (session) -> { + final Contact contact = new Contact( + 1, + new Contact.Name( "John", "Jingleheimer-Schmidt"), + Contact.Gender.MALE, + LocalDate.EPOCH + ); + session.persist( contact ); + } ); + } + + @AfterEach + public void dropTestData(SessionFactoryScope scope) { + scope.inTransaction( (session) -> { + session.createQuery( "delete Contact" ).executeUpdate(); + } ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/QueryHintTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/QueryHintTest.java new file mode 100644 index 0000000000..7bcf4a3f34 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/QueryHintTest.java @@ -0,0 +1,91 @@ +/* + * 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; + +import java.time.LocalDate; +import java.util.Collections; + +import org.hibernate.graph.GraphParser; +import org.hibernate.jpa.QueryHints; +import org.hibernate.query.IllegalQueryOperationException; + +import org.hibernate.testing.orm.assertj.HibernateInitializedCondition; +import org.hibernate.testing.orm.domain.StandardDomainModel; +import org.hibernate.testing.orm.domain.contacts.Contact; +import org.hibernate.testing.orm.domain.contacts.PhoneNumber; +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.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.fail; + +/** + * @author Steve Ebersole + */ +@DomainModel( standardModels = StandardDomainModel.CONTACTS ) +@SessionFactory +public class QueryHintTest { + @Test + public void testFetchGraphHint(SessionFactoryScope scope) { + final Contact queried = scope.fromTransaction( (session) -> { + return session.createQuery( "from Contact", Contact.class ) + .setHint( QueryHints.HINT_FETCHGRAPH, GraphParser.parse( Contact.class, "phoneNumbers", session ) ) + .uniqueResult(); + } ); + + assertThat( queried ).is( HibernateInitializedCondition.IS_INITIALIZED ); + assertThat( queried.getPhoneNumbers() ).is( HibernateInitializedCondition.IS_INITIALIZED ); + } + + @Test + public void testLoadGraphHint(SessionFactoryScope scope) { + final Contact queried = scope.fromTransaction( (session) -> { + return session.createQuery( "from Contact", Contact.class ) + .setHint( QueryHints.HINT_LOADGRAPH, GraphParser.parse( Contact.class, "phoneNumbers", session ) ) + .uniqueResult(); + } ); + + assertThat( queried ).is( HibernateInitializedCondition.IS_INITIALIZED ); + assertThat( queried.getPhoneNumbers() ).is( HibernateInitializedCondition.IS_INITIALIZED ); + } + + @Test + public void testQueryTimeoutHint(SessionFactoryScope scope) { + // see `org.hibernate.test.querytimeout.QueryTimeOutTest` + } + + @BeforeEach + public void prepareTestData(SessionFactoryScope scope) { + scope.inTransaction( (session) -> { + final Contact contact = new Contact( + 1, + new Contact.Name( "John", "Jingleheimer-Schmidt"), + Contact.Gender.MALE, + LocalDate.EPOCH + ); + contact.setPhoneNumbers( + Collections.singletonList( + new PhoneNumber( 123, 456, 7890, PhoneNumber.Classification.OTHER ) + ) + ); + session.persist( contact ); + } ); + } + + @AfterEach + public void dropTestData(SessionFactoryScope scope) { + scope.inTransaction( (session) -> { + session.createQuery( "from Contact" ).list().forEach( session::delete ); + } ); + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/querytimeout/QueryTimeOutTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/QueryTimeOutTest.java similarity index 94% rename from hibernate-core/src/test/java/org/hibernate/test/querytimeout/QueryTimeOutTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/query/QueryTimeOutTest.java index 898b7b8a50..5b9584ac1f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/querytimeout/QueryTimeOutTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/QueryTimeOutTest.java @@ -1,10 +1,10 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . + * 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.test.querytimeout; +package org.hibernate.orm.test.query; import java.sql.SQLException; import java.util.Map; @@ -23,7 +23,7 @@ import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; -import org.hibernate.orm.test.util.jdbc.PreparedStatementSpyConnectionProvider; +import org.hibernate.testing.orm.jdbc.PreparedStatementSpyConnectionProvider; import org.junit.Before; import org.junit.Test; @@ -39,7 +39,7 @@ import static org.mockito.Mockito.verify; public class QueryTimeOutTest extends BaseNonConfigCoreFunctionalTestCase { private static final PreparedStatementSpyConnectionProvider CONNECTION_PROVIDER = new PreparedStatementSpyConnectionProvider( true, false ); - private static final String QUERY = "update AnEntity set name='abc'"; + private static final String QUERY = "update AnEntity set name = 'abc'"; @Override protected Class[] getAnnotatedClasses() { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/resource/transaction/jdbc/autocommit/AbstractSkipAutoCommitTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/resource/transaction/jdbc/autocommit/AbstractSkipAutoCommitTest.java index 7e2a858a84..ebf79bdb17 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/resource/transaction/jdbc/autocommit/AbstractSkipAutoCommitTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/resource/transaction/jdbc/autocommit/AbstractSkipAutoCommitTest.java @@ -19,7 +19,7 @@ import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; -import org.hibernate.orm.test.util.jdbc.PreparedStatementSpyConnectionProvider; +import org.hibernate.testing.orm.jdbc.PreparedStatementSpyConnectionProvider; import org.junit.Test; import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/uniqueconstraint/MySQLDropConstraintThrowsExceptionTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/uniqueconstraint/MySQLDropConstraintThrowsExceptionTest.java index eeaef3ab78..bc91c3fec3 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/uniqueconstraint/MySQLDropConstraintThrowsExceptionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/uniqueconstraint/MySQLDropConstraintThrowsExceptionTest.java @@ -30,7 +30,7 @@ import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseUnitTestCase; -import org.hibernate.orm.test.util.jdbc.PreparedStatementSpyConnectionProvider; +import org.hibernate.testing.orm.jdbc.PreparedStatementSpyConnectionProvider; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/hibernate-core/src/test/java/org/hibernate/test/queryhint/QueryHintTest.java b/hibernate-core/src/test/java/org/hibernate/test/queryhint/OracleQueryHintTest.java similarity index 98% rename from hibernate-core/src/test/java/org/hibernate/test/queryhint/QueryHintTest.java rename to hibernate-core/src/test/java/org/hibernate/test/queryhint/OracleQueryHintTest.java index 5b8aa56b97..103a05339d 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/queryhint/QueryHintTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/queryhint/OracleQueryHintTest.java @@ -37,7 +37,7 @@ import static org.junit.Assert.assertTrue; * @author Brett Meyer */ @RequiresDialect( Oracle8iDialect.class ) -public class QueryHintTest extends BaseNonConfigCoreFunctionalTestCase { +public class OracleQueryHintTest extends BaseNonConfigCoreFunctionalTestCase { private SQLStatementInterceptor sqlStatementInterceptor; diff --git a/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimeCustomTimeZoneTest.java b/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimeCustomTimeZoneTest.java index afff831ec3..d6e3f84bf5 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimeCustomTimeZoneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimeCustomTimeZoneTest.java @@ -28,7 +28,7 @@ import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; -import org.hibernate.orm.test.util.jdbc.PreparedStatementSpyConnectionProvider; +import org.hibernate.testing.orm.jdbc.PreparedStatementSpyConnectionProvider; import org.junit.Test; import org.mockito.ArgumentCaptor; diff --git a/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimeDefaultTimeZoneTest.java b/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimeDefaultTimeZoneTest.java index 1c764b66b6..3362b00ce5 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimeDefaultTimeZoneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimeDefaultTimeZoneTest.java @@ -20,7 +20,7 @@ import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; -import org.hibernate.orm.test.util.jdbc.PreparedStatementSpyConnectionProvider; +import org.hibernate.testing.orm.jdbc.PreparedStatementSpyConnectionProvider; import org.junit.Test; import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; diff --git a/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampCustomSessionLevelTimeZoneTest.java b/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampCustomSessionLevelTimeZoneTest.java index 8a1d77fc0d..814ecb5b62 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampCustomSessionLevelTimeZoneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampCustomSessionLevelTimeZoneTest.java @@ -25,7 +25,7 @@ import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; -import org.hibernate.orm.test.util.jdbc.PreparedStatementSpyConnectionProvider; +import org.hibernate.testing.orm.jdbc.PreparedStatementSpyConnectionProvider; import org.junit.Test; import org.mockito.ArgumentCaptor; diff --git a/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampCustomTimeZoneTest.java b/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampCustomTimeZoneTest.java index 3fdb7cc0d3..40f9582f4c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampCustomTimeZoneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampCustomTimeZoneTest.java @@ -25,7 +25,7 @@ import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; -import org.hibernate.orm.test.util.jdbc.PreparedStatementSpyConnectionProvider; +import org.hibernate.testing.orm.jdbc.PreparedStatementSpyConnectionProvider; import org.junit.Test; import org.mockito.ArgumentCaptor; diff --git a/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampDefaultTimeZoneTest.java b/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampDefaultTimeZoneTest.java index 80f78e2915..a1026cb756 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampDefaultTimeZoneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampDefaultTimeZoneTest.java @@ -19,7 +19,7 @@ import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; -import org.hibernate.orm.test.util.jdbc.PreparedStatementSpyConnectionProvider; +import org.hibernate.testing.orm.jdbc.PreparedStatementSpyConnectionProvider; import org.junit.Test; import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; diff --git a/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampUTCTimeZoneTest.java b/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampUTCTimeZoneTest.java index 4ceac4fbdf..d2939730e3 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampUTCTimeZoneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampUTCTimeZoneTest.java @@ -14,7 +14,7 @@ import org.hibernate.dialect.PostgreSQL82Dialect; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.testing.RequiresDialect; -import org.hibernate.orm.test.util.jdbc.TimeZoneConnectionProvider; +import org.hibernate.testing.orm.jdbc.TimeZoneConnectionProvider; /** * @author Vlad Mihalcea diff --git a/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampWithDefaultUTCTimeZoneTest.java b/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampWithDefaultUTCTimeZoneTest.java index a01b4dcc6d..be03410a50 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampWithDefaultUTCTimeZoneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampWithDefaultUTCTimeZoneTest.java @@ -13,7 +13,7 @@ import org.hibernate.dialect.PostgreSQL82Dialect; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.testing.RequiresDialect; -import org.hibernate.orm.test.util.jdbc.TimeZoneConnectionProvider; +import org.hibernate.testing.orm.jdbc.TimeZoneConnectionProvider; /** * @author Vlad Mihalcea diff --git a/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampWithoutUTCTimeZoneTest.java b/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampWithoutUTCTimeZoneTest.java index d02c768fd3..f85b6aaab3 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampWithoutUTCTimeZoneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/timestamp/JdbcTimestampWithoutUTCTimeZoneTest.java @@ -23,7 +23,7 @@ import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; -import org.hibernate.orm.test.util.jdbc.TimeZoneConnectionProvider; +import org.hibernate.testing.orm.jdbc.TimeZoneConnectionProvider; import org.junit.Test; import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; diff --git a/hibernate-testing/hibernate-testing.gradle b/hibernate-testing/hibernate-testing.gradle index 311d4bec0d..86a1125604 100644 --- a/hibernate-testing/hibernate-testing.gradle +++ b/hibernate-testing/hibernate-testing.gradle @@ -20,6 +20,9 @@ dependencies { api libraries.junit5_api api libraries.junit5_params api 'org.hamcrest:hamcrest-all:1.3' + api libraries.assertj + api libraries.mockito + api libraries.mockito_inline api libraries.byteman api libraries.byteman_install api libraries.byteman_bmunit diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/jdbc/JdbcMocks.java b/hibernate-testing/src/main/java/org/hibernate/testing/jdbc/JdbcMocks.java index 582e246a06..276e5c4d84 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/jdbc/JdbcMocks.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/jdbc/JdbcMocks.java @@ -336,6 +336,14 @@ public class JdbcMocks { return false; } + public static class PreparedStatementHandler implements InvocationHandler { + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + return null; + } + } + public static class EmptyResultSetHandler implements InvocationHandler { public static ResultSet makeProxy() { final EmptyResultSetHandler handler = new EmptyResultSetHandler(); diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/orm/assertj/HibernateInitializedCondition.java b/hibernate-testing/src/main/java/org/hibernate/testing/orm/assertj/HibernateInitializedCondition.java new file mode 100644 index 0000000000..a3d8364835 --- /dev/null +++ b/hibernate-testing/src/main/java/org/hibernate/testing/orm/assertj/HibernateInitializedCondition.java @@ -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.testing.orm.assertj; + +import org.hibernate.Hibernate; + +import org.assertj.core.api.Condition; + +/** + * @author Steve Ebersole + */ +public class HibernateInitializedCondition extends Condition { + public static final HibernateInitializedCondition IS_INITIALIZED = new HibernateInitializedCondition( true ); + public static final HibernateInitializedCondition IS_NOT_INITIALIZED = new HibernateInitializedCondition( false ); + + private final boolean positive; + + public HibernateInitializedCondition(boolean positive) { + super( "Hibernate#isInitialized check" ); + this.positive = positive; + } + + @Override + public boolean matches(Object value) { + return positive == Hibernate.isInitialized( value ); + } +} diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/orm/domain/contacts/Contact.java b/hibernate-testing/src/main/java/org/hibernate/testing/orm/domain/contacts/Contact.java index 60c4a81438..4aa3b7e3cf 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/orm/domain/contacts/Contact.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/orm/domain/contacts/Contact.java @@ -33,9 +33,6 @@ public class Contact { private LocalDate birthDay; - // NOTE : because of the @OrderColumn `addresses` is a List, while `phoneNumbers` is a BAG - // which is a List with no persisted order - @OrderColumn private List
addresses; private List phoneNumbers; @@ -86,6 +83,9 @@ public class Contact { @ElementCollection @CollectionTable( name = "contact_addresses" ) + // NOTE : because of the @OrderColumn `addresses` is a List, while `phoneNumbers` is + // a BAG which is a List with no persisted order + @OrderColumn public List
getAddresses() { return addresses; } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/orm/domain/contacts/PhoneNumber.java b/hibernate-testing/src/main/java/org/hibernate/testing/orm/domain/contacts/PhoneNumber.java index 7c81368319..f0084ded5f 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/orm/domain/contacts/PhoneNumber.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/orm/domain/contacts/PhoneNumber.java @@ -19,6 +19,16 @@ public class PhoneNumber { private Classification classification; + public PhoneNumber() { + } + + public PhoneNumber(int areaCode, int prefix, int lineNumber, Classification classification) { + this.areaCode = areaCode; + this.prefix = prefix; + this.lineNumber = lineNumber; + this.classification = classification; + } + public int getAreaCode() { return areaCode; } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/util/jdbc/PreparedStatementSpyConnectionProvider.java b/hibernate-testing/src/main/java/org/hibernate/testing/orm/jdbc/PreparedStatementSpyConnectionProvider.java similarity index 98% rename from hibernate-core/src/test/java/org/hibernate/orm/test/util/jdbc/PreparedStatementSpyConnectionProvider.java rename to hibernate-testing/src/main/java/org/hibernate/testing/orm/jdbc/PreparedStatementSpyConnectionProvider.java index 40ab9ccf77..da2d3bd191 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/util/jdbc/PreparedStatementSpyConnectionProvider.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/orm/jdbc/PreparedStatementSpyConnectionProvider.java @@ -1,10 +1,10 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . + * 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.util.jdbc; +package org.hibernate.testing.orm.jdbc; import java.sql.Connection; import java.sql.PreparedStatement; diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/orm/jdbc/PreparedStatementSpyConnectionProviderSettingProvider.java b/hibernate-testing/src/main/java/org/hibernate/testing/orm/jdbc/PreparedStatementSpyConnectionProviderSettingProvider.java new file mode 100644 index 0000000000..565f2f6534 --- /dev/null +++ b/hibernate-testing/src/main/java/org/hibernate/testing/orm/jdbc/PreparedStatementSpyConnectionProviderSettingProvider.java @@ -0,0 +1,19 @@ +/* + * 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.testing.orm.jdbc; + +import org.hibernate.testing.orm.junit.SettingProvider; + +/** + * @author Steve Ebersole + */ +public class PreparedStatementSpyConnectionProviderSettingProvider implements SettingProvider.Provider { + @Override + public PreparedStatementSpyConnectionProvider getSetting() { + return new PreparedStatementSpyConnectionProvider( true, false ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/util/jdbc/TimeZoneConnectionProvider.java b/hibernate-testing/src/main/java/org/hibernate/testing/orm/jdbc/TimeZoneConnectionProvider.java similarity index 88% rename from hibernate-core/src/test/java/org/hibernate/orm/test/util/jdbc/TimeZoneConnectionProvider.java rename to hibernate-testing/src/main/java/org/hibernate/testing/orm/jdbc/TimeZoneConnectionProvider.java index 3febc6e88d..32ef2e6739 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/util/jdbc/TimeZoneConnectionProvider.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/orm/jdbc/TimeZoneConnectionProvider.java @@ -1,10 +1,10 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . + * 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.util.jdbc; +package org.hibernate.testing.orm.jdbc; import java.util.TimeZone; diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/ServiceRegistry.java b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/ServiceRegistry.java index 0a647797ec..45785a7159 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/ServiceRegistry.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/ServiceRegistry.java @@ -75,6 +75,8 @@ public @interface ServiceRegistry { Setting[] settings() default {}; + SettingProvider[] settingProviders() default {}; + @interface Service { Class role(); Class impl(); diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/ServiceRegistryExtension.java b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/ServiceRegistryExtension.java index bb46d38a58..334ff0a5ab 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/ServiceRegistryExtension.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/ServiceRegistryExtension.java @@ -182,6 +182,12 @@ public class ServiceRegistryExtension ssrb.applySetting( setting.name(), setting.value() ); } + for ( SettingProvider providerAnn : serviceRegistryAnn.settingProviders() ) { + final Class> providerImpl = providerAnn.provider(); + final SettingProvider.Provider provider = providerImpl.getConstructor().newInstance(); + ssrb.applySetting( providerAnn.settingName(), provider.getSetting() ); + } + for ( Class contributorClass : serviceRegistryAnn.serviceContributors() ) { final ServiceContributor serviceContributor = contributorClass.newInstance(); serviceContributor.contribute( ssrb ); diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/SettingProvider.java b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/SettingProvider.java new file mode 100644 index 0000000000..51c2befaef --- /dev/null +++ b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/SettingProvider.java @@ -0,0 +1,19 @@ +/* + * 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.testing.orm.junit; + +/** + * @author Steve Ebersole + */ +public @interface SettingProvider { + interface Provider { + S getSetting(); + } + + String settingName(); + Class> provider(); +}