Skip to content

Commit c180c1e

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

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
@@ -3696,7 +3696,7 @@ public boolean isSubclassPropertyNullable(int i) {
36963696
public int[] findDirty(Object[] currentState, Object[] previousState, Object entity, SharedSessionContractImplementor session)
36973697
throws HibernateException {
36983698
int[] props = DirtyHelper.findDirty(
3699-
entityMetamodel.getProperties(),
3699+
entityMetamodel.getDirtyCheckablePropertyTypes(),
37003700
currentState,
37013701
previousState,
37023702
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
@@ -52,8 +52,11 @@
5252
import org.hibernate.type.CompositeType;
5353
import org.hibernate.type.EntityType;
5454
import org.hibernate.type.ManyToOneType;
55+
import org.hibernate.type.OneToOneType;
5556
import org.hibernate.type.Type;
5657

58+
import org.checkerframework.checker.nullness.qual.Nullable;
59+
5760
import static java.util.Collections.singleton;
5861
import static org.hibernate.internal.CoreLogging.messageLogger;
5962
import static org.hibernate.internal.util.ReflectHelper.isAbstractClass;
@@ -92,6 +95,7 @@ public class EntityMetamodel implements Serializable {
9295
// temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9396
private final String[] propertyNames;
9497
private final Type[] propertyTypes;
98+
private final @Nullable Type[] dirtyCheckablePropertyTypes;
9599
private final boolean[] propertyLaziness;
96100
private final boolean[] propertyUpdateability;
97101
private final boolean[] nonlazyPropertyUpdateability;
@@ -210,6 +214,7 @@ public EntityMetamodel(
210214
// temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
211215
propertyNames = new String[propertySpan];
212216
propertyTypes = new Type[propertySpan];
217+
dirtyCheckablePropertyTypes = new Type[propertySpan];
213218
propertyUpdateability = new boolean[propertySpan];
214219
propertyInsertability = new boolean[propertySpan];
215220
nonlazyPropertyUpdateability = new boolean[propertySpan];
@@ -298,6 +303,9 @@ public EntityMetamodel(
298303
propertyNames[i] = attribute.getName();
299304
final Type propertyType = attribute.getType();
300305
propertyTypes[i] = propertyType;
306+
if ( attribute.isDirtyCheckable() && !( propertyType instanceof OneToOneType ) ) {
307+
dirtyCheckablePropertyTypes[i] = propertyType;
308+
}
301309
propertyNullability[i] = attribute.isNullable();
302310
propertyUpdateability[i] = attribute.isUpdateable();
303311
propertyInsertability[i] = attribute.isInsertable();
@@ -757,6 +765,10 @@ public Type[] getPropertyTypes() {
757765
return propertyTypes;
758766
}
759767

768+
public @Nullable Type[] getDirtyCheckablePropertyTypes() {
769+
return dirtyCheckablePropertyTypes;
770+
}
771+
760772
public boolean[] getPropertyLaziness() {
761773
return propertyLaziness;
762774
}

0 commit comments

Comments
 (0)