From ac55bb28db5963d9e2d213b80ece39c24d567381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Mon, 16 Jan 2023 15:17:32 +0100 Subject: [PATCH] HHH-16049 Test setting a property to its current value with bytecode enhancement enabled --- .../basic/EagerAndLazyBasicUpdateTest.java | 176 +++++++++++- .../lazy/basic/OnlyEagerBasicUpdateTest.java | 259 ++++++++++++++++++ .../lazy/basic/OnlyLazyBasicUpdateTest.java | 75 ++++- .../testing/jdbc/SQLStatementInspector.java | 8 + 4 files changed, 511 insertions(+), 7 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/basic/OnlyEagerBasicUpdateTest.java diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/basic/EagerAndLazyBasicUpdateTest.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/basic/EagerAndLazyBasicUpdateTest.java index 1081f956b092..17cc0a6e9f4f 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/basic/EagerAndLazyBasicUpdateTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/basic/EagerAndLazyBasicUpdateTest.java @@ -6,6 +6,9 @@ */ package org.hibernate.test.bytecode.enhancement.lazy.basic; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Configuration; import org.hibernate.orm.test.bytecode.enhancement.lazy.NoDirtyCheckingContext; import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; @@ -16,7 +19,9 @@ import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext; import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext; +import org.hibernate.testing.jdbc.SQLStatementInspector; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -29,7 +34,7 @@ @RunWith(BytecodeEnhancerRunner.class) @CustomEnhancementContext( {EnhancerTestContext.class, NoDirtyCheckingContext.class} ) -@TestForIssue(jiraKey = "HHH-15634") +@TestForIssue(jiraKey = { "HHH-15634", "HHH-16049" }) public class EagerAndLazyBasicUpdateTest extends BaseCoreFunctionalTestCase { private Long entityId; @@ -39,6 +44,16 @@ public Class[] getAnnotatedClasses() { return new Class[] { LazyEntity.class }; } + @Override + protected void prepareBasicRegistryBuilder(StandardServiceRegistryBuilder serviceRegistryBuilder) { + super.prepareBasicRegistryBuilder( serviceRegistryBuilder ); + serviceRegistryBuilder.applySetting( AvailableSettings.STATEMENT_INSPECTOR, SQLStatementInspector.class.getName() ); + } + + SQLStatementInspector statementInspector() { + return (SQLStatementInspector) sessionFactory().getSessionFactoryOptions().getStatementInspector(); + } + private void initNull() { doInHibernate( this::sessionFactory, s -> { LazyEntity entity = new LazyEntity(); @@ -58,6 +73,23 @@ private void initNonNull() { } ); } + @Before + public void clearStatementInspector() { + statementInspector().clear(); + } + + @Test + public void updateOneLazyProperty_nullToNull() { + initNull(); + doInHibernate( this::sessionFactory, s -> { + LazyEntity entity = s.get( LazyEntity.class, entityId ); + entity.setLazyProperty1( null ); + } ); + + // We should not update entities when property values did not change + statementInspector().assertNoUpdate(); + } + @Test public void updateOneLazyProperty_nullToNonNull() { initNull(); @@ -75,7 +107,7 @@ public void updateOneLazyProperty_nullToNonNull() { } @Test - public void updateOneLazyProperty_nonNullToNonNull() { + public void updateOneLazyProperty_nonNullToNonNull_differentValues() { initNonNull(); doInHibernate( this::sessionFactory, s -> { LazyEntity entity = s.get( LazyEntity.class, entityId ); @@ -90,6 +122,18 @@ public void updateOneLazyProperty_nonNullToNonNull() { } ); } + @Test + public void updateOneLazyProperty_nonNullToNonNull_sameValues() { + initNonNull(); + doInHibernate( this::sessionFactory, s -> { + LazyEntity entity = s.get( LazyEntity.class, entityId ); + entity.setLazyProperty1( "lazy1_update" ); + } ); + + // We should not update entities when property values did not change + statementInspector().assertNoUpdate(); + } + @Test public void updateOneLazyProperty_nonNullToNull() { initNonNull(); @@ -106,6 +150,91 @@ public void updateOneLazyProperty_nonNullToNull() { } ); } + @Test + public void updateOneEagerProperty_nullToNull() { + initNull(); + doInHibernate( this::sessionFactory, s -> { + LazyEntity entity = s.get( LazyEntity.class, entityId ); + entity.setEagerProperty( null ); + } ); + + // We should not update entities when property values did not change + statementInspector().assertNoUpdate(); + } + + @Test + public void updateOneEagerProperty_nullToNonNull() { + initNull(); + doInHibernate( this::sessionFactory, s -> { + LazyEntity entity = s.get( LazyEntity.class, entityId ); + entity.setEagerProperty( "eager_update" ); + } ); + doInHibernate( this::sessionFactory, s -> { + LazyEntity entity = s.get( LazyEntity.class, entityId ); + assertEquals( "eager_update", entity.getEagerProperty() ); + + assertNull( entity.getLazyProperty1() ); + assertNull( entity.getLazyProperty2() ); + } ); + } + + @Test + public void updateOneEagerProperty_nonNullToNonNull_differentValues() { + initNonNull(); + doInHibernate( this::sessionFactory, s -> { + LazyEntity entity = s.get( LazyEntity.class, entityId ); + entity.setEagerProperty( "eager_update" ); + } ); + doInHibernate( this::sessionFactory, s -> { + LazyEntity entity = s.get( LazyEntity.class, entityId ); + assertEquals( "eager_update", entity.getEagerProperty() ); + + assertEquals( "lazy1_initial", entity.getLazyProperty1() ); + assertEquals( "lazy2_initial", entity.getLazyProperty2() ); + } ); + } + + @Test + public void updateOneEagerProperty_nonNullToNonNull_sameValues() { + initNonNull(); + doInHibernate( this::sessionFactory, s -> { + LazyEntity entity = s.get( LazyEntity.class, entityId ); + entity.setEagerProperty( "eager_update" ); + } ); + + // We should not update entities when property values did not change + statementInspector().assertNoUpdate(); + } + + @Test + public void updateOneEagerProperty_nonNullToNull() { + initNonNull(); + doInHibernate( this::sessionFactory, s -> { + LazyEntity entity = s.get( LazyEntity.class, entityId ); + entity.setEagerProperty( null ); + } ); + doInHibernate( this::sessionFactory, s -> { + LazyEntity entity = s.get( LazyEntity.class, entityId ); + assertNull( entity.getEagerProperty() ); + + assertEquals( "lazy1_initial", entity.getLazyProperty1() ); + assertEquals( "lazy2_initial", entity.getLazyProperty2() ); + } ); + } + + @Test + public void updateOneEagerPropertyAndOneLazyProperty_nullToNull() { + initNull(); + doInHibernate( this::sessionFactory, s -> { + LazyEntity entity = s.get( LazyEntity.class, entityId ); + entity.setEagerProperty( null ); + entity.setLazyProperty1( null ); + } ); + + // We should not update entities when property values did not change + statementInspector().assertNoUpdate(); + } + @Test public void updateOneEagerPropertyAndOneLazyProperty_nullToNonNull() { initNull(); @@ -124,7 +253,7 @@ public void updateOneEagerPropertyAndOneLazyProperty_nullToNonNull() { } @Test - public void updateOneEagerPropertyAndOneLazyProperty_nonNullToNonNull() { + public void updateOneEagerPropertyAndOneLazyProperty_nonNullToNonNull_differentValues() { initNonNull(); doInHibernate( this::sessionFactory, s -> { LazyEntity entity = s.get( LazyEntity.class, entityId ); @@ -140,6 +269,19 @@ public void updateOneEagerPropertyAndOneLazyProperty_nonNullToNonNull() { } ); } + @Test + public void updateOneEagerPropertyAndOneLazyProperty_nonNullToNonNull_sameValues() { + initNonNull(); + doInHibernate( this::sessionFactory, s -> { + LazyEntity entity = s.get( LazyEntity.class, entityId ); + entity.setEagerProperty( entity.getEagerProperty() ); + entity.setLazyProperty1( entity.getLazyProperty1() ); + } ); + + // We should not update entities when property values did not change + statementInspector().assertNoUpdate(); + } + @Test public void updateOneEagerPropertyAndOneLazyProperty_nonNullToNull() { initNonNull(); @@ -157,6 +299,19 @@ public void updateOneEagerPropertyAndOneLazyProperty_nonNullToNull() { } ); } + @Test + public void updateAllLazyProperties_nullToNull() { + initNull(); + doInHibernate( this::sessionFactory, s -> { + LazyEntity entity = s.get( LazyEntity.class, entityId ); + entity.setLazyProperty1( null ); + entity.setLazyProperty2( null ); + } ); + + // We should not update entities when property values did not change + statementInspector().assertNoUpdate(); + } + @Test public void updateAllLazyProperties_nullToNonNull() { initNull(); @@ -175,7 +330,7 @@ public void updateAllLazyProperties_nullToNonNull() { } @Test - public void updateAllLazyProperties_nonNullToNonNull() { + public void updateAllLazyProperties_nonNullToNonNull_differentValues() { initNonNull(); doInHibernate( this::sessionFactory, s -> { LazyEntity entity = s.get( LazyEntity.class, entityId ); @@ -191,6 +346,19 @@ public void updateAllLazyProperties_nonNullToNonNull() { } ); } + @Test + public void updateAllLazyProperties_nonNullToNonNull_sameValues() { + initNonNull(); + doInHibernate( this::sessionFactory, s -> { + LazyEntity entity = s.get( LazyEntity.class, entityId ); + entity.setLazyProperty1( entity.getLazyProperty1() ); + entity.setLazyProperty2( entity.getLazyProperty2() ); + } ); + + // We should not update entities when property values did not change + statementInspector().assertNoUpdate(); + } + @Test public void updateAllLazyProperties_nonNullToNull() { initNonNull(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/basic/OnlyEagerBasicUpdateTest.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/basic/OnlyEagerBasicUpdateTest.java new file mode 100644 index 000000000000..16ed6f90b1a4 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/basic/OnlyEagerBasicUpdateTest.java @@ -0,0 +1,259 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.bytecode.enhancement.lazy.basic; + +import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.orm.test.bytecode.enhancement.lazy.NoDirtyCheckingContext; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; +import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext; +import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext; +import org.hibernate.testing.jdbc.SQLStatementInspector; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.persistence.Basic; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * Tests the behavior of basic property updates when all properties are eager (the default). + *

+ * This is mostly for comparison with {@link EagerAndLazyBasicUpdateTest}/{@link OnlyLazyBasicUpdateTest}, + * because the mere presence of lazy properties in one entity may affect the behavior of eager properties, too. + */ +@RunWith(BytecodeEnhancerRunner.class) +@CustomEnhancementContext({ EnhancerTestContext.class, NoDirtyCheckingContext.class }) +@TestForIssue(jiraKey = "HHH-16049") +public class OnlyEagerBasicUpdateTest extends BaseCoreFunctionalTestCase { + + private Long entityId; + + @Override + public Class[] getAnnotatedClasses() { + return new Class[] { EagerEntity.class }; + } + + @Override + protected void prepareBasicRegistryBuilder(StandardServiceRegistryBuilder serviceRegistryBuilder) { + super.prepareBasicRegistryBuilder( serviceRegistryBuilder ); + serviceRegistryBuilder.applySetting( AvailableSettings.STATEMENT_INSPECTOR, SQLStatementInspector.class.getName() ); + } + + SQLStatementInspector statementInspector() { + return (SQLStatementInspector) sessionFactory().getSessionFactoryOptions().getStatementInspector(); + } + + private void initNull() { + doInHibernate( this::sessionFactory, s -> { + EagerEntity entity = new EagerEntity(); + s.persist( entity ); + entityId = entity.getId(); + } ); + } + + private void initNonNull() { + doInHibernate( this::sessionFactory, s -> { + EagerEntity entity = new EagerEntity(); + entity.setEagerProperty1( "eager1_initial" ); + entity.setEagerProperty2( "eager2_initial" ); + s.persist( entity ); + entityId = entity.getId(); + } ); + } + + @Before + public void clearStatementInspector() { + statementInspector().clear(); + } + + @Test + public void updateSomeEagerProperty_nullToNull() { + initNull(); + doInHibernate( this::sessionFactory, s -> { + EagerEntity entity = s.get( EagerEntity.class, entityId ); + entity.setEagerProperty1( null ); + } ); + + // We should not update entities when property values did not change + statementInspector().assertNoUpdate(); + } + + @Test + public void updateSomeEagerProperty_nullToNonNull() { + initNull(); + doInHibernate( this::sessionFactory, s -> { + EagerEntity entity = s.get( EagerEntity.class, entityId ); + entity.setEagerProperty1( "eager1_update" ); + } ); + doInHibernate( this::sessionFactory, s -> { + EagerEntity entity = s.get( EagerEntity.class, entityId ); + assertEquals( "eager1_update", entity.getEagerProperty1() ); + + assertNull( entity.getEagerProperty2() ); + } ); + } + + @Test + public void updateSomeEagerProperty_nonNullToNonNull_differentValues() { + initNonNull(); + doInHibernate( this::sessionFactory, s -> { + EagerEntity entity = s.get( EagerEntity.class, entityId ); + entity.setEagerProperty1( "eager1_update" ); + } ); + doInHibernate( this::sessionFactory, s -> { + EagerEntity entity = s.get( EagerEntity.class, entityId ); + assertEquals( "eager1_update", entity.getEagerProperty1() ); + + assertEquals( "eager2_initial", entity.getEagerProperty2() ); + } ); + } + + @Test + public void updateSomeEagerProperty_nonNullToNonNull_sameValues() { + initNonNull(); + doInHibernate( this::sessionFactory, s -> { + EagerEntity entity = s.get( EagerEntity.class, entityId ); + entity.setEagerProperty1( entity.getEagerProperty1() ); + } ); + + // We should not update entities when property values did not change + statementInspector().assertNoUpdate(); + } + + @Test + public void updateSomeEagerProperty_nonNullToNull() { + initNonNull(); + doInHibernate( this::sessionFactory, s -> { + EagerEntity entity = s.get( EagerEntity.class, entityId ); + entity.setEagerProperty1( null ); + } ); + doInHibernate( this::sessionFactory, s -> { + EagerEntity entity = s.get( EagerEntity.class, entityId ); + assertNull( entity.getEagerProperty1() ); + + assertEquals( "eager2_initial", entity.getEagerProperty2() ); + } ); + } + + @Test + public void updateAllEagerProperties_nullToNull() { + initNull(); + doInHibernate( this::sessionFactory, s -> { + EagerEntity entity = s.get( EagerEntity.class, entityId ); + entity.setEagerProperty1( null ); + entity.setEagerProperty2( null ); + } ); + + // We should not update entities when property values did not change + statementInspector().assertNoUpdate(); + } + + @Test + public void updateAllEagerProperties_nullToNonNull() { + initNull(); + doInHibernate( this::sessionFactory, s -> { + EagerEntity entity = s.get( EagerEntity.class, entityId ); + entity.setEagerProperty1( "eager1_update" ); + entity.setEagerProperty2( "eager2_update" ); + } ); + doInHibernate( this::sessionFactory, s -> { + EagerEntity entity = s.get( EagerEntity.class, entityId ); + assertEquals( "eager1_update", entity.getEagerProperty1() ); + assertEquals( "eager2_update", entity.getEagerProperty2() ); + } ); + } + + @Test + public void updateAllEagerProperties_nonNullToNonNull_differentValues() { + initNonNull(); + doInHibernate( this::sessionFactory, s -> { + EagerEntity entity = s.get( EagerEntity.class, entityId ); + entity.setEagerProperty1( "eager1_update" ); + entity.setEagerProperty2( "eager2_update" ); + } ); + doInHibernate( this::sessionFactory, s -> { + EagerEntity entity = s.get( EagerEntity.class, entityId ); + assertEquals( "eager1_update", entity.getEagerProperty1() ); + assertEquals( "eager2_update", entity.getEagerProperty2() ); + } ); + } + + @Test + public void updateAllEagerProperties_nonNullToNonNull_sameValues() { + initNonNull(); + doInHibernate( this::sessionFactory, s -> { + EagerEntity entity = s.get( EagerEntity.class, entityId ); + entity.setEagerProperty1( entity.getEagerProperty1() ); + entity.setEagerProperty2( entity.getEagerProperty2() ); + } ); + + // We should not update entities when property values did not change + statementInspector().assertNoUpdate(); + } + + @Test + public void updateAllEagerProperties_nonNullToNull() { + initNonNull(); + doInHibernate( this::sessionFactory, s -> { + EagerEntity entity = s.get( EagerEntity.class, entityId ); + entity.setEagerProperty1( null ); + entity.setEagerProperty2( null ); + } ); + doInHibernate( this::sessionFactory, s -> { + EagerEntity entity = s.get( EagerEntity.class, entityId ); + assertNull( entity.getEagerProperty1() ); + assertNull( entity.getEagerProperty2() ); + } ); + } + + @Entity + @Table(name = "LAZY_ENTITY") + private static class EagerEntity { + @Id + @GeneratedValue + Long id; + @Basic + String eagerProperty1; + @Basic + String eagerProperty2; + + Long getId() { + return id; + } + + void setId(Long id) { + this.id = id; + } + + public String getEagerProperty1() { + return eagerProperty1; + } + + public void setEagerProperty1(String eagerProperty1) { + this.eagerProperty1 = eagerProperty1; + } + + public String getEagerProperty2() { + return eagerProperty2; + } + + public void setEagerProperty2(String eagerProperty2) { + this.eagerProperty2 = eagerProperty2; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/basic/OnlyLazyBasicUpdateTest.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/basic/OnlyLazyBasicUpdateTest.java index dfadd521529b..7ce2446df4e6 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/basic/OnlyLazyBasicUpdateTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/basic/OnlyLazyBasicUpdateTest.java @@ -6,13 +6,17 @@ */ package org.hibernate.test.bytecode.enhancement.lazy.basic; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.cfg.AvailableSettings; import org.hibernate.orm.test.bytecode.enhancement.lazy.NoDirtyCheckingContext; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext; import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext; +import org.hibernate.testing.jdbc.SQLStatementInspector; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -29,7 +33,7 @@ @RunWith(BytecodeEnhancerRunner.class) @CustomEnhancementContext({ EnhancerTestContext.class, NoDirtyCheckingContext.class }) -@TestForIssue(jiraKey = "HHH-15634") +@TestForIssue(jiraKey = { "HHH-15634", "HHH-16049" }) public class OnlyLazyBasicUpdateTest extends BaseCoreFunctionalTestCase { private Long entityId; @@ -39,6 +43,16 @@ public Class[] getAnnotatedClasses() { return new Class[] { LazyEntity.class }; } + @Override + protected void prepareBasicRegistryBuilder(StandardServiceRegistryBuilder serviceRegistryBuilder) { + super.prepareBasicRegistryBuilder( serviceRegistryBuilder ); + serviceRegistryBuilder.applySetting( AvailableSettings.STATEMENT_INSPECTOR, SQLStatementInspector.class.getName() ); + } + + SQLStatementInspector statementInspector() { + return (SQLStatementInspector) sessionFactory().getSessionFactoryOptions().getStatementInspector(); + } + private void initNull() { doInHibernate( this::sessionFactory, s -> { LazyEntity entity = new LazyEntity(); @@ -57,6 +71,23 @@ private void initNonNull() { } ); } + @Before + public void clearStatementInspector() { + statementInspector().clear(); + } + + @Test + public void updateSomeLazyProperty_nullToNull() { + initNull(); + doInHibernate( this::sessionFactory, s -> { + LazyEntity entity = s.get( LazyEntity.class, entityId ); + entity.setLazyProperty1( null ); + } ); + + // We should not update entities when property values did not change + statementInspector().assertNoUpdate(); + } + @Test public void updateSomeLazyProperty_nullToNonNull() { initNull(); @@ -73,7 +104,7 @@ public void updateSomeLazyProperty_nullToNonNull() { } @Test - public void updateSomeLazyProperty_nonNullToNonNull() { + public void updateSomeLazyProperty_nonNullToNonNull_differentValues() { initNonNull(); doInHibernate( this::sessionFactory, s -> { LazyEntity entity = s.get( LazyEntity.class, entityId ); @@ -87,6 +118,18 @@ public void updateSomeLazyProperty_nonNullToNonNull() { } ); } + @Test + public void updateSomeLazyProperty_nonNullToNonNull_sameValues() { + initNonNull(); + doInHibernate( this::sessionFactory, s -> { + LazyEntity entity = s.get( LazyEntity.class, entityId ); + entity.setLazyProperty1( entity.getLazyProperty1() ); + } ); + + // We should not update entities when property values did not change + statementInspector().assertNoUpdate(); + } + @Test public void updateSomeLazyProperty_nonNullToNull() { initNonNull(); @@ -102,6 +145,19 @@ public void updateSomeLazyProperty_nonNullToNull() { } ); } + @Test + public void updateAllLazyProperties_nullToNull() { + initNull(); + doInHibernate( this::sessionFactory, s -> { + LazyEntity entity = s.get( LazyEntity.class, entityId ); + entity.setLazyProperty1( null ); + entity.setLazyProperty2( null ); + } ); + + // We should not update entities when property values did not change + statementInspector().assertNoUpdate(); + } + @Test public void updateAllLazyProperties_nullToNonNull() { initNull(); @@ -118,7 +174,7 @@ public void updateAllLazyProperties_nullToNonNull() { } @Test - public void updateAllLazyProperties_nonNullToNonNull() { + public void updateAllLazyProperties_nonNullToNonNull_differentValues() { initNonNull(); doInHibernate( this::sessionFactory, s -> { LazyEntity entity = s.get( LazyEntity.class, entityId ); @@ -132,6 +188,19 @@ public void updateAllLazyProperties_nonNullToNonNull() { } ); } + @Test + public void updateAllLazyProperties_nonNullToNonNull_sameValues() { + initNonNull(); + doInHibernate( this::sessionFactory, s -> { + LazyEntity entity = s.get( LazyEntity.class, entityId ); + entity.setLazyProperty1( entity.getLazyProperty1() ); + entity.setLazyProperty2( entity.getLazyProperty2() ); + } ); + + // We should not update entities when property values did not change + statementInspector().assertNoUpdate(); + } + @Test public void updateAllLazyProperties_nonNullToNull() { initNonNull(); diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/jdbc/SQLStatementInspector.java b/hibernate-testing/src/main/java/org/hibernate/testing/jdbc/SQLStatementInspector.java index 231d5098f100..d1627be19c4c 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/jdbc/SQLStatementInspector.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/jdbc/SQLStatementInspector.java @@ -19,6 +19,8 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; +import org.assertj.core.api.Assertions; + /** * @author Andrea Boriero */ @@ -99,6 +101,12 @@ public void assertIsUpdate(int queryNumber) { assertTrue( query.toLowerCase( Locale.ROOT ).startsWith( "update" ) ); } + public void assertNoUpdate() { + Assertions.assertThat( sqlQueries ) + .isNotEmpty() + .allSatisfy( sql -> Assertions.assertThat( sql.toLowerCase( Locale.ROOT ) ).doesNotStartWith( "update" ) ); + } + public static SQLStatementInspector extractFromSession(SessionImplementor session) { return (SQLStatementInspector) session.getJdbcSessionContext().getStatementInspector(); }