From a9022e5b04efc8284d3ea8a5060c7a67efc1c015 Mon Sep 17 00:00:00 2001 From: barreiro Date: Wed, 8 Mar 2017 17:10:28 +0000 Subject: [PATCH] HHH-11506 - Fix update of lazy attributes when there are attributes not loaded HHH-11506 - Deprecate methods HHH-11506 : Added original TypeHelper#findModfied and deprecated; changed deprecated methods to call the new methods. (cherry picked from commit aaebcdf454d57a640c8194d0559642d405f00868) --- .../entity/AbstractEntityPersister.java | 2 - .../tuple/AbstractNonIdentifierAttribute.java | 2 +- .../tuple/NonIdentifierAttribute.java | 4 ++ .../java/org/hibernate/type/TypeHelper.java | 64 +++++++++++++++++-- .../bytecode/enhancement/EnhancerTest.java | 14 ++++ 5 files changed, 77 insertions(+), 9 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 9b4313d1b2c1..b7203646d6fe 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -4206,7 +4206,6 @@ public int[] findDirty(Object[] currentState, Object[] previousState, Object ent currentState, previousState, propertyColumnUpdateable, - hasUninitializedLazyProperties( entity ), session ); if ( props == null ) { @@ -4237,7 +4236,6 @@ public int[] findModified(Object[] old, Object[] current, Object entity, Session current, old, propertyColumnUpdateable, - hasUninitializedLazyProperties( entity ), session ); if ( props == null ) { diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/AbstractNonIdentifierAttribute.java b/hibernate-core/src/main/java/org/hibernate/tuple/AbstractNonIdentifierAttribute.java index e6bbf2f230fd..8b4d21e91a69 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/AbstractNonIdentifierAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/AbstractNonIdentifierAttribute.java @@ -86,7 +86,7 @@ public boolean isDirtyCheckable() { @Override public boolean isDirtyCheckable(boolean hasUninitializedProperties) { - return isDirtyCheckable() && ( !hasUninitializedProperties || !isLazy() ); + return isDirtyCheckable(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/NonIdentifierAttribute.java b/hibernate-core/src/main/java/org/hibernate/tuple/NonIdentifierAttribute.java index d39ab4b899a5..1efd0706fcc9 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/NonIdentifierAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/NonIdentifierAttribute.java @@ -24,6 +24,10 @@ public interface NonIdentifierAttribute extends Attribute, AttributeDefinition { public boolean isNullable(); + /** + * @deprecated Use {@link org.hibernate.tuple.NonIdentifierAttribute#isDirtyCheckable()} instead + */ + @Deprecated public boolean isDirtyCheckable(boolean hasUninitializedProperties); public boolean isDirtyCheckable(); diff --git a/hibernate-core/src/main/java/org/hibernate/type/TypeHelper.java b/hibernate-core/src/main/java/org/hibernate/type/TypeHelper.java index fdd0f081564e..bc588e3910fe 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/TypeHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/type/TypeHelper.java @@ -276,9 +276,12 @@ else if ( !types[i].isAssociationType() ) { * @param includeColumns Columns to be included in the dirty checking, per property * @param anyUninitializedProperties Does the entity currently hold any uninitialized property values? * @param session The session from which the dirty check request originated. - * + * * @return Array containing indices of the dirty properties, or null if no properties considered dirty. + * + * @deprecated Use {org.hibernate.type.TypeHelper{@link #findDirty(NonIdentifierAttribute[], Object[], Object[], boolean[][], SessionImplementor)} instead */ + @Deprecated public static int[] findDirty( final NonIdentifierAttribute[] properties, final Object[] currentState, @@ -286,13 +289,36 @@ public static int[] findDirty( final boolean[][] includeColumns, final boolean anyUninitializedProperties, final SessionImplementor session) { + return findDirty( properties, currentState, previousState, includeColumns, session ); + } + + /** + * Determine if any of the given field values are dirty, returning an array containing + * indices of the dirty fields. + *

+ * If it is determined that no fields are dirty, null is returned. + * + * @param properties The property definitions + * @param currentState The current state of the entity + * @param previousState The baseline state of the entity + * @param includeColumns Columns to be included in the dirty checking, per property + * @param session The session from which the dirty check request originated. + * + * @return Array containing indices of the dirty properties, or null if no properties considered dirty. + */ + public static int[] findDirty( + final NonIdentifierAttribute[] properties, + final Object[] currentState, + final Object[] previousState, + final boolean[][] includeColumns, + final SessionImplementor session) { int[] results = null; int count = 0; int span = properties.length; for ( int i = 0; i < span; i++ ) { final boolean dirty = currentState[i] != LazyPropertyInitializer.UNFETCHED_PROPERTY - && properties[i].isDirtyCheckable( anyUninitializedProperties ) + && properties[i].isDirtyCheckable() && properties[i].getType().isDirty( previousState[i], currentState[i], includeColumns[i], session ); if ( dirty ) { if ( results == null ) { @@ -326,7 +352,11 @@ public static int[] findDirty( * @param session The session from which the dirty check request originated. * * @return Array containing indices of the modified properties, or null if no properties considered modified. + * + * @deprecated Use {@link #findModified(NonIdentifierAttribute[], Object[], Object[], boolean[][], boolean, SessionImplementor)} + * instead. */ + @Deprecated public static int[] findModified( final NonIdentifierAttribute[] properties, final Object[] currentState, @@ -334,15 +364,37 @@ public static int[] findModified( final boolean[][] includeColumns, final boolean anyUninitializedProperties, final SessionImplementor session) { + return findModified( properties, currentState, previousState, includeColumns, session ); + } + + /** + * Determine if any of the given field values are modified, returning an array containing + * indices of the modified fields. + *

+ * If it is determined that no fields are dirty, null is returned. + * + * @param properties The property definitions + * @param currentState The current state of the entity + * @param previousState The baseline state of the entity + * @param includeColumns Columns to be included in the mod checking, per property + * @param session The session from which the dirty check request originated. + * + * @return Array containing indices of the modified properties, or null if no properties considered modified. + **/ + public static int[] findModified( + final NonIdentifierAttribute[] properties, + final Object[] currentState, + final Object[] previousState, + final boolean[][] includeColumns, + final SessionImplementor session) { int[] results = null; int count = 0; int span = properties.length; for ( int i = 0; i < span; i++ ) { - final boolean modified = currentState[i]!=LazyPropertyInitializer.UNFETCHED_PROPERTY - && properties[i].isDirtyCheckable(anyUninitializedProperties) - && properties[i].getType().isModified( previousState[i], currentState[i], includeColumns[i], session ); - + final boolean modified = currentState[ i ] != LazyPropertyInitializer.UNFETCHED_PROPERTY + && properties[ i ].isDirtyCheckable() + && properties[ i ].getType().isModified( previousState[ i ], currentState[ i ], includeColumns[ i ], session ); if ( modified ) { if ( results == null ) { results = new int[span]; diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/EnhancerTest.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/EnhancerTest.java index dcbb05177662..72bbabea8774 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/EnhancerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/EnhancerTest.java @@ -14,7 +14,9 @@ import org.hibernate.test.bytecode.enhancement.association.InheritedAttributeAssociationTestTask; import org.hibernate.test.bytecode.enhancement.otherentityentrycontext.OtherEntityEntryContextTestTask; import org.hibernate.test.bytecode.enhancement.cascade.CascadeWithFkConstraintTestTask; +import org.hibernate.testing.DialectChecks; import org.hibernate.testing.FailureExpected; +import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext; import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils; @@ -122,6 +124,7 @@ public boolean hasLazyLoadableAttributes(CtClass classDescriptor) { @Test @TestForIssue( jiraKey = "HHH-11173" ) + @RequiresDialectFeature( DialectChecks.SupportsIdentityColumns.class) public void testLazyCache() { EnhancerTestUtils.runEnhancerTestTask( LazyInCacheTestTask.class ); } @@ -162,6 +165,17 @@ public void testLazyGroupsUpdateSimple() { EnhancerTestUtils.runEnhancerTestTask( SimpleLazyGroupUpdateTestTask.class ); } + @Test + @TestForIssue( jiraKey = "HHH-11506" ) + public void testLazyGroupsUpdateWithoutDirtyChecking() { + EnhancerTestUtils.runEnhancerTestTask( SimpleLazyGroupUpdateTestTask.class , new EnhancerTestContext() { + @Override + public boolean doDirtyCheckingInline(CtClass classDescriptor) { + return false; + } + } ); + } + @Test public void testLazyCollectionNoTransactionHandling() { EnhancerTestUtils.runEnhancerTestTask( LazyCollectionNoTransactionLoadingTestTask.class );