diff --git a/hibernate-core/src/main/java/org/hibernate/FlushMode.java b/hibernate-core/src/main/java/org/hibernate/FlushMode.java
index 79a0ca205d..29caaf86a0 100644
--- a/hibernate-core/src/main/java/org/hibernate/FlushMode.java
+++ b/hibernate-core/src/main/java/org/hibernate/FlushMode.java
@@ -18,9 +18,16 @@ import jakarta.persistence.FlushModeType;
*
* For example, {@link #COMMIT} specifies that the session flushes
* automatically when the transaction is about to commit.
+ *
+ * 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 org.hibernate.query.CommonQueryContract#setHibernateFlushMode
+ * @see org.hibernate.query.QueryFlushMode
*
* @author Gavin King
*/
diff --git a/hibernate-core/src/main/java/org/hibernate/Session.java b/hibernate-core/src/main/java/org/hibernate/Session.java
index e5b8713c8a..64c0a3358f 100644
--- a/hibernate-core/src/main/java/org/hibernate/Session.java
+++ b/hibernate-core/src/main/java/org/hibernate/Session.java
@@ -199,7 +199,7 @@ public interface Session extends SharedSessionContract, EntityManager {
void flush();
/**
- * Set the current {@link FlushModeType JPA flush mode} for this session.
+ * Set the current {@linkplain FlushModeType JPA flush mode} for this session.
*
* Flushing is the process of synchronizing the underlying persistent
* store with persistable state held in memory. The current flush mode determines
diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/FlushModeType.java b/hibernate-core/src/main/java/org/hibernate/annotations/FlushModeType.java
index 24818577ec..73c1462c1a 100644
--- a/hibernate-core/src/main/java/org/hibernate/annotations/FlushModeType.java
+++ b/hibernate-core/src/main/java/org/hibernate/annotations/FlushModeType.java
@@ -6,6 +6,8 @@
*/
package org.hibernate.annotations;
+import org.hibernate.query.QueryFlushMode;
+
/**
* Enumeration extending the {@linkplain jakarta.persistence.FlushModeType JPA flush modes}
* 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
*
- * @see NamedQuery
- * @see NamedNativeQuery
+ * @see NamedQuery#flushMode
+ * @see NamedNativeQuery#flushMode
+ *
+ * @deprecated use {@link QueryFlushMode}
*/
+@Deprecated(since="7")
public enum FlushModeType {
/**
* Corresponds to {@link org.hibernate.FlushMode#ALWAYS}.
diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/NamedNativeQuery.java b/hibernate-core/src/main/java/org/hibernate/annotations/NamedNativeQuery.java
index 79b204bdcc..7a028ee81d 100644
--- a/hibernate-core/src/main/java/org/hibernate/annotations/NamedNativeQuery.java
+++ b/hibernate-core/src/main/java/org/hibernate/annotations/NamedNativeQuery.java
@@ -13,6 +13,7 @@ import java.lang.annotation.Target;
import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode;
import org.hibernate.CacheMode;
+import org.hibernate.query.QueryFlushMode;
import static java.lang.annotation.ElementType.PACKAGE;
import static java.lang.annotation.ElementType.TYPE;
@@ -63,12 +64,25 @@ public @interface NamedNativeQuery {
*/
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.
*
* @see org.hibernate.query.CommonQueryContract#setFlushMode(jakarta.persistence.FlushModeType)
* @see org.hibernate.jpa.HibernateHints#HINT_FLUSH_MODE
+ *
+ * @deprecated use {@link #flush()}
*/
+ @Deprecated(since = "7")
FlushModeType flushMode() default FlushModeType.PERSISTENCE_CONTEXT;
/**
diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/NamedQuery.java b/hibernate-core/src/main/java/org/hibernate/annotations/NamedQuery.java
index 61c8bba6f3..8d2adf5472 100644
--- a/hibernate-core/src/main/java/org/hibernate/annotations/NamedQuery.java
+++ b/hibernate-core/src/main/java/org/hibernate/annotations/NamedQuery.java
@@ -15,6 +15,7 @@ import jakarta.persistence.CacheStoreMode;
import jakarta.persistence.EntityManager;
import org.hibernate.CacheMode;
+import org.hibernate.query.QueryFlushMode;
import static java.lang.annotation.ElementType.PACKAGE;
import static java.lang.annotation.ElementType.TYPE;
@@ -58,12 +59,25 @@ public @interface NamedQuery {
*/
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.
*
* @see org.hibernate.query.CommonQueryContract#setFlushMode(jakarta.persistence.FlushModeType)
* @see org.hibernate.jpa.HibernateHints#HINT_FLUSH_MODE
+ *
+ * @deprecated use {@link #flush()}
*/
+ @Deprecated(since = "7")
FlushModeType flushMode() default FlushModeType.PERSISTENCE_CONTEXT;
/**
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/QueryBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/QueryBinder.java
index 1151318f39..999f8ea04a 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/QueryBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/QueryBinder.java
@@ -16,6 +16,7 @@ import java.util.function.Supplier;
import org.hibernate.AnnotationException;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
+import org.hibernate.query.QueryFlushMode;
import org.hibernate.LockOptions;
import org.hibernate.annotations.FlushModeType;
import org.hibernate.annotations.HQLSelect;
@@ -35,6 +36,7 @@ import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.log.DeprecationLogger;
import org.hibernate.jpa.HibernateHints;
+import org.hibernate.jpa.internal.util.FlushModeTypeHelper;
import org.hibernate.models.internal.util.StringHelper;
import org.hibernate.models.spi.ClassDetails;
import org.hibernate.models.spi.SourceModelBuildingContext;
@@ -271,7 +273,7 @@ public abstract class QueryBinder {
.setCacheMode(getCacheMode(namedNativeQuery.cacheRetrieveMode(), namedNativeQuery.cacheStoreMode()))
.setTimeout(timeout < 0 ? null : timeout)
.setFetchSize(fetchSize < 0 ? null : fetchSize)
- .setFlushMode(getFlushMode(namedNativeQuery.flushMode()))
+ .setFlushMode(getFlushMode(namedNativeQuery.flush(), namedNativeQuery.flushMode()))
.setReadOnly(namedNativeQuery.readOnly())
.setQuerySpaces(querySpaces)
.setComment(nullIfEmpty(namedNativeQuery.comment()));
@@ -412,7 +414,7 @@ public abstract class QueryBinder {
.setCacheMode(getCacheMode(namedQuery.cacheRetrieveMode(), namedQuery.cacheStoreMode()))
.setTimeout(timeout < 0 ? null : timeout)
.setFetchSize(fetchSize < 0 ? null : fetchSize)
- .setFlushMode(getFlushMode(namedQuery.flushMode()))
+ .setFlushMode(getFlushMode(namedQuery.flush(), namedQuery.flushMode()))
.setReadOnly(namedQuery.readOnly())
.setComment(nullIfEmpty(namedQuery.comment()));
}
@@ -422,6 +424,12 @@ public abstract class QueryBinder {
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) {
return switch ( flushModeType ) {
case ALWAYS -> FlushMode.ALWAYS;
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/models/annotations/internal/NamedNativeQueryAnnotation.java b/hibernate-core/src/main/java/org/hibernate/boot/models/annotations/internal/NamedNativeQueryAnnotation.java
index 45441f7229..2b4c0898cb 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/models/annotations/internal/NamedNativeQueryAnnotation.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/models/annotations/internal/NamedNativeQueryAnnotation.java
@@ -24,6 +24,7 @@ import org.hibernate.models.spi.SourceModelBuildingContext;
import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode;
+import org.hibernate.query.QueryFlushMode;
@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" })
@jakarta.annotation.Generated("org.hibernate.orm.build.annotations.ClassGeneratorProcessor")
@@ -33,6 +34,7 @@ public class NamedNativeQueryAnnotation implements NamedNativeQuery {
private Class> resultClass;
private String resultSetMapping;
private FlushModeType flushMode;
+ private QueryFlushMode flush;
boolean cacheable;
String cacheRegion;
int fetchSize;
@@ -51,6 +53,7 @@ public class NamedNativeQueryAnnotation implements NamedNativeQuery {
resultClass = void.class;
resultSetMapping = "";
flushMode = FlushModeType.PERSISTENCE_CONTEXT;
+ flush = QueryFlushMode.DEFAULT;
cacheable = false;
cacheRegion = "";
fetchSize = -1;
@@ -72,6 +75,7 @@ public class NamedNativeQueryAnnotation implements NamedNativeQuery {
this.resultClass = annotation.resultClass();
this.resultSetMapping = annotation.resultSetMapping();
this.flushMode = annotation.flushMode();
+ this.flush = annotation.flush();
this.cacheable = annotation.cacheable();
this.cacheRegion = annotation.cacheRegion();
this.fetchSize = annotation.fetchSize();
@@ -97,6 +101,7 @@ public class NamedNativeQueryAnnotation implements NamedNativeQuery {
this.resultClass = (Class>) attributeValues.get( "resultClass" );
this.resultSetMapping = (String) attributeValues.get( "resultSetMapping" );
this.flushMode = (FlushModeType) attributeValues.get( "flushMode" );
+ this.flush = (QueryFlushMode) attributeValues.get( "flush" );
this.cacheable = (boolean) attributeValues.get( "cacheable" );
this.cacheRegion = (String) attributeValues.get( "cacheRegion" );
this.fetchSize = (int) attributeValues.get( "fetchSize" );
@@ -152,6 +157,15 @@ public class NamedNativeQueryAnnotation implements NamedNativeQuery {
this.resultSetMapping = value;
}
+ @Override
+ public QueryFlushMode flush() {
+ return flush;
+ }
+
+ public void flush(QueryFlushMode value) {
+ this.flush = value;
+ }
+
@Override
public FlushModeType flushMode() {
return flushMode;
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/models/annotations/internal/NamedQueryAnnotation.java b/hibernate-core/src/main/java/org/hibernate/boot/models/annotations/internal/NamedQueryAnnotation.java
index 01eb1aa921..d884bac43c 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/models/annotations/internal/NamedQueryAnnotation.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/models/annotations/internal/NamedQueryAnnotation.java
@@ -19,6 +19,7 @@ import org.hibernate.models.spi.SourceModelBuildingContext;
import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode;
+import org.hibernate.query.QueryFlushMode;
import static org.hibernate.boot.models.xml.internal.QueryProcessing.interpretFlushMode;
@@ -29,6 +30,7 @@ public class NamedQueryAnnotation implements NamedQuery {
private String query;
private Class> resultClass;
private FlushModeType flushMode;
+ private QueryFlushMode flush;
boolean cacheable;
String cacheRegion;
int fetchSize;
@@ -44,6 +46,7 @@ public class NamedQueryAnnotation implements NamedQuery {
public NamedQueryAnnotation(SourceModelBuildingContext modelContext) {
resultClass = void.class;
flushMode = FlushModeType.PERSISTENCE_CONTEXT;
+ flush = QueryFlushMode.DEFAULT;
cacheable = false;
cacheRegion = "";
fetchSize = -1;
@@ -62,6 +65,7 @@ public class NamedQueryAnnotation implements NamedQuery {
this.query = annotation.query();
this.resultClass = annotation.resultClass();
this.flushMode = annotation.flushMode();
+ this.flush = annotation.flush();
this.cacheable = annotation.cacheable();
this.cacheRegion = annotation.cacheRegion();
this.fetchSize = annotation.fetchSize();
@@ -84,6 +88,7 @@ public class NamedQueryAnnotation implements NamedQuery {
this.query = (String) attributeValues.get( "query" );
this.resultClass = (Class>) attributeValues.get( "resultClass" );
this.flushMode = (FlushModeType) attributeValues.get( "flushMode" );
+ this.flush = (QueryFlushMode) attributeValues.get( "flush" );
this.cacheable = (boolean) attributeValues.get( "cacheable" );
this.cacheRegion = (String) attributeValues.get( "cacheRegion" );
this.fetchSize = (int) attributeValues.get( "fetchSize" );
@@ -128,6 +133,15 @@ public class NamedQueryAnnotation implements NamedQuery {
this.resultClass = value;
}
+ @Override
+ public QueryFlushMode flush() {
+ return flush;
+ }
+
+ public void flush(QueryFlushMode value) {
+ this.flush = value;
+ }
+
@Override
public FlushModeType flushMode() {
return flushMode;
diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/internal/util/FlushModeTypeHelper.java b/hibernate-core/src/main/java/org/hibernate/jpa/internal/util/FlushModeTypeHelper.java
index c07ba9b4d7..55e438baa8 100644
--- a/hibernate-core/src/main/java/org/hibernate/jpa/internal/util/FlushModeTypeHelper.java
+++ b/hibernate-core/src/main/java/org/hibernate/jpa/internal/util/FlushModeTypeHelper.java
@@ -10,8 +10,8 @@ package org.hibernate.jpa.internal.util;
import java.util.Locale;
import jakarta.persistence.FlushModeType;
-import org.hibernate.AssertionFailure;
import org.hibernate.FlushMode;
+import org.hibernate.query.QueryFlushMode;
import org.hibernate.MappingException;
import org.jboss.logging.Logger;
@@ -28,35 +28,55 @@ public class FlushModeTypeHelper {
}
public static FlushModeType getFlushModeType(FlushMode flushMode) {
- if ( flushMode == FlushMode.ALWAYS ) {
- log.debug( "Interpreting Hibernate FlushMode#ALWAYS to JPA FlushModeType#AUTO; may cause problems if relying on FlushMode#ALWAYS-specific behavior" );
- return FlushModeType.AUTO;
+ if ( flushMode == null ) {
+ return null;
}
- else if ( flushMode == FlushMode.MANUAL ) {
- log.debug( "Interpreting Hibernate FlushMode#MANUAL to JPA FlushModeType#COMMIT; may cause problems if relying on FlushMode#MANUAL-specific behavior" );
- return FlushModeType.COMMIT;
- }
- else if ( flushMode == FlushMode.COMMIT ) {
- return FlushModeType.COMMIT;
- }
- else if ( flushMode == FlushMode.AUTO ) {
- return FlushModeType.AUTO;
- }
- else {
- throw new AssertionFailure( "unhandled FlushMode " + flushMode );
+ return switch (flushMode) {
+ case ALWAYS -> {
+ log.debug("Interpreting Hibernate FlushMode.ALWAYS as JPA FlushModeType.AUTO (may cause problems if relying on FlushMode.ALWAYS-specific behavior)");
+ yield FlushModeType.AUTO;
+ }
+ case MANUAL -> {
+ log.debug("Interpreting Hibernate FlushMode.MANUAL as JPA FlushModeType.COMMIT (may cause problems if relying on FlushMode.MANUAL-specific behavior)");
+ yield FlushModeType.COMMIT;
+ }
+ case COMMIT -> FlushModeType.COMMIT;
+ case AUTO -> FlushModeType.AUTO;
+ };
+ }
+
+ 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) {
- if ( flushModeType == FlushModeType.AUTO ) {
- return FlushMode.AUTO;
+ if ( flushModeType == null ) {
+ return null;
}
- else if ( flushModeType == FlushModeType.COMMIT ) {
- return FlushMode.COMMIT;
- }
- else {
- throw new AssertionFailure( "unhandled FlushModeType " + flushModeType );
+ return switch (flushModeType) {
+ case AUTO -> FlushMode.AUTO;
+ case COMMIT -> FlushMode.COMMIT;
+ };
+ }
+
+ 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) {
diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/ProcedureCall.java b/hibernate-core/src/main/java/org/hibernate/procedure/ProcedureCall.java
index 7418ac6546..a6db5f5fbc 100644
--- a/hibernate-core/src/main/java/org/hibernate/procedure/ProcedureCall.java
+++ b/hibernate-core/src/main/java/org/hibernate/procedure/ProcedureCall.java
@@ -281,7 +281,7 @@ public interface ProcedureCall
@Override
ProcedureCall setParameter(int position, Date value, TemporalType temporalType);
- @Override
+ @Override @Deprecated(since = "7")
ProcedureCall setFlushMode(FlushModeType flushMode);
@Override
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 d61b28d410..4904cce092 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
@@ -809,7 +809,7 @@ public class ProcedureCallImpl
isCacheable(),
getCacheRegion(),
getCacheMode(),
- getHibernateFlushMode(),
+ getQueryOptions().getFlushMode(),
isReadOnly(),
getTimeout(),
getFetchSize(),
diff --git a/hibernate-core/src/main/java/org/hibernate/query/CommonQueryContract.java b/hibernate-core/src/main/java/org/hibernate/query/CommonQueryContract.java
index 1acbeccdf6..a6919298aa 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/CommonQueryContract.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/CommonQueryContract.java
@@ -51,48 +51,86 @@ import jakarta.persistence.TemporalType;
*/
public interface CommonQueryContract {
+ /**
+ * The {@link QueryFlushMode} in effect for this query.
+ *
+ * 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
* query inherits the {@link FlushMode} of the {@link Session} from which
* it originates.
*
- * @see #getHibernateFlushMode
- * @see Session#getHibernateFlushMode
+ * @see #getQueryFlushMode()
+ * @see #getHibernateFlushMode()
+ * @see Session#getHibernateFlushMode()
+ *
+ * @deprecated use {@link #getQueryFlushMode()}
*/
+ @Deprecated(since = "7")
FlushModeType getFlushMode();
/**
- * Set the {@link FlushMode} in to use for this query.
- *
- * @implNote Setting to {@code null} ultimately indicates to use the
- * FlushMode of the Session. Use {@link #setHibernateFlushMode} passing
- * {@link FlushMode#MANUAL} instead to indicate that no automatic flushing
- * should occur
+ * Set the {@link FlushMode} to use for this query.
+ *
+ * Setting this to {@code null} ultimately indicates to use the
+ * {@link FlushMode} of the session. Use {@link #setHibernateFlushMode}
+ * passing {@link FlushMode#MANUAL} instead to indicate that no automatic
+ * flushing should occur.
*
+ * @see #getQueryFlushMode()
* @see #getHibernateFlushMode()
* @see Session#getHibernateFlushMode()
+ *
+ * @deprecated use {@link #setQueryFlushMode(QueryFlushMode)}
*/
+ @Deprecated(since = "7")
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
* originates.
*
- * @see Session#getHibernateFlushMode
+ * @see #getQueryFlushMode()
+ * @see Session#getHibernateFlushMode()
+ *
+ * @deprecated use {@link #getQueryFlushMode()}
*/
+ @Deprecated(since = "7")
FlushMode getHibernateFlushMode();
/**
* Set the current {@link FlushMode} in effect for this query.
*
* @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.
*
+ * @see #getQueryFlushMode()
* @see #getHibernateFlushMode()
* @see Session#getHibernateFlushMode()
+ *
+ * @deprecated use {@link #setQueryFlushMode(QueryFlushMode)}
*/
+ @Deprecated(since = "7")
CommonQueryContract setHibernateFlushMode(FlushMode flushMode);
/**
diff --git a/hibernate-core/src/main/java/org/hibernate/query/MutationQuery.java b/hibernate-core/src/main/java/org/hibernate/query/MutationQuery.java
index 2f13e5178d..9ce0ef89c4 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/MutationQuery.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/MutationQuery.java
@@ -14,7 +14,6 @@ import java.util.Map;
import org.hibernate.FlushMode;
import org.hibernate.Incubating;
-import org.hibernate.Session;
import jakarta.persistence.FlushModeType;
import jakarta.persistence.Parameter;
@@ -81,10 +80,10 @@ public interface MutationQuery extends CommonQueryContract {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Covariant returns
- @Override
+ @Override @Deprecated(since = "7")
MutationQuery setFlushMode(FlushModeType flushMode);
- @Override
+ @Override @Deprecated(since = "7")
MutationQuery setHibernateFlushMode(FlushMode flushMode);
@Override
@@ -209,4 +208,7 @@ public interface MutationQuery extends CommonQueryContract {
@Override
MutationQuery setProperties(@SuppressWarnings("rawtypes") Map bean);
+
+ @Override
+ MutationQuery setQueryFlushMode(QueryFlushMode queryFlushMode);
}
diff --git a/hibernate-core/src/main/java/org/hibernate/query/NativeQuery.java b/hibernate-core/src/main/java/org/hibernate/query/NativeQuery.java
index 6e2ac20e5c..54aab000a9 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/NativeQuery.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/NativeQuery.java
@@ -554,10 +554,13 @@ public interface NativeQuery extends Query, SynchronizeableQuery {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// covariant overrides - Query
- @Override
+ @Override @Deprecated(since = "7")
NativeQuery setHibernateFlushMode(FlushMode flushMode);
@Override
+ NativeQuery setQueryFlushMode(QueryFlushMode queryFlushMode);
+
+ @Override @Deprecated(since = "7")
NativeQuery setFlushMode(FlushModeType flushMode);
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/query/Query.java b/hibernate-core/src/main/java/org/hibernate/query/Query.java
index ba82fa6d2b..6cf35124cb 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/Query.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/Query.java
@@ -851,9 +851,12 @@ public interface Query extends SelectionQuery, MutationQuery, TypedQuery setHibernateFlushMode(FlushMode flushMode);
+ @Override
+ Query setQueryFlushMode(QueryFlushMode queryFlushMode);
+
@Override
Query setCacheable(boolean cacheable);
@@ -914,7 +917,7 @@ public interface Query extends SelectionQuery, MutationQuery, TypedQuery disableFetchProfile(String profileName);
- @Override
+ @Override @Deprecated(since = "7")
Query setFlushMode(FlushModeType flushMode);
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/query/QueryFlushMode.java b/hibernate-core/src/main/java/org/hibernate/query/QueryFlushMode.java
new file mode 100644
index 0000000000..46b919b7db
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/query/QueryFlushMode.java
@@ -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 .
+ */
+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
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/query/SelectionQuery.java b/hibernate-core/src/main/java/org/hibernate/query/SelectionQuery.java
index 5bdd7eff2d..b79789a453 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/SelectionQuery.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/SelectionQuery.java
@@ -295,12 +295,15 @@ public interface SelectionQuery extends CommonQueryContract {
*/
SelectionQuery disableFetchProfile(String profileName);
- @Override
+ @Override @Deprecated(since = "7")
SelectionQuery setFlushMode(FlushModeType flushMode);
- @Override
+ @Override @Deprecated(since = "7")
SelectionQuery setHibernateFlushMode(FlushMode flushMode);
+ @Override
+ SelectionQuery setQueryFlushMode(QueryFlushMode queryFlushMode);
+
@Override
SelectionQuery setTimeout(int timeout);
@@ -421,14 +424,13 @@ public interface SelectionQuery extends CommonQueryContract {
* the query inherits the {@link CacheMode} of the session from which
* it originates.
*
- * The {@link CacheMode} here describes reading-from/writing-to the
- * entity/collection caches as we process query results. For caching
- * of the actual query results, see {@link #isCacheable()} and
- * {@link #getCacheRegion()}
+ * The {@link CacheMode} here affects the use of entity and collection
+ * caches as the query result set is processed. For caching of the actual
+ * query results, use {@link #isCacheable()} and {@link #getCacheRegion()}.
*
* In order for this setting to have any affect, second-level caching
- * would have to be enabled and the entities/collections in question
- * configured for caching.
+ * must be enabled and the entities and collections must be eligible
+ * for storage in the second-level cache.
*
* @see Session#getCacheMode()
*/
@@ -450,9 +452,9 @@ public interface SelectionQuery extends CommonQueryContract {
/**
* Set the current {@link CacheMode} in effect for this query.
- *
- * @implNote Setting it to {@code null} ultimately indicates to use the
- * {@code CacheMode} of the session.
+ *
+ * Set it to {@code null} to indicate that the {@code CacheMode}
+ * of the {@link Session#getCacheMode() session} should be used.
*
* @see #getCacheMode()
* @see Session#setCacheMode(CacheMode)
diff --git a/hibernate-core/src/main/java/org/hibernate/query/hql/spi/SqmQueryImplementor.java b/hibernate-core/src/main/java/org/hibernate/query/hql/spi/SqmQueryImplementor.java
index 48ccfd244d..e2229853bd 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/hql/spi/SqmQueryImplementor.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/hql/spi/SqmQueryImplementor.java
@@ -14,6 +14,7 @@ import java.util.Map;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
+import org.hibernate.query.QueryFlushMode;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.graph.GraphSemantic;
@@ -104,9 +105,12 @@ public interface SqmQueryImplementor extends QueryImplementor, SqmQuery, N
return setTupleTransformer( transformer ).setResultListTransformer( transformer );
}
- @Override
+ @Override @Deprecated(since = "7")
SqmQueryImplementor setHibernateFlushMode(FlushMode flushMode);
+ @Override
+ SqmQueryImplementor setQueryFlushMode(QueryFlushMode queryFlushMode);
+
@Override
SqmQueryImplementor setMaxResults(int maxResult);
@@ -116,7 +120,7 @@ public interface SqmQueryImplementor extends QueryImplementor, SqmQuery, N
@Override
SqmQueryImplementor setHint(String hintName, Object value);
- @Override
+ @Override @Deprecated(since = "7")
SqmQueryImplementor setFlushMode(FlushModeType flushMode);
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java b/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java
index 4ad3c56f15..2071d2b31e 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java
@@ -17,6 +17,7 @@ import java.util.Set;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
+import org.hibernate.query.QueryFlushMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
@@ -178,7 +179,7 @@ public abstract class AbstractCommonQueryContract implements CommonQueryContract
}
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_FETCH_SIZE, getQueryOptions().getFetchSize() );
@@ -521,7 +522,8 @@ public abstract class AbstractCommonQueryContract implements CommonQueryContract
@Override
public FlushMode getHibernateFlushMode() {
- return getQueryOptions().getFlushMode();
+ final FlushMode flushMode = getQueryOptions().getFlushMode();
+ return flushMode == null ? getSession().getHibernateFlushMode() : flushMode;
}
@Override
@@ -530,6 +532,17 @@ public abstract class AbstractCommonQueryContract implements CommonQueryContract
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) {
getQueryOptions().setCacheRetrieveMode( retrieveMode );
return true;
diff --git a/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractQuery.java b/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractQuery.java
index 5bf155f2ac..ab954dbfa8 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractQuery.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractQuery.java
@@ -27,6 +27,7 @@ import jakarta.persistence.TemporalType;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
+import org.hibernate.query.QueryFlushMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
@@ -194,18 +195,21 @@ public abstract class AbstractQuery
return this;
}
+ @Override
+ public QueryImplementor setQueryFlushMode(QueryFlushMode queryFlushMode) {
+ super.setQueryFlushMode(queryFlushMode);
+ return this;
+ }
+
@Override
public FlushModeType getFlushMode() {
- getSession().checkOpen();
- final FlushMode flushMode = getQueryOptions().getFlushMode() == null
- ? getSession().getHibernateFlushMode()
- : getQueryOptions().getFlushMode();
- return FlushModeTypeHelper.getFlushModeType( flushMode );
+// getSession().checkOpen();
+ return FlushModeTypeHelper.getFlushModeType( getHibernateFlushMode() );
}
@Override
public QueryImplementor setFlushMode(FlushModeType flushModeType) {
- getSession().checkOpen();
+// getSession().checkOpen();
setHibernateFlushMode( FlushModeTypeHelper.getFlushMode( flushModeType ) );
return this;
}
@@ -366,7 +370,7 @@ public abstract class AbstractQuery
putIfNotNull( hints, HINT_COMMENT, getComment() );
putIfNotNull( hints, HINT_FETCH_SIZE, getQueryOptions().getFetchSize() );
- putIfNotNull( hints, HINT_FLUSH_MODE, getHibernateFlushMode() );
+ putIfNotNull( hints, HINT_FLUSH_MODE, getQueryOptions().getFlushMode() );
if ( getCacheMode() != null ) {
putIfNotNull( hints, HINT_CACHE_MODE, getCacheMode() );
diff --git a/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractSelectionQuery.java b/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractSelectionQuery.java
index ebf4653eed..dddfbb81e5 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractSelectionQuery.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractSelectionQuery.java
@@ -20,6 +20,7 @@ import java.util.stream.StreamSupport;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
+import org.hibernate.query.QueryFlushMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
@@ -31,6 +32,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.graph.GraphSemantic;
import org.hibernate.graph.spi.AppliedGraph;
import org.hibernate.graph.spi.RootGraphImplementor;
+import org.hibernate.jpa.internal.util.FlushModeTypeHelper;
import org.hibernate.jpa.internal.util.LockModeTypeHelper;
import org.hibernate.query.BindableType;
import org.hibernate.query.IllegalQueryOperationException;
@@ -52,7 +54,6 @@ import jakarta.persistence.TemporalType;
import static java.util.Spliterators.spliteratorUnknownSize;
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_STORE_MODE;
import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_RETRIEVE_MODE;
@@ -167,7 +168,7 @@ public abstract class AbstractSelectionQuery
assert sessionFlushMode == null;
assert sessionCacheMode == null;
- final FlushMode effectiveFlushMode = getHibernateFlushMode();
+ final FlushMode effectiveFlushMode = getQueryOptions().getFlushMode();
if ( effectiveFlushMode != null ) {
sessionFlushMode = session.getHibernateFlushMode();
session.setHibernateFlushMode( effectiveFlushMode );
@@ -333,12 +334,12 @@ public abstract class AbstractSelectionQuery
@Override
public FlushModeType getFlushMode() {
- return getQueryOptions().getFlushMode().toJpaFlushMode();
+ return FlushModeTypeHelper.getFlushModeType( getHibernateFlushMode() );
}
@Override
public SelectionQuery setFlushMode(FlushModeType flushMode) {
- getQueryOptions().setFlushMode( fromJpaFlushMode( flushMode ) );
+ getQueryOptions().setFlushMode( FlushModeTypeHelper.getFlushMode( flushMode ) );
return this;
}
@@ -566,6 +567,12 @@ public abstract class AbstractSelectionQuery
return this;
}
+ @Override
+ public SelectionQuery setQueryFlushMode(QueryFlushMode queryFlushMode) {
+ super.setQueryFlushMode(queryFlushMode);
+ return this;
+ }
+
@Override
public SelectionQuery setTimeout(int timeout) {
super.setTimeout( timeout );
diff --git a/hibernate-core/src/main/java/org/hibernate/query/spi/SqmQuery.java b/hibernate-core/src/main/java/org/hibernate/query/spi/SqmQuery.java
index 4c3a09850d..580f953c63 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/spi/SqmQuery.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/spi/SqmQuery.java
@@ -13,6 +13,7 @@ import java.util.Date;
import java.util.Map;
import org.hibernate.FlushMode;
+import org.hibernate.query.QueryFlushMode;
import org.hibernate.query.BindableType;
import org.hibernate.query.CommonQueryContract;
import org.hibernate.query.ParameterMetadata;
@@ -151,6 +152,9 @@ public interface SqmQuery extends CommonQueryContract {
@Override
SqmQuery setProperties(@SuppressWarnings("rawtypes") Map bean);
- @Override
+ @Override @Deprecated(since = "7")
SqmQuery setHibernateFlushMode(FlushMode flushMode);
+
+ @Override
+ SqmQuery setQueryFlushMode(QueryFlushMode queryFlushMode);
}
diff --git a/hibernate-core/src/main/java/org/hibernate/query/sql/internal/NativeQueryImpl.java b/hibernate-core/src/main/java/org/hibernate/query/sql/internal/NativeQueryImpl.java
index 80fde787f0..6eb5bad550 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/sql/internal/NativeQueryImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/sql/internal/NativeQueryImpl.java
@@ -22,6 +22,7 @@ import java.util.function.Supplier;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
+import org.hibernate.query.QueryFlushMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
@@ -55,7 +56,6 @@ import org.hibernate.query.TupleTransformer;
import org.hibernate.query.internal.DelegatingDomainQueryExecutionContext;
import org.hibernate.query.internal.ParameterMetadataImpl;
import org.hibernate.query.internal.QueryOptionsImpl;
-import org.hibernate.query.internal.QueryParameterBindingsImpl;
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
import org.hibernate.query.named.NamedResultSetMappingMemento;
import org.hibernate.query.results.Builders;
@@ -469,7 +469,7 @@ public class NativeQueryImpl
isCacheable(),
getCacheRegion(),
getCacheMode(),
- getHibernateFlushMode(),
+ getQueryOptions().getFlushMode(),
isReadOnly(),
getTimeout(),
getFetchSize(),
@@ -607,7 +607,7 @@ public class NativeQueryImpl
private boolean shouldFlush() {
if ( getSession().isTransactionInProgress() ) {
- FlushMode effectiveFlushMode = getHibernateFlushMode();
+ FlushMode effectiveFlushMode = getQueryOptions().getFlushMode();
if ( effectiveFlushMode == null ) {
effectiveFlushMode = getSession().getHibernateFlushMode();
}
@@ -1180,6 +1180,12 @@ public class NativeQueryImpl
return this;
}
+ @Override
+ public NativeQueryImplementor setQueryFlushMode(QueryFlushMode queryFlushMode) {
+ super.setQueryFlushMode(queryFlushMode);
+ return this;
+ }
+
@Override
public NativeQueryImplementor setFlushMode(FlushModeType flushModeType) {
super.setFlushMode( flushModeType );
diff --git a/hibernate-core/src/main/java/org/hibernate/query/sql/spi/NativeQueryImplementor.java b/hibernate-core/src/main/java/org/hibernate/query/sql/spi/NativeQueryImplementor.java
index 5f2150e040..73f166f48b 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/sql/spi/NativeQueryImplementor.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/sql/spi/NativeQueryImplementor.java
@@ -14,6 +14,7 @@ import java.util.Map;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
+import org.hibernate.query.QueryFlushMode;
import org.hibernate.Incubating;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
@@ -148,10 +149,13 @@ public interface NativeQueryImplementor extends QueryImplementor, NativeQu
@Override
NativeQueryImplementor setHint(String hintName, Object value);
- @Override
+ @Override @Deprecated(since = "7")
NativeQueryImplementor setHibernateFlushMode(FlushMode flushMode);
@Override
+ NativeQueryImplementor setQueryFlushMode(QueryFlushMode queryFlushMode);
+
+ @Override @Deprecated(since = "7")
NativeQueryImplementor setFlushMode(FlushModeType flushMode);
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmSelectionQuery.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmSelectionQuery.java
index 0b5c20144e..677d569f98 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmSelectionQuery.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmSelectionQuery.java
@@ -14,6 +14,7 @@ import java.util.Map;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
+import org.hibernate.query.QueryFlushMode;
import org.hibernate.query.BindableType;
import org.hibernate.query.QueryParameter;
import org.hibernate.query.SelectionQuery;
@@ -141,9 +142,12 @@ public interface SqmSelectionQuery extends SqmQuery, SelectionQuery {
@Override
SqmSelectionQuery setProperties(@SuppressWarnings("rawtypes") Map bean);
- @Override
+ @Override @Deprecated(since = "7")
SqmSelectionQuery setHibernateFlushMode(FlushMode flushMode);
+ @Override
+ SqmSelectionQuery setQueryFlushMode(QueryFlushMode queryFlushMode);
+
@Override
SqmSelectionQuery setCacheMode(CacheMode cacheMode);
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 0851508cdf..037b89a31a 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
@@ -21,6 +21,7 @@ import java.util.function.Supplier;
import jakarta.persistence.EntityGraph;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
+import org.hibernate.query.QueryFlushMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
@@ -35,8 +36,6 @@ import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.id.BulkInsertionCapableIdentifierGenerator;
import org.hibernate.id.OptimizableGenerator;
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.internal.SingleAttributeIdentifierMapping;
import org.hibernate.metamodel.model.domain.EntityDomainType;
@@ -123,7 +122,6 @@ import static org.hibernate.query.sqm.internal.SqmUtil.verifyIsNonSelectStatemen
public class QuerySqmImpl
extends AbstractSqmSelectionQuery
implements SqmQueryImplementor, InterpretationsKeySource, DomainQueryExecutionContext {
- private static final CoreMessageLogger LOG = CoreLogging.messageLogger( QuerySqmImpl.class );
private final String hql;
private SqmStatement sqm;
@@ -733,6 +731,12 @@ public class QuerySqmImpl
return this;
}
+ @Override
+ public SqmQueryImplementor setQueryFlushMode(QueryFlushMode queryFlushMode) {
+ super.setQueryFlushMode(queryFlushMode);
+ return this;
+ }
+
@Override
public SqmQueryImplementor setFlushMode(FlushModeType flushMode) {
applyJpaFlushMode( flushMode );
@@ -909,7 +913,7 @@ public class QuerySqmImpl
isCacheable(),
getCacheRegion(),
getCacheMode(),
- getHibernateFlushMode(),
+ getQueryOptions().getFlushMode(),
isReadOnly(),
getLockOptions(),
getTimeout(),
@@ -929,7 +933,7 @@ public class QuerySqmImpl
isCacheable(),
getCacheRegion(),
getCacheMode(),
- getHibernateFlushMode(),
+ getQueryOptions().getFlushMode(),
isReadOnly(),
getLockOptions(),
getTimeout(),
diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmSelectionQueryImpl.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmSelectionQueryImpl.java
index 67921591cd..a493fd62df 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmSelectionQueryImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmSelectionQueryImpl.java
@@ -24,6 +24,7 @@ import jakarta.persistence.TemporalType;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
+import org.hibernate.query.QueryFlushMode;
import org.hibernate.LockMode;
import org.hibernate.ScrollMode;
import org.hibernate.engine.spi.LoadQueryInfluencers;
@@ -551,6 +552,12 @@ public class SqmSelectionQueryImpl extends AbstractSqmSelectionQuery
return this;
}
+ @Override
+ public SqmSelectionQuery setQueryFlushMode(QueryFlushMode queryFlushMode) {
+ super.setQueryFlushMode(queryFlushMode);
+ return this;
+ }
+
@Override
public SqmSelectionQuery setTimeout(int timeout) {
super.setTimeout( timeout );
diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/spi/DelegatingSqmSelectionQueryImplementor.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/spi/DelegatingSqmSelectionQueryImplementor.java
index bbd39da456..1c5ba392e9 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/sqm/spi/DelegatingSqmSelectionQueryImplementor.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/spi/DelegatingSqmSelectionQueryImplementor.java
@@ -29,8 +29,10 @@ import org.hibernate.query.KeyedResultList;
import org.hibernate.query.Order;
import org.hibernate.query.Page;
import org.hibernate.query.ParameterMetadata;
+import org.hibernate.query.QueryFlushMode;
import org.hibernate.query.QueryParameter;
import org.hibernate.query.spi.QueryOptions;
+import org.hibernate.query.sqm.SqmSelectionQuery;
import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.sql.results.spi.ResultsConsumer;
@@ -63,6 +65,16 @@ public abstract class DelegatingSqmSelectionQueryImplementor implements SqmSe
return getDelegate().getHibernateFlushMode();
}
+ @Override
+ public QueryFlushMode getQueryFlushMode() {
+ return getDelegate().getQueryFlushMode();
+ }
+
+ @Override
+ public SqmSelectionQuery setQueryFlushMode(QueryFlushMode queryFlushMode) {
+ return getDelegate().setQueryFlushMode( queryFlushMode );
+ }
+
@Override
public Integer getTimeout() {
return getDelegate().getTimeout();
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/query/NamedQueryFlushModeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/query/NamedQueryFlushModeTest.java
index 8eb01a25c4..ded24d9660 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/query/NamedQueryFlushModeTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/query/NamedQueryFlushModeTest.java
@@ -25,7 +25,6 @@ import org.hibernate.testing.orm.junit.Jpa;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
/**
* @author Yoann Rodiere
@@ -103,22 +102,22 @@ public class NamedQueryFlushModeTest {
s.setHibernateFlushMode( FlushMode.MANUAL );
query = s.getNamedQuery( queryName );
- assertNull( query.getHibernateFlushMode() );
+ assertEquals( FlushMode.MANUAL, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.COMMIT, query.getFlushMode() );
s.setHibernateFlushMode( FlushMode.COMMIT );
query = s.getNamedQuery( queryName );
- assertNull( query.getHibernateFlushMode() );
+ assertEquals( FlushMode.COMMIT, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.COMMIT, query.getFlushMode() );
s.setHibernateFlushMode( FlushMode.AUTO );
query = s.getNamedQuery( queryName );
- assertNull( query.getHibernateFlushMode() );
+ assertEquals( FlushMode.AUTO, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.AUTO, query.getFlushMode() );
s.setHibernateFlushMode( FlushMode.ALWAYS );
query = s.getNamedQuery( queryName );
- assertNull( query.getHibernateFlushMode() );
+ assertEquals( FlushMode.ALWAYS, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.AUTO, query.getFlushMode() );
}
);
@@ -185,22 +184,22 @@ public class NamedQueryFlushModeTest {
s.setHibernateFlushMode( FlushMode.MANUAL );
query = s.getNamedNativeQuery( queryName );
- assertNull( query.getHibernateFlushMode() );
+ assertEquals( FlushMode.MANUAL, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.COMMIT, query.getFlushMode() );
s.setHibernateFlushMode( FlushMode.COMMIT );
query = s.getNamedNativeQuery( queryName );
- assertNull( query.getHibernateFlushMode() );
+ assertEquals( FlushMode.COMMIT, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.COMMIT, query.getFlushMode() );
s.setHibernateFlushMode( FlushMode.AUTO );
query = s.getNamedNativeQuery( queryName );
- assertNull( query.getHibernateFlushMode() );
+ assertEquals( FlushMode.AUTO, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.AUTO, query.getFlushMode() );
s.setHibernateFlushMode( FlushMode.ALWAYS );
query = s.getNamedNativeQuery( queryName );
- assertNull( query.getHibernateFlushMode() );
+ assertEquals( FlushMode.ALWAYS, query.getHibernateFlushMode() );
assertEquals( jakarta.persistence.FlushModeType.AUTO, query.getFlushMode() );
}
);
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/query/NamedQueryQueryFlushModeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/query/NamedQueryQueryFlushModeTest.java
new file mode 100644
index 0000000000..a6e1644bd5
--- /dev/null
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/query/NamedQueryQueryFlushModeTest.java
@@ -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 .
+ */
+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;
+ }
+ }
+}