Skip to content

Commit bf69471

Browse files
committed
HHH-18506 Reduce itable stubs during dirty checking
1 parent 4c124cd commit bf69471

File tree

3 files changed

+77
-1
lines changed

3 files changed

+77
-1
lines changed

hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3921,7 +3921,7 @@ public boolean isSubclassPropertyNullable(int i) {
39213921
public int[] findDirty(Object[] currentState, Object[] previousState, Object entity, SharedSessionContractImplementor session)
39223922
throws HibernateException {
39233923
int[] props = DirtyHelper.findDirty(
3924-
entityMetamodel.getProperties(),
3924+
entityMetamodel.getDirtyCheckablePropertyTypes(),
39253925
currentState,
39263926
previousState,
39273927
propertyColumnUpdateable,

hibernate-core/src/main/java/org/hibernate/persister/entity/DirtyHelper.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@
1111
import org.hibernate.engine.spi.SharedSessionContractImplementor;
1212
import org.hibernate.internal.util.collections.ArrayHelper;
1313
import org.hibernate.tuple.NonIdentifierAttribute;
14+
import org.hibernate.type.AnyType;
15+
import org.hibernate.type.BasicType;
16+
import org.hibernate.type.CollectionType;
17+
import org.hibernate.type.ComponentType;
18+
import org.hibernate.type.ManyToOneType;
19+
import org.hibernate.type.Type;
20+
21+
import org.checkerframework.checker.nullness.qual.Nullable;
1422

1523
/**
1624
* Operations for searching an array of property values for modified elements.
@@ -72,6 +80,62 @@ else if ( previousState[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
7280
}
7381
}
7482

83+
/**
84+
* Determine if any of the given field values are dirty, returning an array containing
85+
* indices of the dirty fields.
86+
* <p>
87+
* If it is determined that no fields are dirty, null is returned.
88+
*
89+
* @param propertyTypes The property types that are dirty checkable. null entry for non-dirty checkable properties
90+
* @param currentState The current state of the entity
91+
* @param previousState The baseline state of the entity
92+
* @param includeColumns Columns to be included in the dirty checking, per property
93+
* @param session The session from which the dirty check request originated.
94+
*
95+
* @return Array containing indices of the dirty properties, or null if no properties considered dirty.
96+
*/
97+
public static int[] findDirty(
98+
@Nullable Type[] propertyTypes,
99+
final Object[] currentState,
100+
final Object[] previousState,
101+
final boolean[][] includeColumns,
102+
final SharedSessionContractImplementor session) {
103+
int[] results = null;
104+
int count = 0;
105+
int span = propertyTypes.length;
106+
107+
for ( int i = 0; i < span; i++ ) {
108+
109+
if ( isDirty( propertyTypes, currentState, previousState, includeColumns, session, i ) ) {
110+
if ( results == null ) {
111+
results = new int[span];
112+
}
113+
results[count++] = i;
114+
}
115+
}
116+
117+
return count == 0 ? null : ArrayHelper.trim( results, count );
118+
}
119+
120+
private static boolean isDirty(
121+
@Nullable Type[] propertyTypes,
122+
Object[] currentState,
123+
Object[] previousState,
124+
boolean[][] includeColumns,
125+
SharedSessionContractImplementor session, int i) {
126+
final Type propertyType;
127+
if ( currentState[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY
128+
|| ( propertyType = propertyTypes[i] ) == null ) {
129+
return false;
130+
}
131+
else if ( previousState[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
132+
return true;
133+
}
134+
else {
135+
return propertyType.isDirty( previousState[i], currentState[i], includeColumns[i], session );
136+
}
137+
}
138+
75139
/**
76140
* Determine if any of the given field values are modified, returning an array containing
77141
* indices of the modified fields.

hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,11 @@
5555
import org.hibernate.type.CompositeType;
5656
import org.hibernate.type.EntityType;
5757
import org.hibernate.type.ManyToOneType;
58+
import org.hibernate.type.OneToOneType;
5859
import org.hibernate.type.Type;
5960

61+
import org.checkerframework.checker.nullness.qual.Nullable;
62+
6063
import static java.util.Collections.singleton;
6164
import static org.hibernate.internal.CoreLogging.messageLogger;
6265
import static org.hibernate.internal.util.ReflectHelper.isAbstractClass;
@@ -95,6 +98,7 @@ public class EntityMetamodel implements Serializable {
9598
// temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9699
private final String[] propertyNames;
97100
private final Type[] propertyTypes;
101+
private final @Nullable Type[] dirtyCheckablePropertyTypes;
98102
private final boolean[] propertyLaziness;
99103
private final boolean[] propertyUpdateability;
100104
private final boolean[] nonlazyPropertyUpdateability;
@@ -217,6 +221,7 @@ public EntityMetamodel(
217221
// temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
218222
propertyNames = new String[propertySpan];
219223
propertyTypes = new Type[propertySpan];
224+
dirtyCheckablePropertyTypes = new Type[propertySpan];
220225
propertyUpdateability = new boolean[propertySpan];
221226
propertyInsertability = new boolean[propertySpan];
222227
nonlazyPropertyUpdateability = new boolean[propertySpan];
@@ -306,6 +311,9 @@ public EntityMetamodel(
306311
propertyNames[i] = attribute.getName();
307312
final Type propertyType = attribute.getType();
308313
propertyTypes[i] = propertyType;
314+
if ( attribute.isDirtyCheckable() && !( propertyType instanceof OneToOneType ) ) {
315+
dirtyCheckablePropertyTypes[i] = propertyType;
316+
}
309317
propertyNullability[i] = attribute.isNullable();
310318
propertyUpdateability[i] = attribute.isUpdateable();
311319
propertyInsertability[i] = attribute.isInsertable();
@@ -794,6 +802,10 @@ public Type[] getPropertyTypes() {
794802
return propertyTypes;
795803
}
796804

805+
public @Nullable Type[] getDirtyCheckablePropertyTypes() {
806+
return dirtyCheckablePropertyTypes;
807+
}
808+
797809
public boolean[] getPropertyLaziness() {
798810
return propertyLaziness;
799811
}

0 commit comments

Comments
 (0)