Skip to content

Commit 5d45d19

Browse files
committed
HHH-18506 Reduce itable stubs during dirty checking
1 parent 94b444b commit 5d45d19

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
@@ -3628,7 +3628,7 @@ public boolean isAffectedByEnabledFilters(
36283628
public int[] findDirty(Object[] currentState, Object[] previousState, Object entity, SharedSessionContractImplementor session)
36293629
throws HibernateException {
36303630
int[] props = DirtyHelper.findDirty(
3631-
entityMetamodel.getProperties(),
3631+
entityMetamodel.getDirtyCheckablePropertyTypes(),
36323632
currentState,
36333633
previousState,
36343634
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
@@ -54,8 +54,11 @@
5454
import org.hibernate.type.CompositeType;
5555
import org.hibernate.type.EntityType;
5656
import org.hibernate.type.ManyToOneType;
57+
import org.hibernate.type.OneToOneType;
5758
import org.hibernate.type.Type;
5859

60+
import org.checkerframework.checker.nullness.qual.Nullable;
61+
5962
import static java.util.Collections.singleton;
6063
import static org.hibernate.internal.CoreLogging.messageLogger;
6164
import static org.hibernate.internal.util.ReflectHelper.isAbstractClass;
@@ -93,6 +96,7 @@ public class EntityMetamodel implements Serializable {
9396
// temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9497
private final String[] propertyNames;
9598
private final Type[] propertyTypes;
99+
private final @Nullable Type[] dirtyCheckablePropertyTypes;
96100
private final boolean[] propertyLaziness;
97101
private final boolean[] propertyUpdateability;
98102
private final boolean[] nonlazyPropertyUpdateability;
@@ -206,6 +210,7 @@ public EntityMetamodel(
206210
// temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
207211
propertyNames = new String[propertySpan];
208212
propertyTypes = new Type[propertySpan];
213+
dirtyCheckablePropertyTypes = new Type[propertySpan];
209214
propertyUpdateability = new boolean[propertySpan];
210215
propertyInsertability = new boolean[propertySpan];
211216
nonlazyPropertyUpdateability = new boolean[propertySpan];
@@ -295,6 +300,9 @@ public EntityMetamodel(
295300
propertyNames[i] = attribute.getName();
296301
final Type propertyType = attribute.getType();
297302
propertyTypes[i] = propertyType;
303+
if ( attribute.isDirtyCheckable() && !( propertyType instanceof OneToOneType ) ) {
304+
dirtyCheckablePropertyTypes[i] = propertyType;
305+
}
298306
propertyNullability[i] = attribute.isNullable();
299307
propertyUpdateability[i] = attribute.isUpdateable();
300308
propertyInsertability[i] = attribute.isInsertable();
@@ -786,6 +794,10 @@ public Type[] getPropertyTypes() {
786794
return propertyTypes;
787795
}
788796

797+
public @Nullable Type[] getDirtyCheckablePropertyTypes() {
798+
return dirtyCheckablePropertyTypes;
799+
}
800+
789801
public boolean[] getPropertyLaziness() {
790802
return propertyLaziness;
791803
}

0 commit comments

Comments
 (0)