Lazy properties are not updated on bytecode-enhanced entity if not all lazy properties (e.g. collections) are initialized

Description

If a bytecode-enhanced entity with a lazy field is updated, the update of that field is issued correctly only if all lazy properties are initialized, including e.g. collections.
This is what my test case shows: The lazy property longText is not updated unless the OneToMany collection children is loaded.

There have been two other issues describing this: (opened by Petras Petkus) and (opened by me). Both issues have been closed, but IMHO the problem is not fixed.

I'll be happy to verify this on trunc as soon as it's fixed, just let me know.

Attachments

1

Activity

Show:

Davide Massarenti November 15, 2017 at 4:09 PM

I'm running 5.2.10 and I still see an issue.

If an entity has multiple lazy properties but not all of them have been loaded, hasUninitializedLazyProperties() returns true, and then getUpdateStrings() selects the lazy update SQL statement, which does not update any of the lazy properties:

private String[] getUpdateStrings(boolean byRowId, boolean lazy) {
if ( byRowId ) {
return lazy ? getSQLLazyUpdateByRowIdStrings() : getSQLUpdateByRowIdStrings();
}
else {
return lazy ? getSQLLazyUpdateStrings() : getSQLUpdateStrings();
}
}

It seems that there should be a check around here to see if only some of the lazy properties are initialized and others are dirty and activate Dynamic Update:

if ( entry == null && !isMutable() ) {
throw new IllegalStateException( "Updating immutable entity that is not in session yet!" );
}
if ( ( entityMetamodel.isDynamicUpdate() && dirtyFields != null ) ) {
// We need to generate the UPDATE SQL when dynamic-update="true"
propsToUpdate = getPropertiesToUpdate( dirtyFields, hasDirtyCollection );
// don't need to check laziness (dirty checking algorithm handles that)
updateStrings = new String[span];
for ( int j = 0; j < span; j++ ) {
updateStrings[j] = tableUpdateNeeded[j] ?
generateUpdateString( propsToUpdate, j, oldFields, j == 0 && rowId != null ) :
null;
}
}

Jörg Mattes March 14, 2017 at 7:04 AM

Thanks for the fix. I'd be very happy if you could backport it to 5.1.x.

Former user March 14, 2017 at 5:19 AM

Fixed in master.

Luis Barreiro March 8, 2017 at 1:05 PM

It seems to be happening because without enableDirtyTracking the dirty checking mechanism used is TypeHelper#findDirty()[1] and it calls [2] which clearly states that for a lazy property to be dirty all lazy properties must be initialized.

[1] - https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/main/java/org/hibernate/type/TypeHelper.java#L298
[2] - https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/main/java/org/hibernate/tuple/AbstractNonIdentifierAttribute.java#L89

Former user March 4, 2017 at 1:39 AM

This seems to happen only with enableDirtyTracking=false. When it is changed to true, the test passes.

, please take a look at this.

Fixed

Details

Assignee

Reporter

Worked in

Components

Fix versions

Affects versions

Priority

Created February 20, 2017 at 10:09 PM
Updated November 15, 2017 at 4:09 PM
Resolved March 14, 2017 at 5:19 AM