Skip to content

Commit c0c628f

Browse files
committed
HHH-17188 Eagerly select values when query cache is enabled
1 parent c84a30c commit c0c628f

File tree

8 files changed

+66
-3
lines changed

8 files changed

+66
-3
lines changed

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/CompoundNaturalIdMapping.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,13 @@ public Object[] assemble(
668668
return result;
669669
}
670670

671+
@Override
672+
public void resolveState(RowProcessingState rowProcessingState) {
673+
for ( DomainResultAssembler<?> subAssembler : subAssemblers ) {
674+
subAssembler.resolveState( rowProcessingState );
675+
}
676+
}
677+
671678
@Override
672679
public JavaType<Object[]> getAssembledJavaType() {
673680
return jtd;

hibernate-core/src/main/java/org/hibernate/sql/results/graph/DomainResultAssembler.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,12 @@ default J assemble(RowProcessingState rowProcessingState) {
3838
* assembles.
3939
*/
4040
JavaType<J> getAssembledJavaType();
41+
42+
/**
43+
* This method is used to resolve the assembler's state, i.e. reading the result values,
44+
* with some performance optimization when we don't need the result object itself
45+
*/
46+
default void resolveState(RowProcessingState rowProcessingState) {
47+
assemble( rowProcessingState );
48+
}
4149
}

hibernate-core/src/main/java/org/hibernate/sql/results/graph/basic/BasicResultAssembler.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ public J assemble(
8484
return (J) jdbcValue;
8585
}
8686

87+
@Override
88+
public void resolveState(RowProcessingState rowProcessingState) {
89+
extractRawValue( rowProcessingState );
90+
}
91+
8792
@Override
8893
public JavaType<J> getAssembledJavaType() {
8994
if ( valueConverter != null ) {

hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/AbstractEmbeddableInitializer.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,15 @@ else if ( isPartOfKey ) {
323323
state = stateAllNull ? State.NULL : State.EXTRACTED;
324324
}
325325

326+
@Override
327+
public void resolveState(RowProcessingState rowProcessingState) {
328+
if ( determinInitialState() == State.INITIAL ) {
329+
for ( final DomainResultAssembler<?> assembler : assemblers ) {
330+
assembler.resolveState( rowProcessingState );
331+
}
332+
}
333+
}
334+
326335
private Object createCompositeInstance(NavigablePath navigablePath, SessionFactoryImplementor sessionFactory) {
327336
if ( state == State.NULL ) {
328337
// todo (6.0) : should we initialize the composite instance if it has a parent attribute?

hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/EmbeddableInitializer.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,6 @@ default boolean isEmbeddableInitializer() {
4848
default EmbeddableInitializer asEmbeddableInitializer() {
4949
return this;
5050
}
51+
52+
void resolveState(RowProcessingState rowProcessingState);
5153
}

hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/AbstractNonAggregatedIdentifierMappingInitializer.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.hibernate.sql.results.graph.FetchParentAccess;
2929
import org.hibernate.sql.results.graph.Fetchable;
3030
import org.hibernate.sql.results.graph.Initializer;
31+
import org.hibernate.sql.results.graph.embeddable.AbstractEmbeddableInitializer;
3132
import org.hibernate.sql.results.graph.embeddable.EmbeddableInitializer;
3233
import org.hibernate.sql.results.graph.embeddable.EmbeddableLoadingLogger;
3334
import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode;
@@ -158,9 +159,7 @@ public void initializeInstance(RowProcessingState processingState) {
158159
return;
159160
case INITIAL:
160161
// If we don't have an id class and this is a find by id lookup, we just use that instance
161-
if ( !hasIdClass && processingState.getEntityId() != null
162-
&& navigablePath.getParent().getParent() == null
163-
&& navigablePath instanceof EntityIdentifierNavigablePath ) {
162+
if ( isFindByIdLookup( processingState ) ) {
164163
compositeInstance = processingState.getEntityId();
165164
state = State.INJECTED;
166165
return;
@@ -216,6 +215,12 @@ public void initializeInstance(RowProcessingState processingState) {
216215
}
217216
}
218217

218+
private boolean isFindByIdLookup(RowProcessingState processingState) {
219+
return !hasIdClass && processingState.getEntityId() != null
220+
&& navigablePath.getParent().getParent() == null
221+
&& navigablePath instanceof EntityIdentifierNavigablePath;
222+
}
223+
219224
private void extractRowState(RowProcessingState processingState) {
220225
state = State.NULL;
221226
for ( int i = 0; i < assemblers.length; i++ ) {
@@ -256,6 +261,15 @@ private void extractRowState(RowProcessingState processingState) {
256261
state = State.EXTRACTED;
257262
}
258263

264+
@Override
265+
public void resolveState(RowProcessingState rowProcessingState) {
266+
if ( !isFindByIdLookup( rowProcessingState ) ) {
267+
for ( final DomainResultAssembler<?> assembler : assemblers ) {
268+
assembler.resolveState( rowProcessingState );
269+
}
270+
}
271+
}
272+
259273
@Override
260274
public Object[] getValues() {
261275
return state == State.NULL ? null : idClassState;

hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableAssembler.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,10 @@ public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourcePr
3535
return initializer.getCompositeInstance();
3636
}
3737

38+
@Override
39+
public void resolveState(RowProcessingState rowProcessingState) {
40+
// use resolveState instead of initialize instance to avoid
41+
// unneeded embeddable instantiation and injection
42+
initializer.resolveState( rowProcessingState );
43+
}
3844
}

hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractEntityInitializer.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,10 @@ protected void resolveEntityInstance(
517517
this.isInitialized = true;
518518
registerReloadedEntity( rowProcessingState, existingEntity );
519519
notifyResolutionListeners( entityInstance );
520+
if ( rowProcessingState.getQueryOptions().isResultCachingEnabled() == Boolean.TRUE ) {
521+
// We still need to read result set values to correctly populate the query cache
522+
resolveState( rowProcessingState );
523+
}
520524
}
521525
else {
522526
registerLoadingEntityInstanceFromExecutionContext( rowProcessingState, entityInstance );
@@ -1062,6 +1066,14 @@ protected Object[] extractConcreteTypeStateValues(RowProcessingState rowProcessi
10621066
return values;
10631067
}
10641068

1069+
private void resolveState(RowProcessingState rowProcessingState) {
1070+
for ( final DomainResultAssembler<?> assembler : assemblers[concreteDescriptor.getSubclassId()] ) {
1071+
if ( assembler != null ) {
1072+
assembler.resolveState( rowProcessingState );
1073+
}
1074+
}
1075+
}
1076+
10651077
protected boolean skipInitialization(Object toInitialize, RowProcessingState rowProcessingState) {
10661078
if ( !isOwningInitializer ) {
10671079
return true;

0 commit comments

Comments
 (0)