HHH-15942 introduce QueryFlushMode for specifying whether a query flushes or not

- replaces FlushModeType in the annotation package
- much less confusing when applied to a Query
  * what do MANUAL and COMMIT mean for a Query?
  * how is AUTO useful for a Query?

- also make Query.getHibernateFlushMode() obey its
  documented semantics by returning the session
  flush mode instead of null when unset
This commit is contained in:
Gavin 2022-12-28 14:54:37 +01:00 committed by Gavin King
parent 5f8bf125fc
commit 52e185b194
30 changed files with 641 additions and 94 deletions

View File

@ -18,9 +18,16 @@ import jakarta.persistence.FlushModeType;
* <p> * <p>
* For example, {@link #COMMIT} specifies that the session flushes * For example, {@link #COMMIT} specifies that the session flushes
* automatically when the transaction is about to commit. * automatically when the transaction is about to commit.
* <p>
* This enumeration represents options which may be
* {@linkplain Session#setHibernateFlushMode set at the session
* level}, and competes with the JPA-defined enumeration
* {@link jakarta.persistence.FlushModeType}. Alternatively, a
* {@link org.hibernate.query.QueryFlushMode QueryFlushMode} may
* be specified for a given query.
* *
* @see Session#setHibernateFlushMode * @see Session#setHibernateFlushMode
* @see org.hibernate.query.CommonQueryContract#setHibernateFlushMode * @see org.hibernate.query.QueryFlushMode
* *
* @author Gavin King * @author Gavin King
*/ */

View File

@ -199,7 +199,7 @@ public interface Session extends SharedSessionContract, EntityManager {
void flush(); void flush();
/** /**
* Set the current {@link FlushModeType JPA flush mode} for this session. * Set the current {@linkplain FlushModeType JPA flush mode} for this session.
* <p> * <p>
* <em>Flushing</em> is the process of synchronizing the underlying persistent * <em>Flushing</em> is the process of synchronizing the underlying persistent
* store with persistable state held in memory. The current flush mode determines * store with persistable state held in memory. The current flush mode determines

View File

@ -6,6 +6,8 @@
*/ */
package org.hibernate.annotations; package org.hibernate.annotations;
import org.hibernate.query.QueryFlushMode;
/** /**
* Enumeration extending the {@linkplain jakarta.persistence.FlushModeType JPA flush modes} * Enumeration extending the {@linkplain jakarta.persistence.FlushModeType JPA flush modes}
* with flush modes specific to Hibernate, and a "null" mode, {@link #PERSISTENCE_CONTEXT}, * with flush modes specific to Hibernate, and a "null" mode, {@link #PERSISTENCE_CONTEXT},
@ -14,9 +16,12 @@ package org.hibernate.annotations;
* *
* @author Carlos Gonzalez-Cadenas * @author Carlos Gonzalez-Cadenas
* *
* @see NamedQuery * @see NamedQuery#flushMode
* @see NamedNativeQuery * @see NamedNativeQuery#flushMode
*
* @deprecated use {@link QueryFlushMode}
*/ */
@Deprecated(since="7")
public enum FlushModeType { public enum FlushModeType {
/** /**
* Corresponds to {@link org.hibernate.FlushMode#ALWAYS}. * Corresponds to {@link org.hibernate.FlushMode#ALWAYS}.

View File

@ -13,6 +13,7 @@ import java.lang.annotation.Target;
import jakarta.persistence.CacheRetrieveMode; import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode; import jakarta.persistence.CacheStoreMode;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.query.QueryFlushMode;
import static java.lang.annotation.ElementType.PACKAGE; import static java.lang.annotation.ElementType.PACKAGE;
import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.TYPE;
@ -63,12 +64,25 @@ public @interface NamedNativeQuery {
*/ */
String resultSetMapping() default ""; String resultSetMapping() default "";
/**
* Determines whether the session should be flushed before
* executing the query.
*
* @see org.hibernate.query.CommonQueryContract#setQueryFlushMode(QueryFlushMode)
*
* @since 7.0
*/
QueryFlushMode flush() default QueryFlushMode.DEFAULT;
/** /**
* The flush mode for the query. * The flush mode for the query.
* *
* @see org.hibernate.query.CommonQueryContract#setFlushMode(jakarta.persistence.FlushModeType) * @see org.hibernate.query.CommonQueryContract#setFlushMode(jakarta.persistence.FlushModeType)
* @see org.hibernate.jpa.HibernateHints#HINT_FLUSH_MODE * @see org.hibernate.jpa.HibernateHints#HINT_FLUSH_MODE
*
* @deprecated use {@link #flush()}
*/ */
@Deprecated(since = "7")
FlushModeType flushMode() default FlushModeType.PERSISTENCE_CONTEXT; FlushModeType flushMode() default FlushModeType.PERSISTENCE_CONTEXT;
/** /**

View File

@ -15,6 +15,7 @@ import jakarta.persistence.CacheStoreMode;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.query.QueryFlushMode;
import static java.lang.annotation.ElementType.PACKAGE; import static java.lang.annotation.ElementType.PACKAGE;
import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.TYPE;
@ -58,12 +59,25 @@ public @interface NamedQuery {
*/ */
Class<?> resultClass() default void.class; Class<?> resultClass() default void.class;
/**
* Determines whether the session should be flushed before
* executing the query.
*
* @see org.hibernate.query.CommonQueryContract#setQueryFlushMode(QueryFlushMode)
*
* @since 7.0
*/
QueryFlushMode flush() default QueryFlushMode.DEFAULT;
/** /**
* The flush mode for this query. * The flush mode for this query.
* *
* @see org.hibernate.query.CommonQueryContract#setFlushMode(jakarta.persistence.FlushModeType) * @see org.hibernate.query.CommonQueryContract#setFlushMode(jakarta.persistence.FlushModeType)
* @see org.hibernate.jpa.HibernateHints#HINT_FLUSH_MODE * @see org.hibernate.jpa.HibernateHints#HINT_FLUSH_MODE
*
* @deprecated use {@link #flush()}
*/ */
@Deprecated(since = "7")
FlushModeType flushMode() default FlushModeType.PERSISTENCE_CONTEXT; FlushModeType flushMode() default FlushModeType.PERSISTENCE_CONTEXT;
/** /**

View File

@ -16,6 +16,7 @@ import java.util.function.Supplier;
import org.hibernate.AnnotationException; import org.hibernate.AnnotationException;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
import org.hibernate.query.QueryFlushMode;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
import org.hibernate.annotations.FlushModeType; import org.hibernate.annotations.FlushModeType;
import org.hibernate.annotations.HQLSelect; import org.hibernate.annotations.HQLSelect;
@ -35,6 +36,7 @@ import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.log.DeprecationLogger; import org.hibernate.internal.log.DeprecationLogger;
import org.hibernate.jpa.HibernateHints; import org.hibernate.jpa.HibernateHints;
import org.hibernate.jpa.internal.util.FlushModeTypeHelper;
import org.hibernate.models.internal.util.StringHelper; import org.hibernate.models.internal.util.StringHelper;
import org.hibernate.models.spi.ClassDetails; import org.hibernate.models.spi.ClassDetails;
import org.hibernate.models.spi.SourceModelBuildingContext; import org.hibernate.models.spi.SourceModelBuildingContext;
@ -271,7 +273,7 @@ public abstract class QueryBinder {
.setCacheMode(getCacheMode(namedNativeQuery.cacheRetrieveMode(), namedNativeQuery.cacheStoreMode())) .setCacheMode(getCacheMode(namedNativeQuery.cacheRetrieveMode(), namedNativeQuery.cacheStoreMode()))
.setTimeout(timeout < 0 ? null : timeout) .setTimeout(timeout < 0 ? null : timeout)
.setFetchSize(fetchSize < 0 ? null : fetchSize) .setFetchSize(fetchSize < 0 ? null : fetchSize)
.setFlushMode(getFlushMode(namedNativeQuery.flushMode())) .setFlushMode(getFlushMode(namedNativeQuery.flush(), namedNativeQuery.flushMode()))
.setReadOnly(namedNativeQuery.readOnly()) .setReadOnly(namedNativeQuery.readOnly())
.setQuerySpaces(querySpaces) .setQuerySpaces(querySpaces)
.setComment(nullIfEmpty(namedNativeQuery.comment())); .setComment(nullIfEmpty(namedNativeQuery.comment()));
@ -412,7 +414,7 @@ public abstract class QueryBinder {
.setCacheMode(getCacheMode(namedQuery.cacheRetrieveMode(), namedQuery.cacheStoreMode())) .setCacheMode(getCacheMode(namedQuery.cacheRetrieveMode(), namedQuery.cacheStoreMode()))
.setTimeout(timeout < 0 ? null : timeout) .setTimeout(timeout < 0 ? null : timeout)
.setFetchSize(fetchSize < 0 ? null : fetchSize) .setFetchSize(fetchSize < 0 ? null : fetchSize)
.setFlushMode(getFlushMode(namedQuery.flushMode())) .setFlushMode(getFlushMode(namedQuery.flush(), namedQuery.flushMode()))
.setReadOnly(namedQuery.readOnly()) .setReadOnly(namedQuery.readOnly())
.setComment(nullIfEmpty(namedQuery.comment())); .setComment(nullIfEmpty(namedQuery.comment()));
} }
@ -422,6 +424,12 @@ public abstract class QueryBinder {
return cacheMode == null ? CacheMode.NORMAL : cacheMode; return cacheMode == null ? CacheMode.NORMAL : cacheMode;
} }
private static FlushMode getFlushMode(QueryFlushMode queryFlushMode, FlushModeType flushModeType) {
return queryFlushMode == QueryFlushMode.DEFAULT
? getFlushMode( flushModeType )
: FlushModeTypeHelper.getFlushMode(queryFlushMode);
}
private static FlushMode getFlushMode(FlushModeType flushModeType) { private static FlushMode getFlushMode(FlushModeType flushModeType) {
return switch ( flushModeType ) { return switch ( flushModeType ) {
case ALWAYS -> FlushMode.ALWAYS; case ALWAYS -> FlushMode.ALWAYS;

View File

@ -24,6 +24,7 @@ import org.hibernate.models.spi.SourceModelBuildingContext;
import jakarta.persistence.CacheRetrieveMode; import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode; import jakarta.persistence.CacheStoreMode;
import org.hibernate.query.QueryFlushMode;
@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) @SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" })
@jakarta.annotation.Generated("org.hibernate.orm.build.annotations.ClassGeneratorProcessor") @jakarta.annotation.Generated("org.hibernate.orm.build.annotations.ClassGeneratorProcessor")
@ -33,6 +34,7 @@ public class NamedNativeQueryAnnotation implements NamedNativeQuery {
private Class<?> resultClass; private Class<?> resultClass;
private String resultSetMapping; private String resultSetMapping;
private FlushModeType flushMode; private FlushModeType flushMode;
private QueryFlushMode flush;
boolean cacheable; boolean cacheable;
String cacheRegion; String cacheRegion;
int fetchSize; int fetchSize;
@ -51,6 +53,7 @@ public class NamedNativeQueryAnnotation implements NamedNativeQuery {
resultClass = void.class; resultClass = void.class;
resultSetMapping = ""; resultSetMapping = "";
flushMode = FlushModeType.PERSISTENCE_CONTEXT; flushMode = FlushModeType.PERSISTENCE_CONTEXT;
flush = QueryFlushMode.DEFAULT;
cacheable = false; cacheable = false;
cacheRegion = ""; cacheRegion = "";
fetchSize = -1; fetchSize = -1;
@ -72,6 +75,7 @@ public class NamedNativeQueryAnnotation implements NamedNativeQuery {
this.resultClass = annotation.resultClass(); this.resultClass = annotation.resultClass();
this.resultSetMapping = annotation.resultSetMapping(); this.resultSetMapping = annotation.resultSetMapping();
this.flushMode = annotation.flushMode(); this.flushMode = annotation.flushMode();
this.flush = annotation.flush();
this.cacheable = annotation.cacheable(); this.cacheable = annotation.cacheable();
this.cacheRegion = annotation.cacheRegion(); this.cacheRegion = annotation.cacheRegion();
this.fetchSize = annotation.fetchSize(); this.fetchSize = annotation.fetchSize();
@ -97,6 +101,7 @@ public class NamedNativeQueryAnnotation implements NamedNativeQuery {
this.resultClass = (Class<?>) attributeValues.get( "resultClass" ); this.resultClass = (Class<?>) attributeValues.get( "resultClass" );
this.resultSetMapping = (String) attributeValues.get( "resultSetMapping" ); this.resultSetMapping = (String) attributeValues.get( "resultSetMapping" );
this.flushMode = (FlushModeType) attributeValues.get( "flushMode" ); this.flushMode = (FlushModeType) attributeValues.get( "flushMode" );
this.flush = (QueryFlushMode) attributeValues.get( "flush" );
this.cacheable = (boolean) attributeValues.get( "cacheable" ); this.cacheable = (boolean) attributeValues.get( "cacheable" );
this.cacheRegion = (String) attributeValues.get( "cacheRegion" ); this.cacheRegion = (String) attributeValues.get( "cacheRegion" );
this.fetchSize = (int) attributeValues.get( "fetchSize" ); this.fetchSize = (int) attributeValues.get( "fetchSize" );
@ -152,6 +157,15 @@ public class NamedNativeQueryAnnotation implements NamedNativeQuery {
this.resultSetMapping = value; this.resultSetMapping = value;
} }
@Override
public QueryFlushMode flush() {
return flush;
}
public void flush(QueryFlushMode value) {
this.flush = value;
}
@Override @Override
public FlushModeType flushMode() { public FlushModeType flushMode() {
return flushMode; return flushMode;

View File

@ -19,6 +19,7 @@ import org.hibernate.models.spi.SourceModelBuildingContext;
import jakarta.persistence.CacheRetrieveMode; import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode; import jakarta.persistence.CacheStoreMode;
import org.hibernate.query.QueryFlushMode;
import static org.hibernate.boot.models.xml.internal.QueryProcessing.interpretFlushMode; import static org.hibernate.boot.models.xml.internal.QueryProcessing.interpretFlushMode;
@ -29,6 +30,7 @@ public class NamedQueryAnnotation implements NamedQuery {
private String query; private String query;
private Class<?> resultClass; private Class<?> resultClass;
private FlushModeType flushMode; private FlushModeType flushMode;
private QueryFlushMode flush;
boolean cacheable; boolean cacheable;
String cacheRegion; String cacheRegion;
int fetchSize; int fetchSize;
@ -44,6 +46,7 @@ public class NamedQueryAnnotation implements NamedQuery {
public NamedQueryAnnotation(SourceModelBuildingContext modelContext) { public NamedQueryAnnotation(SourceModelBuildingContext modelContext) {
resultClass = void.class; resultClass = void.class;
flushMode = FlushModeType.PERSISTENCE_CONTEXT; flushMode = FlushModeType.PERSISTENCE_CONTEXT;
flush = QueryFlushMode.DEFAULT;
cacheable = false; cacheable = false;
cacheRegion = ""; cacheRegion = "";
fetchSize = -1; fetchSize = -1;
@ -62,6 +65,7 @@ public class NamedQueryAnnotation implements NamedQuery {
this.query = annotation.query(); this.query = annotation.query();
this.resultClass = annotation.resultClass(); this.resultClass = annotation.resultClass();
this.flushMode = annotation.flushMode(); this.flushMode = annotation.flushMode();
this.flush = annotation.flush();
this.cacheable = annotation.cacheable(); this.cacheable = annotation.cacheable();
this.cacheRegion = annotation.cacheRegion(); this.cacheRegion = annotation.cacheRegion();
this.fetchSize = annotation.fetchSize(); this.fetchSize = annotation.fetchSize();
@ -84,6 +88,7 @@ public class NamedQueryAnnotation implements NamedQuery {
this.query = (String) attributeValues.get( "query" ); this.query = (String) attributeValues.get( "query" );
this.resultClass = (Class<?>) attributeValues.get( "resultClass" ); this.resultClass = (Class<?>) attributeValues.get( "resultClass" );
this.flushMode = (FlushModeType) attributeValues.get( "flushMode" ); this.flushMode = (FlushModeType) attributeValues.get( "flushMode" );
this.flush = (QueryFlushMode) attributeValues.get( "flush" );
this.cacheable = (boolean) attributeValues.get( "cacheable" ); this.cacheable = (boolean) attributeValues.get( "cacheable" );
this.cacheRegion = (String) attributeValues.get( "cacheRegion" ); this.cacheRegion = (String) attributeValues.get( "cacheRegion" );
this.fetchSize = (int) attributeValues.get( "fetchSize" ); this.fetchSize = (int) attributeValues.get( "fetchSize" );
@ -128,6 +133,15 @@ public class NamedQueryAnnotation implements NamedQuery {
this.resultClass = value; this.resultClass = value;
} }
@Override
public QueryFlushMode flush() {
return flush;
}
public void flush(QueryFlushMode value) {
this.flush = value;
}
@Override @Override
public FlushModeType flushMode() { public FlushModeType flushMode() {
return flushMode; return flushMode;

View File

@ -10,8 +10,8 @@ package org.hibernate.jpa.internal.util;
import java.util.Locale; import java.util.Locale;
import jakarta.persistence.FlushModeType; import jakarta.persistence.FlushModeType;
import org.hibernate.AssertionFailure;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
import org.hibernate.query.QueryFlushMode;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -28,35 +28,55 @@ public class FlushModeTypeHelper {
} }
public static FlushModeType getFlushModeType(FlushMode flushMode) { public static FlushModeType getFlushModeType(FlushMode flushMode) {
if ( flushMode == FlushMode.ALWAYS ) { if ( flushMode == null ) {
log.debug( "Interpreting Hibernate FlushMode#ALWAYS to JPA FlushModeType#AUTO; may cause problems if relying on FlushMode#ALWAYS-specific behavior" ); return null;
return FlushModeType.AUTO;
} }
else if ( flushMode == FlushMode.MANUAL ) { return switch (flushMode) {
log.debug( "Interpreting Hibernate FlushMode#MANUAL to JPA FlushModeType#COMMIT; may cause problems if relying on FlushMode#MANUAL-specific behavior" ); case ALWAYS -> {
return FlushModeType.COMMIT; log.debug("Interpreting Hibernate FlushMode.ALWAYS as JPA FlushModeType.AUTO (may cause problems if relying on FlushMode.ALWAYS-specific behavior)");
} yield FlushModeType.AUTO;
else if ( flushMode == FlushMode.COMMIT ) { }
return FlushModeType.COMMIT; case MANUAL -> {
} log.debug("Interpreting Hibernate FlushMode.MANUAL as JPA FlushModeType.COMMIT (may cause problems if relying on FlushMode.MANUAL-specific behavior)");
else if ( flushMode == FlushMode.AUTO ) { yield FlushModeType.COMMIT;
return FlushModeType.AUTO; }
} case COMMIT -> FlushModeType.COMMIT;
else { case AUTO -> FlushModeType.AUTO;
throw new AssertionFailure( "unhandled FlushMode " + flushMode ); };
}
public static QueryFlushMode getForcedFlushMode(FlushMode flushMode) {
if ( flushMode == null ) {
return QueryFlushMode.DEFAULT;
} }
return switch (flushMode) {
case ALWAYS -> QueryFlushMode.FLUSH;
case COMMIT, MANUAL -> QueryFlushMode.NO_FLUSH;
case AUTO ->
// this is not precisely correctly correct, but good enough
QueryFlushMode.DEFAULT;
};
} }
public static FlushMode getFlushMode(FlushModeType flushModeType) { public static FlushMode getFlushMode(FlushModeType flushModeType) {
if ( flushModeType == FlushModeType.AUTO ) { if ( flushModeType == null ) {
return FlushMode.AUTO; return null;
} }
else if ( flushModeType == FlushModeType.COMMIT ) { return switch (flushModeType) {
return FlushMode.COMMIT; case AUTO -> FlushMode.AUTO;
} case COMMIT -> FlushMode.COMMIT;
else { };
throw new AssertionFailure( "unhandled FlushModeType " + flushModeType ); }
public static FlushMode getFlushMode(QueryFlushMode queryFlushMode) {
if ( queryFlushMode == null ) {
return null;
} }
return switch (queryFlushMode) {
case FLUSH -> FlushMode.ALWAYS;
case NO_FLUSH -> FlushMode.MANUAL;
default -> null;
};
} }
public static FlushMode interpretFlushMode(Object value) { public static FlushMode interpretFlushMode(Object value) {

View File

@ -281,7 +281,7 @@ public interface ProcedureCall
@Override @Override
ProcedureCall setParameter(int position, Date value, TemporalType temporalType); ProcedureCall setParameter(int position, Date value, TemporalType temporalType);
@Override @Override @Deprecated(since = "7")
ProcedureCall setFlushMode(FlushModeType flushMode); ProcedureCall setFlushMode(FlushModeType flushMode);
@Override @Override

View File

@ -809,7 +809,7 @@ public class ProcedureCallImpl<R>
isCacheable(), isCacheable(),
getCacheRegion(), getCacheRegion(),
getCacheMode(), getCacheMode(),
getHibernateFlushMode(), getQueryOptions().getFlushMode(),
isReadOnly(), isReadOnly(),
getTimeout(), getTimeout(),
getFetchSize(), getFetchSize(),

View File

@ -51,48 +51,86 @@ import jakarta.persistence.TemporalType;
*/ */
public interface CommonQueryContract { public interface CommonQueryContract {
/**
* The {@link QueryFlushMode} in effect for this query.
* <p>
* By default, this is {@link QueryFlushMode#DEFAULT}, and the
* {@link FlushMode} of the owning {@link Session} determines whether
* it is flushed.
*
* @see Session#getHibernateFlushMode()
*
* @since 7.0
*/
QueryFlushMode getQueryFlushMode();
/**
* Set the {@link QueryFlushMode} to use for this query.
*
* @see Session#getHibernateFlushMode()
*
* @since 7.0
*/
CommonQueryContract setQueryFlushMode(QueryFlushMode queryFlushMode);
/** /**
* The JPA {@link FlushModeType} in effect for this query. By default, the * The JPA {@link FlushModeType} in effect for this query. By default, the
* query inherits the {@link FlushMode} of the {@link Session} from which * query inherits the {@link FlushMode} of the {@link Session} from which
* it originates. * it originates.
* *
* @see #getHibernateFlushMode * @see #getQueryFlushMode()
* @see Session#getHibernateFlushMode * @see #getHibernateFlushMode()
* @see Session#getHibernateFlushMode()
*
* @deprecated use {@link #getQueryFlushMode()}
*/ */
@Deprecated(since = "7")
FlushModeType getFlushMode(); FlushModeType getFlushMode();
/** /**
* Set the {@link FlushMode} in to use for this query. * Set the {@link FlushMode} to use for this query.
* * <p>
* @implNote Setting to {@code null} ultimately indicates to use the * Setting this to {@code null} ultimately indicates to use the
* FlushMode of the Session. Use {@link #setHibernateFlushMode} passing * {@link FlushMode} of the session. Use {@link #setHibernateFlushMode}
* {@link FlushMode#MANUAL} instead to indicate that no automatic flushing * passing {@link FlushMode#MANUAL} instead to indicate that no automatic
* should occur * flushing should occur.
* *
* @see #getQueryFlushMode()
* @see #getHibernateFlushMode() * @see #getHibernateFlushMode()
* @see Session#getHibernateFlushMode() * @see Session#getHibernateFlushMode()
*
* @deprecated use {@link #setQueryFlushMode(QueryFlushMode)}
*/ */
@Deprecated(since = "7")
CommonQueryContract setFlushMode(FlushModeType flushMode); CommonQueryContract setFlushMode(FlushModeType flushMode);
/** /**
* The {@link FlushMode} in effect for this query. By default, the query * The {@link FlushMode} in effect for this query. By default, the query
* inherits the {@code FlushMode} of the {@link Session} from which it * inherits the {@code FlushMode} of the {@link Session} from which it
* originates. * originates.
* *
* @see Session#getHibernateFlushMode * @see #getQueryFlushMode()
* @see Session#getHibernateFlushMode()
*
* @deprecated use {@link #getQueryFlushMode()}
*/ */
@Deprecated(since = "7")
FlushMode getHibernateFlushMode(); FlushMode getHibernateFlushMode();
/** /**
* Set the current {@link FlushMode} in effect for this query. * Set the current {@link FlushMode} in effect for this query.
* *
* @implNote Setting to {@code null} ultimately indicates to use the * @implNote Setting to {@code null} ultimately indicates to use the
* {@link FlushMode} of the Session. Use {@link FlushMode#MANUAL} * {@link FlushMode} of the session. Use {@link FlushMode#MANUAL}
* instead to indicate that no automatic flushing should occur. * instead to indicate that no automatic flushing should occur.
* *
* @see #getQueryFlushMode()
* @see #getHibernateFlushMode() * @see #getHibernateFlushMode()
* @see Session#getHibernateFlushMode() * @see Session#getHibernateFlushMode()
*
* @deprecated use {@link #setQueryFlushMode(QueryFlushMode)}
*/ */
@Deprecated(since = "7")
CommonQueryContract setHibernateFlushMode(FlushMode flushMode); CommonQueryContract setHibernateFlushMode(FlushMode flushMode);
/** /**

View File

@ -14,7 +14,6 @@ import java.util.Map;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
import org.hibernate.Incubating; import org.hibernate.Incubating;
import org.hibernate.Session;
import jakarta.persistence.FlushModeType; import jakarta.persistence.FlushModeType;
import jakarta.persistence.Parameter; import jakarta.persistence.Parameter;
@ -81,10 +80,10 @@ public interface MutationQuery extends CommonQueryContract {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Covariant returns // Covariant returns
@Override @Override @Deprecated(since = "7")
MutationQuery setFlushMode(FlushModeType flushMode); MutationQuery setFlushMode(FlushModeType flushMode);
@Override @Override @Deprecated(since = "7")
MutationQuery setHibernateFlushMode(FlushMode flushMode); MutationQuery setHibernateFlushMode(FlushMode flushMode);
@Override @Override
@ -209,4 +208,7 @@ public interface MutationQuery extends CommonQueryContract {
@Override @Override
MutationQuery setProperties(@SuppressWarnings("rawtypes") Map bean); MutationQuery setProperties(@SuppressWarnings("rawtypes") Map bean);
@Override
MutationQuery setQueryFlushMode(QueryFlushMode queryFlushMode);
} }

View File

@ -554,10 +554,13 @@ public interface NativeQuery<T> extends Query<T>, SynchronizeableQuery {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// covariant overrides - Query // covariant overrides - Query
@Override @Override @Deprecated(since = "7")
NativeQuery<T> setHibernateFlushMode(FlushMode flushMode); NativeQuery<T> setHibernateFlushMode(FlushMode flushMode);
@Override @Override
NativeQuery<T> setQueryFlushMode(QueryFlushMode queryFlushMode);
@Override @Deprecated(since = "7")
NativeQuery<T> setFlushMode(FlushModeType flushMode); NativeQuery<T> setFlushMode(FlushModeType flushMode);
@Override @Override

View File

@ -851,9 +851,12 @@ public interface Query<R> extends SelectionQuery<R>, MutationQuery, TypedQuery<R
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// covariant overrides - CommonQueryContract // covariant overrides - CommonQueryContract
@Override @Override @Deprecated(since = "7")
Query<R> setHibernateFlushMode(FlushMode flushMode); Query<R> setHibernateFlushMode(FlushMode flushMode);
@Override
Query<R> setQueryFlushMode(QueryFlushMode queryFlushMode);
@Override @Override
Query<R> setCacheable(boolean cacheable); Query<R> setCacheable(boolean cacheable);
@ -914,7 +917,7 @@ public interface Query<R> extends SelectionQuery<R>, MutationQuery, TypedQuery<R
@Override @Override
Query<R> disableFetchProfile(String profileName); Query<R> disableFetchProfile(String profileName);
@Override @Override @Deprecated(since = "7")
Query<R> setFlushMode(FlushModeType flushMode); Query<R> setFlushMode(FlushModeType flushMode);
@Override @Override

View File

@ -0,0 +1,42 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.query;
/**
* Enumerates the possible flush modes for execution of a
* {@link org.hibernate.query.Query}. An explicitly-specified
* {@linkplain Query#setQueryFlushMode(QueryFlushMode)
* query-level flush mode} overrides the current
* {@linkplain org.hibernate.Session#getHibernateFlushMode()
* flush mode of the session}.
*
* @since 7.0
*
* @see CommonQueryContract#setQueryFlushMode(QueryFlushMode)
* @see org.hibernate.annotations.NamedQuery#flush
* @see org.hibernate.annotations.NamedNativeQuery#flush
*
* @author Gavin King
*/
public enum QueryFlushMode {
/**
* Flush before executing the query.
*/
FLUSH,
/**
* Do not flush before executing the query.
*/
NO_FLUSH,
/**
* Let the owning {@link org.hibernate.Session session}
* decide whether to flush, depending on its current
* {@link org.hibernate.FlushMode}.
*
* @see org.hibernate.Session#getFlushMode()
*/
DEFAULT
}

View File

@ -295,12 +295,15 @@ public interface SelectionQuery<R> extends CommonQueryContract {
*/ */
SelectionQuery<R> disableFetchProfile(String profileName); SelectionQuery<R> disableFetchProfile(String profileName);
@Override @Override @Deprecated(since = "7")
SelectionQuery<R> setFlushMode(FlushModeType flushMode); SelectionQuery<R> setFlushMode(FlushModeType flushMode);
@Override @Override @Deprecated(since = "7")
SelectionQuery<R> setHibernateFlushMode(FlushMode flushMode); SelectionQuery<R> setHibernateFlushMode(FlushMode flushMode);
@Override
SelectionQuery<R> setQueryFlushMode(QueryFlushMode queryFlushMode);
@Override @Override
SelectionQuery<R> setTimeout(int timeout); SelectionQuery<R> setTimeout(int timeout);
@ -421,14 +424,13 @@ public interface SelectionQuery<R> extends CommonQueryContract {
* the query inherits the {@link CacheMode} of the session from which * the query inherits the {@link CacheMode} of the session from which
* it originates. * it originates.
* <p> * <p>
* The {@link CacheMode} here describes reading-from/writing-to the * The {@link CacheMode} here affects the use of entity and collection
* entity/collection caches as we process query results. For caching * caches as the query result set is processed. For caching of the actual
* of the actual query results, see {@link #isCacheable()} and * query results, use {@link #isCacheable()} and {@link #getCacheRegion()}.
* {@link #getCacheRegion()}
* <p> * <p>
* In order for this setting to have any affect, second-level caching * In order for this setting to have any affect, second-level caching
* would have to be enabled and the entities/collections in question * must be enabled and the entities and collections must be eligible
* configured for caching. * for storage in the second-level cache.
* *
* @see Session#getCacheMode() * @see Session#getCacheMode()
*/ */
@ -450,9 +452,9 @@ public interface SelectionQuery<R> extends CommonQueryContract {
/** /**
* Set the current {@link CacheMode} in effect for this query. * Set the current {@link CacheMode} in effect for this query.
* * <p>
* @implNote Setting it to {@code null} ultimately indicates to use the * Set it to {@code null} to indicate that the {@code CacheMode}
* {@code CacheMode} of the session. * of the {@link Session#getCacheMode() session} should be used.
* *
* @see #getCacheMode() * @see #getCacheMode()
* @see Session#setCacheMode(CacheMode) * @see Session#setCacheMode(CacheMode)

View File

@ -14,6 +14,7 @@ import java.util.Map;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
import org.hibernate.query.QueryFlushMode;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.GraphSemantic;
@ -104,9 +105,12 @@ public interface SqmQueryImplementor<R> extends QueryImplementor<R>, SqmQuery, N
return setTupleTransformer( transformer ).setResultListTransformer( transformer ); return setTupleTransformer( transformer ).setResultListTransformer( transformer );
} }
@Override @Override @Deprecated(since = "7")
SqmQueryImplementor<R> setHibernateFlushMode(FlushMode flushMode); SqmQueryImplementor<R> setHibernateFlushMode(FlushMode flushMode);
@Override
SqmQueryImplementor<R> setQueryFlushMode(QueryFlushMode queryFlushMode);
@Override @Override
SqmQueryImplementor<R> setMaxResults(int maxResult); SqmQueryImplementor<R> setMaxResults(int maxResult);
@ -116,7 +120,7 @@ public interface SqmQueryImplementor<R> extends QueryImplementor<R>, SqmQuery, N
@Override @Override
SqmQueryImplementor<R> setHint(String hintName, Object value); SqmQueryImplementor<R> setHint(String hintName, Object value);
@Override @Override @Deprecated(since = "7")
SqmQueryImplementor<R> setFlushMode(FlushModeType flushMode); SqmQueryImplementor<R> setFlushMode(FlushModeType flushMode);
@Override @Override

View File

@ -17,6 +17,7 @@ import java.util.Set;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
import org.hibernate.query.QueryFlushMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
@ -178,7 +179,7 @@ public abstract class AbstractCommonQueryContract implements CommonQueryContract
} }
putIfNotNull( hints, HINT_COMMENT, getComment() ); putIfNotNull( hints, HINT_COMMENT, getComment() );
putIfNotNull( hints, HINT_FLUSH_MODE, getHibernateFlushMode() ); putIfNotNull( hints, HINT_FLUSH_MODE, getQueryOptions().getFlushMode() );
putIfNotNull( hints, HINT_READONLY, getQueryOptions().isReadOnly() ); putIfNotNull( hints, HINT_READONLY, getQueryOptions().isReadOnly() );
putIfNotNull( hints, HINT_FETCH_SIZE, getQueryOptions().getFetchSize() ); putIfNotNull( hints, HINT_FETCH_SIZE, getQueryOptions().getFetchSize() );
@ -521,7 +522,8 @@ public abstract class AbstractCommonQueryContract implements CommonQueryContract
@Override @Override
public FlushMode getHibernateFlushMode() { public FlushMode getHibernateFlushMode() {
return getQueryOptions().getFlushMode(); final FlushMode flushMode = getQueryOptions().getFlushMode();
return flushMode == null ? getSession().getHibernateFlushMode() : flushMode;
} }
@Override @Override
@ -530,6 +532,17 @@ public abstract class AbstractCommonQueryContract implements CommonQueryContract
return this; return this;
} }
@Override
public QueryFlushMode getQueryFlushMode() {
return FlushModeTypeHelper.getForcedFlushMode( getQueryOptions().getFlushMode() );
}
@Override
public CommonQueryContract setQueryFlushMode(QueryFlushMode queryFlushMode) {
getQueryOptions().setFlushMode( FlushModeTypeHelper.getFlushMode(queryFlushMode) );
return this;
}
protected boolean applyJpaCacheRetrieveModeHint(CacheRetrieveMode retrieveMode) { protected boolean applyJpaCacheRetrieveModeHint(CacheRetrieveMode retrieveMode) {
getQueryOptions().setCacheRetrieveMode( retrieveMode ); getQueryOptions().setCacheRetrieveMode( retrieveMode );
return true; return true;

View File

@ -27,6 +27,7 @@ import jakarta.persistence.TemporalType;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
import org.hibernate.query.QueryFlushMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
@ -194,18 +195,21 @@ public abstract class AbstractQuery<R>
return this; return this;
} }
@Override
public QueryImplementor<R> setQueryFlushMode(QueryFlushMode queryFlushMode) {
super.setQueryFlushMode(queryFlushMode);
return this;
}
@Override @Override
public FlushModeType getFlushMode() { public FlushModeType getFlushMode() {
getSession().checkOpen(); // getSession().checkOpen();
final FlushMode flushMode = getQueryOptions().getFlushMode() == null return FlushModeTypeHelper.getFlushModeType( getHibernateFlushMode() );
? getSession().getHibernateFlushMode()
: getQueryOptions().getFlushMode();
return FlushModeTypeHelper.getFlushModeType( flushMode );
} }
@Override @Override
public QueryImplementor<R> setFlushMode(FlushModeType flushModeType) { public QueryImplementor<R> setFlushMode(FlushModeType flushModeType) {
getSession().checkOpen(); // getSession().checkOpen();
setHibernateFlushMode( FlushModeTypeHelper.getFlushMode( flushModeType ) ); setHibernateFlushMode( FlushModeTypeHelper.getFlushMode( flushModeType ) );
return this; return this;
} }
@ -366,7 +370,7 @@ public abstract class AbstractQuery<R>
putIfNotNull( hints, HINT_COMMENT, getComment() ); putIfNotNull( hints, HINT_COMMENT, getComment() );
putIfNotNull( hints, HINT_FETCH_SIZE, getQueryOptions().getFetchSize() ); putIfNotNull( hints, HINT_FETCH_SIZE, getQueryOptions().getFetchSize() );
putIfNotNull( hints, HINT_FLUSH_MODE, getHibernateFlushMode() ); putIfNotNull( hints, HINT_FLUSH_MODE, getQueryOptions().getFlushMode() );
if ( getCacheMode() != null ) { if ( getCacheMode() != null ) {
putIfNotNull( hints, HINT_CACHE_MODE, getCacheMode() ); putIfNotNull( hints, HINT_CACHE_MODE, getCacheMode() );

View File

@ -20,6 +20,7 @@ import java.util.stream.StreamSupport;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
import org.hibernate.query.QueryFlushMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
@ -31,6 +32,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.GraphSemantic;
import org.hibernate.graph.spi.AppliedGraph; import org.hibernate.graph.spi.AppliedGraph;
import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.jpa.internal.util.FlushModeTypeHelper;
import org.hibernate.jpa.internal.util.LockModeTypeHelper; import org.hibernate.jpa.internal.util.LockModeTypeHelper;
import org.hibernate.query.BindableType; import org.hibernate.query.BindableType;
import org.hibernate.query.IllegalQueryOperationException; import org.hibernate.query.IllegalQueryOperationException;
@ -52,7 +54,6 @@ import jakarta.persistence.TemporalType;
import static java.util.Spliterators.spliteratorUnknownSize; import static java.util.Spliterators.spliteratorUnknownSize;
import static org.hibernate.CacheMode.fromJpaModes; import static org.hibernate.CacheMode.fromJpaModes;
import static org.hibernate.FlushMode.fromJpaFlushMode;
import static org.hibernate.cfg.AvailableSettings.JAKARTA_SHARED_CACHE_RETRIEVE_MODE; import static org.hibernate.cfg.AvailableSettings.JAKARTA_SHARED_CACHE_RETRIEVE_MODE;
import static org.hibernate.cfg.AvailableSettings.JAKARTA_SHARED_CACHE_STORE_MODE; import static org.hibernate.cfg.AvailableSettings.JAKARTA_SHARED_CACHE_STORE_MODE;
import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_RETRIEVE_MODE; import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_RETRIEVE_MODE;
@ -167,7 +168,7 @@ public abstract class AbstractSelectionQuery<R>
assert sessionFlushMode == null; assert sessionFlushMode == null;
assert sessionCacheMode == null; assert sessionCacheMode == null;
final FlushMode effectiveFlushMode = getHibernateFlushMode(); final FlushMode effectiveFlushMode = getQueryOptions().getFlushMode();
if ( effectiveFlushMode != null ) { if ( effectiveFlushMode != null ) {
sessionFlushMode = session.getHibernateFlushMode(); sessionFlushMode = session.getHibernateFlushMode();
session.setHibernateFlushMode( effectiveFlushMode ); session.setHibernateFlushMode( effectiveFlushMode );
@ -333,12 +334,12 @@ public abstract class AbstractSelectionQuery<R>
@Override @Override
public FlushModeType getFlushMode() { public FlushModeType getFlushMode() {
return getQueryOptions().getFlushMode().toJpaFlushMode(); return FlushModeTypeHelper.getFlushModeType( getHibernateFlushMode() );
} }
@Override @Override
public SelectionQuery<R> setFlushMode(FlushModeType flushMode) { public SelectionQuery<R> setFlushMode(FlushModeType flushMode) {
getQueryOptions().setFlushMode( fromJpaFlushMode( flushMode ) ); getQueryOptions().setFlushMode( FlushModeTypeHelper.getFlushMode( flushMode ) );
return this; return this;
} }
@ -566,6 +567,12 @@ public abstract class AbstractSelectionQuery<R>
return this; return this;
} }
@Override
public SelectionQuery<R> setQueryFlushMode(QueryFlushMode queryFlushMode) {
super.setQueryFlushMode(queryFlushMode);
return this;
}
@Override @Override
public SelectionQuery<R> setTimeout(int timeout) { public SelectionQuery<R> setTimeout(int timeout) {
super.setTimeout( timeout ); super.setTimeout( timeout );

View File

@ -13,6 +13,7 @@ import java.util.Date;
import java.util.Map; import java.util.Map;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
import org.hibernate.query.QueryFlushMode;
import org.hibernate.query.BindableType; import org.hibernate.query.BindableType;
import org.hibernate.query.CommonQueryContract; import org.hibernate.query.CommonQueryContract;
import org.hibernate.query.ParameterMetadata; import org.hibernate.query.ParameterMetadata;
@ -151,6 +152,9 @@ public interface SqmQuery extends CommonQueryContract {
@Override @Override
SqmQuery setProperties(@SuppressWarnings("rawtypes") Map bean); SqmQuery setProperties(@SuppressWarnings("rawtypes") Map bean);
@Override @Override @Deprecated(since = "7")
SqmQuery setHibernateFlushMode(FlushMode flushMode); SqmQuery setHibernateFlushMode(FlushMode flushMode);
@Override
SqmQuery setQueryFlushMode(QueryFlushMode queryFlushMode);
} }

View File

@ -22,6 +22,7 @@ import java.util.function.Supplier;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
import org.hibernate.query.QueryFlushMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
@ -55,7 +56,6 @@ import org.hibernate.query.TupleTransformer;
import org.hibernate.query.internal.DelegatingDomainQueryExecutionContext; import org.hibernate.query.internal.DelegatingDomainQueryExecutionContext;
import org.hibernate.query.internal.ParameterMetadataImpl; import org.hibernate.query.internal.ParameterMetadataImpl;
import org.hibernate.query.internal.QueryOptionsImpl; import org.hibernate.query.internal.QueryOptionsImpl;
import org.hibernate.query.internal.QueryParameterBindingsImpl;
import org.hibernate.query.internal.ResultSetMappingResolutionContext; import org.hibernate.query.internal.ResultSetMappingResolutionContext;
import org.hibernate.query.named.NamedResultSetMappingMemento; import org.hibernate.query.named.NamedResultSetMappingMemento;
import org.hibernate.query.results.Builders; import org.hibernate.query.results.Builders;
@ -469,7 +469,7 @@ public class NativeQueryImpl<R>
isCacheable(), isCacheable(),
getCacheRegion(), getCacheRegion(),
getCacheMode(), getCacheMode(),
getHibernateFlushMode(), getQueryOptions().getFlushMode(),
isReadOnly(), isReadOnly(),
getTimeout(), getTimeout(),
getFetchSize(), getFetchSize(),
@ -607,7 +607,7 @@ public class NativeQueryImpl<R>
private boolean shouldFlush() { private boolean shouldFlush() {
if ( getSession().isTransactionInProgress() ) { if ( getSession().isTransactionInProgress() ) {
FlushMode effectiveFlushMode = getHibernateFlushMode(); FlushMode effectiveFlushMode = getQueryOptions().getFlushMode();
if ( effectiveFlushMode == null ) { if ( effectiveFlushMode == null ) {
effectiveFlushMode = getSession().getHibernateFlushMode(); effectiveFlushMode = getSession().getHibernateFlushMode();
} }
@ -1180,6 +1180,12 @@ public class NativeQueryImpl<R>
return this; return this;
} }
@Override
public NativeQueryImplementor<R> setQueryFlushMode(QueryFlushMode queryFlushMode) {
super.setQueryFlushMode(queryFlushMode);
return this;
}
@Override @Override
public NativeQueryImplementor<R> setFlushMode(FlushModeType flushModeType) { public NativeQueryImplementor<R> setFlushMode(FlushModeType flushModeType) {
super.setFlushMode( flushModeType ); super.setFlushMode( flushModeType );

View File

@ -14,6 +14,7 @@ import java.util.Map;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
import org.hibernate.query.QueryFlushMode;
import org.hibernate.Incubating; import org.hibernate.Incubating;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
@ -148,10 +149,13 @@ public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQu
@Override @Override
NativeQueryImplementor<R> setHint(String hintName, Object value); NativeQueryImplementor<R> setHint(String hintName, Object value);
@Override @Override @Deprecated(since = "7")
NativeQueryImplementor<R> setHibernateFlushMode(FlushMode flushMode); NativeQueryImplementor<R> setHibernateFlushMode(FlushMode flushMode);
@Override @Override
NativeQueryImplementor<R> setQueryFlushMode(QueryFlushMode queryFlushMode);
@Override @Deprecated(since = "7")
NativeQueryImplementor<R> setFlushMode(FlushModeType flushMode); NativeQueryImplementor<R> setFlushMode(FlushModeType flushMode);
@Override @Override

View File

@ -14,6 +14,7 @@ import java.util.Map;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
import org.hibernate.query.QueryFlushMode;
import org.hibernate.query.BindableType; import org.hibernate.query.BindableType;
import org.hibernate.query.QueryParameter; import org.hibernate.query.QueryParameter;
import org.hibernate.query.SelectionQuery; import org.hibernate.query.SelectionQuery;
@ -141,9 +142,12 @@ public interface SqmSelectionQuery<R> extends SqmQuery, SelectionQuery<R> {
@Override @Override
SqmSelectionQuery<R> setProperties(@SuppressWarnings("rawtypes") Map bean); SqmSelectionQuery<R> setProperties(@SuppressWarnings("rawtypes") Map bean);
@Override @Override @Deprecated(since = "7")
SqmSelectionQuery<R> setHibernateFlushMode(FlushMode flushMode); SqmSelectionQuery<R> setHibernateFlushMode(FlushMode flushMode);
@Override
SqmSelectionQuery<R> setQueryFlushMode(QueryFlushMode queryFlushMode);
@Override @Override
SqmSelectionQuery<R> setCacheMode(CacheMode cacheMode); SqmSelectionQuery<R> setCacheMode(CacheMode cacheMode);

View File

@ -21,6 +21,7 @@ import java.util.function.Supplier;
import jakarta.persistence.EntityGraph; import jakarta.persistence.EntityGraph;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
import org.hibernate.query.QueryFlushMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
@ -35,8 +36,6 @@ import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.id.BulkInsertionCapableIdentifierGenerator; import org.hibernate.id.BulkInsertionCapableIdentifierGenerator;
import org.hibernate.id.OptimizableGenerator; import org.hibernate.id.OptimizableGenerator;
import org.hibernate.id.enhanced.Optimizer; import org.hibernate.id.enhanced.Optimizer;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping; import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping;
import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType;
@ -123,7 +122,6 @@ import static org.hibernate.query.sqm.internal.SqmUtil.verifyIsNonSelectStatemen
public class QuerySqmImpl<R> public class QuerySqmImpl<R>
extends AbstractSqmSelectionQuery<R> extends AbstractSqmSelectionQuery<R>
implements SqmQueryImplementor<R>, InterpretationsKeySource, DomainQueryExecutionContext { implements SqmQueryImplementor<R>, InterpretationsKeySource, DomainQueryExecutionContext {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( QuerySqmImpl.class );
private final String hql; private final String hql;
private SqmStatement<R> sqm; private SqmStatement<R> sqm;
@ -733,6 +731,12 @@ public class QuerySqmImpl<R>
return this; return this;
} }
@Override
public SqmQueryImplementor<R> setQueryFlushMode(QueryFlushMode queryFlushMode) {
super.setQueryFlushMode(queryFlushMode);
return this;
}
@Override @Override
public SqmQueryImplementor<R> setFlushMode(FlushModeType flushMode) { public SqmQueryImplementor<R> setFlushMode(FlushModeType flushMode) {
applyJpaFlushMode( flushMode ); applyJpaFlushMode( flushMode );
@ -909,7 +913,7 @@ public class QuerySqmImpl<R>
isCacheable(), isCacheable(),
getCacheRegion(), getCacheRegion(),
getCacheMode(), getCacheMode(),
getHibernateFlushMode(), getQueryOptions().getFlushMode(),
isReadOnly(), isReadOnly(),
getLockOptions(), getLockOptions(),
getTimeout(), getTimeout(),
@ -929,7 +933,7 @@ public class QuerySqmImpl<R>
isCacheable(), isCacheable(),
getCacheRegion(), getCacheRegion(),
getCacheMode(), getCacheMode(),
getHibernateFlushMode(), getQueryOptions().getFlushMode(),
isReadOnly(), isReadOnly(),
getLockOptions(), getLockOptions(),
getTimeout(), getTimeout(),

View File

@ -24,6 +24,7 @@ import jakarta.persistence.TemporalType;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
import org.hibernate.query.QueryFlushMode;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.ScrollMode; import org.hibernate.ScrollMode;
import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.LoadQueryInfluencers;
@ -551,6 +552,12 @@ public class SqmSelectionQueryImpl<R> extends AbstractSqmSelectionQuery<R>
return this; return this;
} }
@Override
public SqmSelectionQuery<R> setQueryFlushMode(QueryFlushMode queryFlushMode) {
super.setQueryFlushMode(queryFlushMode);
return this;
}
@Override @Override
public SqmSelectionQuery<R> setTimeout(int timeout) { public SqmSelectionQuery<R> setTimeout(int timeout) {
super.setTimeout( timeout ); super.setTimeout( timeout );

View File

@ -29,8 +29,10 @@ import org.hibernate.query.KeyedResultList;
import org.hibernate.query.Order; import org.hibernate.query.Order;
import org.hibernate.query.Page; import org.hibernate.query.Page;
import org.hibernate.query.ParameterMetadata; import org.hibernate.query.ParameterMetadata;
import org.hibernate.query.QueryFlushMode;
import org.hibernate.query.QueryParameter; import org.hibernate.query.QueryParameter;
import org.hibernate.query.spi.QueryOptions; import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.sqm.SqmSelectionQuery;
import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.sql.results.spi.ResultsConsumer; import org.hibernate.sql.results.spi.ResultsConsumer;
@ -63,6 +65,16 @@ public abstract class DelegatingSqmSelectionQueryImplementor<R> implements SqmSe
return getDelegate().getHibernateFlushMode(); return getDelegate().getHibernateFlushMode();
} }
@Override
public QueryFlushMode getQueryFlushMode() {
return getDelegate().getQueryFlushMode();
}
@Override
public SqmSelectionQuery<R> setQueryFlushMode(QueryFlushMode queryFlushMode) {
return getDelegate().setQueryFlushMode( queryFlushMode );
}
@Override @Override
public Integer getTimeout() { public Integer getTimeout() {
return getDelegate().getTimeout(); return getDelegate().getTimeout();

View File

@ -25,7 +25,6 @@ import org.hibernate.testing.orm.junit.Jpa;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
/** /**
* @author Yoann Rodiere * @author Yoann Rodiere
@ -103,22 +102,22 @@ public class NamedQueryFlushModeTest {
s.setHibernateFlushMode( FlushMode.MANUAL ); s.setHibernateFlushMode( FlushMode.MANUAL );
query = s.getNamedQuery( queryName ); query = s.getNamedQuery( queryName );
assertNull( query.getHibernateFlushMode() ); assertEquals( FlushMode.MANUAL, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.COMMIT, query.getFlushMode() ); assertEquals( jakarta.persistence.FlushModeType.COMMIT, query.getFlushMode() );
s.setHibernateFlushMode( FlushMode.COMMIT ); s.setHibernateFlushMode( FlushMode.COMMIT );
query = s.getNamedQuery( queryName ); query = s.getNamedQuery( queryName );
assertNull( query.getHibernateFlushMode() ); assertEquals( FlushMode.COMMIT, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.COMMIT, query.getFlushMode() ); assertEquals( jakarta.persistence.FlushModeType.COMMIT, query.getFlushMode() );
s.setHibernateFlushMode( FlushMode.AUTO ); s.setHibernateFlushMode( FlushMode.AUTO );
query = s.getNamedQuery( queryName ); query = s.getNamedQuery( queryName );
assertNull( query.getHibernateFlushMode() ); assertEquals( FlushMode.AUTO, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.AUTO, query.getFlushMode() ); assertEquals( jakarta.persistence.FlushModeType.AUTO, query.getFlushMode() );
s.setHibernateFlushMode( FlushMode.ALWAYS ); s.setHibernateFlushMode( FlushMode.ALWAYS );
query = s.getNamedQuery( queryName ); query = s.getNamedQuery( queryName );
assertNull( query.getHibernateFlushMode() ); assertEquals( FlushMode.ALWAYS, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.AUTO, query.getFlushMode() ); assertEquals( jakarta.persistence.FlushModeType.AUTO, query.getFlushMode() );
} }
); );
@ -185,22 +184,22 @@ public class NamedQueryFlushModeTest {
s.setHibernateFlushMode( FlushMode.MANUAL ); s.setHibernateFlushMode( FlushMode.MANUAL );
query = s.getNamedNativeQuery( queryName ); query = s.getNamedNativeQuery( queryName );
assertNull( query.getHibernateFlushMode() ); assertEquals( FlushMode.MANUAL, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.COMMIT, query.getFlushMode() ); assertEquals( jakarta.persistence.FlushModeType.COMMIT, query.getFlushMode() );
s.setHibernateFlushMode( FlushMode.COMMIT ); s.setHibernateFlushMode( FlushMode.COMMIT );
query = s.getNamedNativeQuery( queryName ); query = s.getNamedNativeQuery( queryName );
assertNull( query.getHibernateFlushMode() ); assertEquals( FlushMode.COMMIT, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.COMMIT, query.getFlushMode() ); assertEquals( jakarta.persistence.FlushModeType.COMMIT, query.getFlushMode() );
s.setHibernateFlushMode( FlushMode.AUTO ); s.setHibernateFlushMode( FlushMode.AUTO );
query = s.getNamedNativeQuery( queryName ); query = s.getNamedNativeQuery( queryName );
assertNull( query.getHibernateFlushMode() ); assertEquals( FlushMode.AUTO, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.AUTO, query.getFlushMode() ); assertEquals( jakarta.persistence.FlushModeType.AUTO, query.getFlushMode() );
s.setHibernateFlushMode( FlushMode.ALWAYS ); s.setHibernateFlushMode( FlushMode.ALWAYS );
query = s.getNamedNativeQuery( queryName ); query = s.getNamedNativeQuery( queryName );
assertNull( query.getHibernateFlushMode() ); assertEquals( FlushMode.ALWAYS, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.AUTO, query.getFlushMode() ); assertEquals( jakarta.persistence.FlushModeType.AUTO, query.getFlushMode() );
} }
); );

View File

@ -0,0 +1,293 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.orm.test.jpa.query;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import org.hibernate.FlushMode;
import org.hibernate.query.QueryFlushMode;
import org.hibernate.Session;
import org.hibernate.annotations.NamedNativeQuery;
import org.hibernate.annotations.NamedQuery;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.Query;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.orm.junit.Jpa;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* @author Yoann Rodiere
*/
@JiraKey("HHH-12795")
@Jpa(annotatedClasses = {
NamedQueryQueryFlushModeTest.TestEntity.class
})
public class NamedQueryQueryFlushModeTest {
@Test
public void testNamedQueryWithFlushModeManual(EntityManagerFactoryScope scope) {
String queryName = "NamedQueryFlushModeManual";
scope.inEntityManager(
entityManager -> {
Session s = entityManager.unwrap( Session.class );
Query<?> query = s.getNamedQuery( queryName );
assertEquals( FlushMode.MANUAL, query.getHibernateFlushMode() );
// JPA flush mode is an approximation
assertEquals( jakarta.persistence.FlushModeType.COMMIT, query.getFlushMode() );
}
);
}
@Test
public void testNamedQueryWithFlushModeCommit(EntityManagerFactoryScope scope) {
String queryName = "NamedQueryFlushModeCommit";
scope.inEntityManager(
entityManager -> {
Session s = entityManager.unwrap( Session.class );
Query<?> query = s.getNamedQuery( queryName );
assertEquals( FlushMode.MANUAL, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.COMMIT, query.getFlushMode() );
}
);
}
@Test
public void testNamedQueryWithFlushModeAuto(EntityManagerFactoryScope scope) {
String queryName = "NamedQueryFlushModeAuto";
scope.inEntityManager(
entityManager -> {
Session s = entityManager.unwrap( Session.class );
Query<?> query = s.getNamedQuery( queryName );
assertEquals( FlushMode.AUTO, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.AUTO, query.getFlushMode() );
}
);
}
@Test
public void testNamedQueryWithFlushModeAlways(EntityManagerFactoryScope scope) {
String queryName = "NamedQueryFlushModeAlways";
scope.inEntityManager(
entityManager -> {
Session s = entityManager.unwrap( Session.class );
Query<?> query = s.getNamedQuery( queryName );
assertEquals( FlushMode.ALWAYS, query.getHibernateFlushMode() );
// JPA flush mode is an approximation
assertEquals( jakarta.persistence.FlushModeType.AUTO, query.getFlushMode() );
}
);
}
@Test
public void testNamedQueryWithFlushModePersistenceContext(EntityManagerFactoryScope scope) {
String queryName = "NamedQueryFlushModePersistenceContext";
scope.inEntityManager(
entityManager -> {
Session s = entityManager.unwrap( Session.class );
Query<?> query;
// A null Hibernate flush mode means we will use whatever mode is set on the session
// JPA doesn't allow null flush modes, so we expect some approximation of the flush mode to be returned
s.setHibernateFlushMode( FlushMode.MANUAL );
query = s.getNamedQuery( queryName );
assertEquals( FlushMode.MANUAL, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.COMMIT, query.getFlushMode() );
assertEquals( QueryFlushMode.DEFAULT, query.getQueryFlushMode() );
s.setHibernateFlushMode( FlushMode.COMMIT );
query = s.getNamedQuery( queryName );
assertEquals( FlushMode.COMMIT, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.COMMIT, query.getFlushMode() );
assertEquals( QueryFlushMode.DEFAULT, query.getQueryFlushMode() );
s.setHibernateFlushMode( FlushMode.AUTO );
query = s.getNamedQuery( queryName );
assertEquals( FlushMode.AUTO, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.AUTO, query.getFlushMode() );
assertEquals( QueryFlushMode.DEFAULT, query.getQueryFlushMode() );
s.setHibernateFlushMode( FlushMode.ALWAYS );
query = s.getNamedQuery( queryName );
assertEquals( FlushMode.ALWAYS, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.AUTO, query.getFlushMode() );
assertEquals( QueryFlushMode.DEFAULT, query.getQueryFlushMode() );
}
);
}
@Test
public void testNamedNativeQueryWithFlushModeManual(EntityManagerFactoryScope scope) {
String queryName = "NamedNativeQueryFlushModeManual";
scope.inEntityManager(
entityManager -> {
Session s = entityManager.unwrap( Session.class );
NativeQuery<?> query = s.getNamedNativeQuery( queryName );
assertEquals( FlushMode.MANUAL, query.getHibernateFlushMode() );
assertEquals( QueryFlushMode.NO_FLUSH, query.getQueryFlushMode() );
}
);
}
@Test
public void testNamedNativeQueryWithFlushModeCommit(EntityManagerFactoryScope scope) {
String queryName = "NamedNativeQueryFlushModeCommit";
scope.inEntityManager(
entityManager -> {
Session s = entityManager.unwrap( Session.class );
NativeQuery<?> query = s.getNamedNativeQuery( queryName );
assertEquals( FlushMode.MANUAL, query.getHibernateFlushMode() );
assertEquals( QueryFlushMode.NO_FLUSH, query.getQueryFlushMode() );
}
);
}
@Test
public void testNamedNativeQueryWithFlushModeAuto(EntityManagerFactoryScope scope) {
String queryName = "NamedNativeQueryFlushModeAuto";
scope.inEntityManager(
entityManager -> {
Session s = entityManager.unwrap( Session.class );
NativeQuery<?> query = s.getNamedNativeQuery( queryName );
assertEquals( FlushMode.AUTO, query.getHibernateFlushMode() );
assertEquals( QueryFlushMode.DEFAULT, query.getQueryFlushMode() );
}
);
}
@Test
public void testNamedNativeQueryWithFlushModeAlways(EntityManagerFactoryScope scope) {
String queryName = "NamedNativeQueryFlushModeAlways";
scope.inEntityManager(
entityManager -> {
Session s = entityManager.unwrap( Session.class );
NativeQuery<?> query = s.getNamedNativeQuery( queryName );
assertEquals( FlushMode.ALWAYS, query.getHibernateFlushMode() );
assertEquals( QueryFlushMode.FLUSH, query.getQueryFlushMode() );
}
);
}
@Test
public void testNamedNativeQueryWithFlushModePersistenceContext(EntityManagerFactoryScope scope) {
String queryName = "NamedNativeQueryFlushModePersistenceContext";
scope.inEntityManager(
entityManager -> {
Session s = entityManager.unwrap( Session.class );
NativeQuery<?> query;
// A null Hibernate flush mode means we will use whatever mode is set on the session
// JPA doesn't allow null flush modes, so we expect some approximation of the flush mode to be returned
s.setHibernateFlushMode( FlushMode.MANUAL );
query = s.getNamedNativeQuery( queryName );
assertEquals( FlushMode.MANUAL, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.COMMIT, query.getFlushMode() );
s.setHibernateFlushMode( FlushMode.COMMIT );
query = s.getNamedNativeQuery( queryName );
assertEquals( FlushMode.COMMIT, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.COMMIT, query.getFlushMode() );
s.setHibernateFlushMode( FlushMode.AUTO );
query = s.getNamedNativeQuery( queryName );
assertEquals( FlushMode.AUTO, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.AUTO, query.getFlushMode() );
s.setHibernateFlushMode( FlushMode.ALWAYS );
query = s.getNamedNativeQuery( queryName );
assertEquals( FlushMode.ALWAYS, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.AUTO, query.getFlushMode() );
}
);
}
@Entity(name = "TestEntity")
@NamedQuery(
name = "NamedQueryFlushModeManual",
query = "select e from TestEntity e where e.text = :text",
flush = QueryFlushMode.NO_FLUSH
)
@NamedQuery(
name = "NamedQueryFlushModeCommit",
query = "select e from TestEntity e where e.text = :text",
flush = QueryFlushMode.NO_FLUSH
)
@NamedQuery(
name = "NamedQueryFlushModeAuto",
query = "select e from TestEntity e where e.text = :text",
flush = QueryFlushMode.DEFAULT
)
@NamedQuery(
name = "NamedQueryFlushModeAlways",
query = "select e from TestEntity e where e.text = :text",
flush = QueryFlushMode.FLUSH
)
@NamedQuery(
name = "NamedQueryFlushModePersistenceContext",
query = "select e from TestEntity e where e.text = :text",
flush = QueryFlushMode.DEFAULT
)
@NamedNativeQuery(
name = "NamedNativeQueryFlushModeManual",
query = "select * from TestEntity e where e.text = :text",
resultClass = TestEntity.class,
flush = QueryFlushMode.NO_FLUSH
)
@NamedNativeQuery(
name = "NamedNativeQueryFlushModeCommit",
query = "select * from TestEntity e where e.text = :text",
resultClass = TestEntity.class,
flush = QueryFlushMode.NO_FLUSH
)
@NamedNativeQuery(
name = "NamedNativeQueryFlushModeAuto",
query = "select * from TestEntity e where e.text = :text",
resultClass = TestEntity.class,
flush = QueryFlushMode.DEFAULT
)
@NamedNativeQuery(
name = "NamedNativeQueryFlushModeAlways",
query = "select * from TestEntity e where e.text = :text",
resultClass = TestEntity.class,
flush = QueryFlushMode.FLUSH
)
@NamedNativeQuery(
name = "NamedNativeQueryFlushModePersistenceContext",
query = "select * from TestEntity e where e.text = :text",
resultClass = TestEntity.class,
flush = QueryFlushMode.DEFAULT
)
public static class TestEntity {
@Id
@GeneratedValue
private Long id;
private String text;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
}