Skip to content

Commit 52e185b

Browse files
committed
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
1 parent 5f8bf12 commit 52e185b

30 files changed

+642
-95
lines changed

hibernate-core/src/main/java/org/hibernate/FlushMode.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,16 @@
1818
* <p>
1919
* For example, {@link #COMMIT} specifies that the session flushes
2020
* automatically when the transaction is about to commit.
21+
* <p>
22+
* This enumeration represents options which may be
23+
* {@linkplain Session#setHibernateFlushMode set at the session
24+
* level}, and competes with the JPA-defined enumeration
25+
* {@link jakarta.persistence.FlushModeType}. Alternatively, a
26+
* {@link org.hibernate.query.QueryFlushMode QueryFlushMode} may
27+
* be specified for a given query.
2128
*
2229
* @see Session#setHibernateFlushMode
23-
* @see org.hibernate.query.CommonQueryContract#setHibernateFlushMode
30+
* @see org.hibernate.query.QueryFlushMode
2431
*
2532
* @author Gavin King
2633
*/

hibernate-core/src/main/java/org/hibernate/Session.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ public interface Session extends SharedSessionContract, EntityManager {
199199
void flush();
200200

201201
/**
202-
* Set the current {@link FlushModeType JPA flush mode} for this session.
202+
* Set the current {@linkplain FlushModeType JPA flush mode} for this session.
203203
* <p>
204204
* <em>Flushing</em> is the process of synchronizing the underlying persistent
205205
* store with persistable state held in memory. The current flush mode determines

hibernate-core/src/main/java/org/hibernate/annotations/FlushModeType.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
*/
77
package org.hibernate.annotations;
88

9+
import org.hibernate.query.QueryFlushMode;
10+
911
/**
1012
* Enumeration extending the {@linkplain jakarta.persistence.FlushModeType JPA flush modes}
1113
* with flush modes specific to Hibernate, and a "null" mode, {@link #PERSISTENCE_CONTEXT},
@@ -14,9 +16,12 @@
1416
*
1517
* @author Carlos Gonzalez-Cadenas
1618
*
17-
* @see NamedQuery
18-
* @see NamedNativeQuery
19+
* @see NamedQuery#flushMode
20+
* @see NamedNativeQuery#flushMode
21+
*
22+
* @deprecated use {@link QueryFlushMode}
1923
*/
24+
@Deprecated(since="7")
2025
public enum FlushModeType {
2126
/**
2227
* Corresponds to {@link org.hibernate.FlushMode#ALWAYS}.

hibernate-core/src/main/java/org/hibernate/annotations/NamedNativeQuery.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import jakarta.persistence.CacheRetrieveMode;
1414
import jakarta.persistence.CacheStoreMode;
1515
import org.hibernate.CacheMode;
16+
import org.hibernate.query.QueryFlushMode;
1617

1718
import static java.lang.annotation.ElementType.PACKAGE;
1819
import static java.lang.annotation.ElementType.TYPE;
@@ -63,12 +64,25 @@
6364
*/
6465
String resultSetMapping() default "";
6566

67+
/**
68+
* Determines whether the session should be flushed before
69+
* executing the query.
70+
*
71+
* @see org.hibernate.query.CommonQueryContract#setQueryFlushMode(QueryFlushMode)
72+
*
73+
* @since 7.0
74+
*/
75+
QueryFlushMode flush() default QueryFlushMode.DEFAULT;
76+
6677
/**
6778
* The flush mode for the query.
6879
*
6980
* @see org.hibernate.query.CommonQueryContract#setFlushMode(jakarta.persistence.FlushModeType)
7081
* @see org.hibernate.jpa.HibernateHints#HINT_FLUSH_MODE
82+
*
83+
* @deprecated use {@link #flush()}
7184
*/
85+
@Deprecated(since = "7")
7286
FlushModeType flushMode() default FlushModeType.PERSISTENCE_CONTEXT;
7387

7488
/**

hibernate-core/src/main/java/org/hibernate/annotations/NamedQuery.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import jakarta.persistence.EntityManager;
1616

1717
import org.hibernate.CacheMode;
18+
import org.hibernate.query.QueryFlushMode;
1819

1920
import static java.lang.annotation.ElementType.PACKAGE;
2021
import static java.lang.annotation.ElementType.TYPE;
@@ -58,12 +59,25 @@
5859
*/
5960
Class<?> resultClass() default void.class;
6061

62+
/**
63+
* Determines whether the session should be flushed before
64+
* executing the query.
65+
*
66+
* @see org.hibernate.query.CommonQueryContract#setQueryFlushMode(QueryFlushMode)
67+
*
68+
* @since 7.0
69+
*/
70+
QueryFlushMode flush() default QueryFlushMode.DEFAULT;
71+
6172
/**
6273
* The flush mode for this query.
6374
*
6475
* @see org.hibernate.query.CommonQueryContract#setFlushMode(jakarta.persistence.FlushModeType)
6576
* @see org.hibernate.jpa.HibernateHints#HINT_FLUSH_MODE
77+
*
78+
* @deprecated use {@link #flush()}
6679
*/
80+
@Deprecated(since = "7")
6781
FlushModeType flushMode() default FlushModeType.PERSISTENCE_CONTEXT;
6882

6983
/**

hibernate-core/src/main/java/org/hibernate/boot/model/internal/QueryBinder.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import org.hibernate.AnnotationException;
1717
import org.hibernate.CacheMode;
1818
import org.hibernate.FlushMode;
19+
import org.hibernate.query.QueryFlushMode;
1920
import org.hibernate.LockOptions;
2021
import org.hibernate.annotations.FlushModeType;
2122
import org.hibernate.annotations.HQLSelect;
@@ -35,6 +36,7 @@
3536
import org.hibernate.internal.CoreMessageLogger;
3637
import org.hibernate.internal.log.DeprecationLogger;
3738
import org.hibernate.jpa.HibernateHints;
39+
import org.hibernate.jpa.internal.util.FlushModeTypeHelper;
3840
import org.hibernate.models.internal.util.StringHelper;
3941
import org.hibernate.models.spi.ClassDetails;
4042
import org.hibernate.models.spi.SourceModelBuildingContext;
@@ -271,7 +273,7 @@ private static <T> NamedNativeQueryDefinition.Builder<T> createQueryDefinition(
271273
.setCacheMode(getCacheMode(namedNativeQuery.cacheRetrieveMode(), namedNativeQuery.cacheStoreMode()))
272274
.setTimeout(timeout < 0 ? null : timeout)
273275
.setFetchSize(fetchSize < 0 ? null : fetchSize)
274-
.setFlushMode(getFlushMode(namedNativeQuery.flushMode()))
276+
.setFlushMode(getFlushMode(namedNativeQuery.flush(), namedNativeQuery.flushMode()))
275277
.setReadOnly(namedNativeQuery.readOnly())
276278
.setQuerySpaces(querySpaces)
277279
.setComment(nullIfEmpty(namedNativeQuery.comment()));
@@ -412,7 +414,7 @@ private static <T> NamedHqlQueryDefinition.Builder<T> createQueryDefinition(
412414
.setCacheMode(getCacheMode(namedQuery.cacheRetrieveMode(), namedQuery.cacheStoreMode()))
413415
.setTimeout(timeout < 0 ? null : timeout)
414416
.setFetchSize(fetchSize < 0 ? null : fetchSize)
415-
.setFlushMode(getFlushMode(namedQuery.flushMode()))
417+
.setFlushMode(getFlushMode(namedQuery.flush(), namedQuery.flushMode()))
416418
.setReadOnly(namedQuery.readOnly())
417419
.setComment(nullIfEmpty(namedQuery.comment()));
418420
}
@@ -422,6 +424,12 @@ private static CacheMode getCacheMode(CacheRetrieveMode cacheRetrieveMode, Cache
422424
return cacheMode == null ? CacheMode.NORMAL : cacheMode;
423425
}
424426

427+
private static FlushMode getFlushMode(QueryFlushMode queryFlushMode, FlushModeType flushModeType) {
428+
return queryFlushMode == QueryFlushMode.DEFAULT
429+
? getFlushMode( flushModeType )
430+
: FlushModeTypeHelper.getFlushMode(queryFlushMode);
431+
}
432+
425433
private static FlushMode getFlushMode(FlushModeType flushModeType) {
426434
return switch ( flushModeType ) {
427435
case ALWAYS -> FlushMode.ALWAYS;

hibernate-core/src/main/java/org/hibernate/boot/models/annotations/internal/NamedNativeQueryAnnotation.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import jakarta.persistence.CacheRetrieveMode;
2626
import jakarta.persistence.CacheStoreMode;
27+
import org.hibernate.query.QueryFlushMode;
2728

2829
@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" })
2930
@jakarta.annotation.Generated("org.hibernate.orm.build.annotations.ClassGeneratorProcessor")
@@ -33,6 +34,7 @@ public class NamedNativeQueryAnnotation implements NamedNativeQuery {
3334
private Class<?> resultClass;
3435
private String resultSetMapping;
3536
private FlushModeType flushMode;
37+
private QueryFlushMode flush;
3638
boolean cacheable;
3739
String cacheRegion;
3840
int fetchSize;
@@ -51,6 +53,7 @@ public NamedNativeQueryAnnotation(SourceModelBuildingContext modelContext) {
5153
resultClass = void.class;
5254
resultSetMapping = "";
5355
flushMode = FlushModeType.PERSISTENCE_CONTEXT;
56+
flush = QueryFlushMode.DEFAULT;
5457
cacheable = false;
5558
cacheRegion = "";
5659
fetchSize = -1;
@@ -72,6 +75,7 @@ public NamedNativeQueryAnnotation(NamedNativeQuery annotation, SourceModelBuildi
7275
this.resultClass = annotation.resultClass();
7376
this.resultSetMapping = annotation.resultSetMapping();
7477
this.flushMode = annotation.flushMode();
78+
this.flush = annotation.flush();
7579
this.cacheable = annotation.cacheable();
7680
this.cacheRegion = annotation.cacheRegion();
7781
this.fetchSize = annotation.fetchSize();
@@ -97,6 +101,7 @@ public NamedNativeQueryAnnotation(Map<String, Object> attributeValues, SourceMod
97101
this.resultClass = (Class<?>) attributeValues.get( "resultClass" );
98102
this.resultSetMapping = (String) attributeValues.get( "resultSetMapping" );
99103
this.flushMode = (FlushModeType) attributeValues.get( "flushMode" );
104+
this.flush = (QueryFlushMode) attributeValues.get( "flush" );
100105
this.cacheable = (boolean) attributeValues.get( "cacheable" );
101106
this.cacheRegion = (String) attributeValues.get( "cacheRegion" );
102107
this.fetchSize = (int) attributeValues.get( "fetchSize" );
@@ -152,6 +157,15 @@ public void resultSetMapping(String value) {
152157
this.resultSetMapping = value;
153158
}
154159

160+
@Override
161+
public QueryFlushMode flush() {
162+
return flush;
163+
}
164+
165+
public void flush(QueryFlushMode value) {
166+
this.flush = value;
167+
}
168+
155169
@Override
156170
public FlushModeType flushMode() {
157171
return flushMode;

hibernate-core/src/main/java/org/hibernate/boot/models/annotations/internal/NamedQueryAnnotation.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import jakarta.persistence.CacheRetrieveMode;
2121
import jakarta.persistence.CacheStoreMode;
22+
import org.hibernate.query.QueryFlushMode;
2223

2324
import static org.hibernate.boot.models.xml.internal.QueryProcessing.interpretFlushMode;
2425

@@ -29,6 +30,7 @@ public class NamedQueryAnnotation implements NamedQuery {
2930
private String query;
3031
private Class<?> resultClass;
3132
private FlushModeType flushMode;
33+
private QueryFlushMode flush;
3234
boolean cacheable;
3335
String cacheRegion;
3436
int fetchSize;
@@ -44,6 +46,7 @@ public class NamedQueryAnnotation implements NamedQuery {
4446
public NamedQueryAnnotation(SourceModelBuildingContext modelContext) {
4547
resultClass = void.class;
4648
flushMode = FlushModeType.PERSISTENCE_CONTEXT;
49+
flush = QueryFlushMode.DEFAULT;
4750
cacheable = false;
4851
cacheRegion = "";
4952
fetchSize = -1;
@@ -62,6 +65,7 @@ public NamedQueryAnnotation(NamedQuery annotation, SourceModelBuildingContext mo
6265
this.query = annotation.query();
6366
this.resultClass = annotation.resultClass();
6467
this.flushMode = annotation.flushMode();
68+
this.flush = annotation.flush();
6569
this.cacheable = annotation.cacheable();
6670
this.cacheRegion = annotation.cacheRegion();
6771
this.fetchSize = annotation.fetchSize();
@@ -84,6 +88,7 @@ public NamedQueryAnnotation(Map<String, Object> attributeValues, SourceModelBuil
8488
this.query = (String) attributeValues.get( "query" );
8589
this.resultClass = (Class<?>) attributeValues.get( "resultClass" );
8690
this.flushMode = (FlushModeType) attributeValues.get( "flushMode" );
91+
this.flush = (QueryFlushMode) attributeValues.get( "flush" );
8792
this.cacheable = (boolean) attributeValues.get( "cacheable" );
8893
this.cacheRegion = (String) attributeValues.get( "cacheRegion" );
8994
this.fetchSize = (int) attributeValues.get( "fetchSize" );
@@ -128,6 +133,15 @@ public void resultClass(Class<?> value) {
128133
this.resultClass = value;
129134
}
130135

136+
@Override
137+
public QueryFlushMode flush() {
138+
return flush;
139+
}
140+
141+
public void flush(QueryFlushMode value) {
142+
this.flush = value;
143+
}
144+
131145
@Override
132146
public FlushModeType flushMode() {
133147
return flushMode;

hibernate-core/src/main/java/org/hibernate/jpa/internal/util/FlushModeTypeHelper.java

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
import java.util.Locale;
1111
import jakarta.persistence.FlushModeType;
1212

13-
import org.hibernate.AssertionFailure;
1413
import org.hibernate.FlushMode;
14+
import org.hibernate.query.QueryFlushMode;
1515
import org.hibernate.MappingException;
1616

1717
import org.jboss.logging.Logger;
@@ -28,35 +28,55 @@ private FlushModeTypeHelper() {
2828
}
2929

3030
public static FlushModeType getFlushModeType(FlushMode flushMode) {
31-
if ( flushMode == FlushMode.ALWAYS ) {
32-
log.debug( "Interpreting Hibernate FlushMode#ALWAYS to JPA FlushModeType#AUTO; may cause problems if relying on FlushMode#ALWAYS-specific behavior" );
33-
return FlushModeType.AUTO;
34-
}
35-
else if ( flushMode == FlushMode.MANUAL ) {
36-
log.debug( "Interpreting Hibernate FlushMode#MANUAL to JPA FlushModeType#COMMIT; may cause problems if relying on FlushMode#MANUAL-specific behavior" );
37-
return FlushModeType.COMMIT;
38-
}
39-
else if ( flushMode == FlushMode.COMMIT ) {
40-
return FlushModeType.COMMIT;
41-
}
42-
else if ( flushMode == FlushMode.AUTO ) {
43-
return FlushModeType.AUTO;
44-
}
45-
else {
46-
throw new AssertionFailure( "unhandled FlushMode " + flushMode );
31+
if ( flushMode == null ) {
32+
return null;
4733
}
34+
return switch (flushMode) {
35+
case ALWAYS -> {
36+
log.debug("Interpreting Hibernate FlushMode.ALWAYS as JPA FlushModeType.AUTO (may cause problems if relying on FlushMode.ALWAYS-specific behavior)");
37+
yield FlushModeType.AUTO;
38+
}
39+
case MANUAL -> {
40+
log.debug("Interpreting Hibernate FlushMode.MANUAL as JPA FlushModeType.COMMIT (may cause problems if relying on FlushMode.MANUAL-specific behavior)");
41+
yield FlushModeType.COMMIT;
42+
}
43+
case COMMIT -> FlushModeType.COMMIT;
44+
case AUTO -> FlushModeType.AUTO;
45+
};
46+
}
47+
48+
public static QueryFlushMode getForcedFlushMode(FlushMode flushMode) {
49+
if ( flushMode == null ) {
50+
return QueryFlushMode.DEFAULT;
51+
}
52+
return switch (flushMode) {
53+
case ALWAYS -> QueryFlushMode.FLUSH;
54+
case COMMIT, MANUAL -> QueryFlushMode.NO_FLUSH;
55+
case AUTO ->
56+
// this is not precisely correctly correct, but good enough
57+
QueryFlushMode.DEFAULT;
58+
};
4859
}
4960

5061
public static FlushMode getFlushMode(FlushModeType flushModeType) {
51-
if ( flushModeType == FlushModeType.AUTO ) {
52-
return FlushMode.AUTO;
53-
}
54-
else if ( flushModeType == FlushModeType.COMMIT ) {
55-
return FlushMode.COMMIT;
62+
if ( flushModeType == null ) {
63+
return null;
5664
}
57-
else {
58-
throw new AssertionFailure( "unhandled FlushModeType " + flushModeType );
65+
return switch (flushModeType) {
66+
case AUTO -> FlushMode.AUTO;
67+
case COMMIT -> FlushMode.COMMIT;
68+
};
69+
}
70+
71+
public static FlushMode getFlushMode(QueryFlushMode queryFlushMode) {
72+
if ( queryFlushMode == null ) {
73+
return null;
5974
}
75+
return switch (queryFlushMode) {
76+
case FLUSH -> FlushMode.ALWAYS;
77+
case NO_FLUSH -> FlushMode.MANUAL;
78+
default -> null;
79+
};
6080
}
6181

6282
public static FlushMode interpretFlushMode(Object value) {

hibernate-core/src/main/java/org/hibernate/procedure/ProcedureCall.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ default void close() {
281281
@Override
282282
ProcedureCall setParameter(int position, Date value, TemporalType temporalType);
283283

284-
@Override
284+
@Override @Deprecated(since = "7")
285285
ProcedureCall setFlushMode(FlushModeType flushMode);
286286

287287
@Override

0 commit comments

Comments
 (0)