Skip to content

Commit 4b190a4

Browse files
committed
HHH-19640 on-execution generated fields and forced version increments
When an entity has on-execution generated fields, we have to include them in the UPDATE statement even for a "forced" version increment. So we must skip an optimization.
1 parent b5fb34d commit 4b190a4

File tree

1 file changed

+55
-46
lines changed

1 file changed

+55
-46
lines changed

hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateCoordinatorStandard.java

Lines changed: 55 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -169,15 +169,16 @@ public GeneratedValues update(
169169
SharedSessionContractImplementor session) {
170170
final EntityVersionMapping versionMapping = entityPersister().getVersionMapping();
171171
if ( versionMapping != null ) {
172-
final Supplier<GeneratedValues> generatedValuesAccess = handlePotentialImplicitForcedVersionIncrement(
173-
entity,
174-
id,
175-
values,
176-
oldVersion,
177-
incomingDirtyAttributeIndexes,
178-
session,
179-
versionMapping
180-
);
172+
final var generatedValuesAccess =
173+
handlePotentialImplicitForcedVersionIncrement(
174+
entity,
175+
id,
176+
values,
177+
oldVersion,
178+
incomingDirtyAttributeIndexes,
179+
session,
180+
versionMapping
181+
);
181182
if ( generatedValuesAccess != null ) {
182183
return generatedValuesAccess.get();
183184
}
@@ -389,57 +390,65 @@ protected Supplier<GeneratedValues> handlePotentialImplicitForcedVersionIncremen
389390
int[] incomingDirtyAttributeIndexes,
390391
SharedSessionContractImplementor session,
391392
EntityVersionMapping versionMapping) {
392-
// handle case where the only value being updated is the version.
393-
// we handle this case specially from `#coordinateUpdate` to leverage
394-
// `#doVersionUpdate`
395-
final boolean isSimpleVersionUpdate;
393+
// Handle a case where the only value being updated is the version.
394+
// We treat this case specially in `#coordinateUpdate` to leverage
395+
// `#doVersionUpdate`.
396396
final Object newVersion;
397-
398-
if ( incomingDirtyAttributeIndexes != null ) {
399-
if ( incomingDirtyAttributeIndexes.length == 1
400-
&& versionMapping.getVersionAttribute() == entityPersister().getAttributeMapping( incomingDirtyAttributeIndexes[0] ) ) {
401-
// special case of only the version attribute itself as dirty
402-
isSimpleVersionUpdate = true;
403-
newVersion = values[ incomingDirtyAttributeIndexes[0]];
404-
}
405-
else if ( incomingDirtyAttributeIndexes.length == 0 && oldVersion != null ) {
406-
isSimpleVersionUpdate = !versionMapping.areEqual(
407-
values[ versionMapping.getVersionAttribute().getStateArrayPosition() ],
408-
oldVersion,
409-
session
410-
);
411-
newVersion = values[ versionMapping.getVersionAttribute().getStateArrayPosition()];
412-
}
413-
else {
414-
isSimpleVersionUpdate = false;
415-
newVersion = null;
416-
}
417-
}
418-
else {
419-
isSimpleVersionUpdate = false;
420-
newVersion = null;
397+
if ( entityPersister().hasUpdateGeneratedProperties() ) {
398+
// if we have OnExecutionGenerators for the UPDATE event,
399+
// then we have to include the generated fields in the
400+
// update statement
401+
return null;
421402
}
422-
423-
if ( isSimpleVersionUpdate ) {
424-
// we have just the version being updated - use the special handling
425-
assert newVersion != null;
426-
final GeneratedValues generatedValues = doVersionUpdate( entity, id, newVersion, oldVersion, session );
427-
return () -> generatedValues;
403+
else if ( incomingDirtyAttributeIndexes != null ) {
404+
switch ( incomingDirtyAttributeIndexes.length ) {
405+
case 1:
406+
final int dirtyAttributeIndex = incomingDirtyAttributeIndexes[0];
407+
final var versionAttribute = versionMapping.getVersionAttribute();
408+
final var dirtyAttribute = entityPersister().getAttributeMapping( dirtyAttributeIndex );
409+
if ( versionAttribute == dirtyAttribute ) {
410+
// only the version attribute itself is dirty
411+
newVersion = values[dirtyAttributeIndex];
412+
}
413+
else {
414+
// the dirty field is some other field
415+
return null;
416+
}
417+
break;
418+
case 0:
419+
if ( oldVersion != null ) {
420+
newVersion = values[versionMapping.getVersionAttribute().getStateArrayPosition()];
421+
if ( versionMapping.areEqual( newVersion, oldVersion, session ) ) {
422+
return null;
423+
}
424+
}
425+
else {
426+
return null;
427+
}
428+
break;
429+
default:
430+
return null;
431+
}
428432
}
429433
else {
430434
return null;
431435
}
436+
437+
// we have just the version being updated - use the special handling
438+
assert newVersion != null;
439+
final GeneratedValues generatedValues = doVersionUpdate( entity, id, newVersion, oldVersion, session );
440+
return () -> generatedValues;
432441
}
433442

434443
private static boolean isValueGenerated(Generator generator) {
435444
return generator != null
436-
&& generator.generatesOnUpdate()
437-
&& generator.generatedOnExecution();
445+
&& generator.generatesOnUpdate()
446+
&& generator.generatedOnExecution();
438447
}
439448

440449
private static boolean isValueGenerationInSql(Generator generator, Dialect dialect) {
441450
assert isValueGenerated( generator );
442-
return ( (OnExecutionGenerator) generator ).referenceColumnsInSql(dialect);
451+
return ( (OnExecutionGenerator) generator ).referenceColumnsInSql( dialect );
443452
}
444453

445454
/**

0 commit comments

Comments
 (0)