HHH-16049 Test setting a property to its current value with bytecode enhancement enabled

This commit is contained in:
Yoann Rodière 2023-01-16 15:17:32 +01:00 committed by Andrea Boriero
parent 7026df8add
commit 54a36fe3cb
4 changed files with 510 additions and 7 deletions

View File

@ -6,6 +6,8 @@
*/
package org.hibernate.orm.test.bytecode.enhancement.lazy.basic;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.orm.test.bytecode.enhancement.lazy.NoDirtyCheckingContext;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
@ -16,7 +18,9 @@ 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 @@ import jakarta.persistence.Table;
@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 +43,16 @@ public class EagerAndLazyBasicUpdateTest extends BaseCoreFunctionalTestCase {
return new Class<?>[] { LazyEntity.class };
}
@Override
protected void configure(Configuration configuration) {
super.afterConfigurationBuilt( configuration );
configuration.getProperties().put( Environment.STATEMENT_INSPECTOR, new SQLStatementInspector() );
}
SQLStatementInspector statementInspector() {
return (SQLStatementInspector) sessionFactory().getSessionFactoryOptions().getStatementInspector();
}
private void initNull() {
doInHibernate( this::sessionFactory, s -> {
LazyEntity entity = new LazyEntity();
@ -58,6 +72,23 @@ public class EagerAndLazyBasicUpdateTest extends BaseCoreFunctionalTestCase {
} );
}
@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 +106,7 @@ public class EagerAndLazyBasicUpdateTest extends BaseCoreFunctionalTestCase {
}
@Test
public void updateOneLazyProperty_nonNullToNonNull() {
public void updateOneLazyProperty_nonNullToNonNull_differentValues() {
initNonNull();
doInHibernate( this::sessionFactory, s -> {
LazyEntity entity = s.get( LazyEntity.class, entityId );
@ -90,6 +121,18 @@ public class EagerAndLazyBasicUpdateTest extends BaseCoreFunctionalTestCase {
} );
}
@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 +149,91 @@ public class EagerAndLazyBasicUpdateTest extends BaseCoreFunctionalTestCase {
} );
}
@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 +252,7 @@ public class EagerAndLazyBasicUpdateTest extends BaseCoreFunctionalTestCase {
}
@Test
public void updateOneEagerPropertyAndOneLazyProperty_nonNullToNonNull() {
public void updateOneEagerPropertyAndOneLazyProperty_nonNullToNonNull_differentValues() {
initNonNull();
doInHibernate( this::sessionFactory, s -> {
LazyEntity entity = s.get( LazyEntity.class, entityId );
@ -140,6 +268,19 @@ public class EagerAndLazyBasicUpdateTest extends BaseCoreFunctionalTestCase {
} );
}
@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 +298,19 @@ public class EagerAndLazyBasicUpdateTest extends BaseCoreFunctionalTestCase {
} );
}
@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 +329,7 @@ public class EagerAndLazyBasicUpdateTest extends BaseCoreFunctionalTestCase {
}
@Test
public void updateAllLazyProperties_nonNullToNonNull() {
public void updateAllLazyProperties_nonNullToNonNull_differentValues() {
initNonNull();
doInHibernate( this::sessionFactory, s -> {
LazyEntity entity = s.get( LazyEntity.class, entityId );
@ -191,6 +345,19 @@ public class EagerAndLazyBasicUpdateTest extends BaseCoreFunctionalTestCase {
} );
}
@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();

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.orm.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.cfg.Configuration;
import org.hibernate.cfg.Environment;
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 jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
/**
* Tests the behavior of basic property updates when all properties are eager (the default).
* <p>
* 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 configure(Configuration configuration) {
super.afterConfigurationBuilt( configuration );
configuration.getProperties().put( Environment.STATEMENT_INSPECTOR, new SQLStatementInspector() );
}
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;
}
}
}

View File

@ -6,13 +6,17 @@
*/
package org.hibernate.orm.test.bytecode.enhancement.lazy.basic;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
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 @@ import static org.junit.Assert.assertNull;
@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 OnlyLazyBasicUpdateTest extends BaseCoreFunctionalTestCase {
return new Class<?>[] { LazyEntity.class };
}
@Override
protected void configure(Configuration configuration) {
super.afterConfigurationBuilt( configuration );
configuration.getProperties().put( Environment.STATEMENT_INSPECTOR, new SQLStatementInspector() );
}
SQLStatementInspector statementInspector() {
return (SQLStatementInspector) sessionFactory().getSessionFactoryOptions().getStatementInspector();
}
private void initNull() {
doInHibernate( this::sessionFactory, s -> {
LazyEntity entity = new LazyEntity();
@ -57,6 +71,23 @@ public class OnlyLazyBasicUpdateTest extends BaseCoreFunctionalTestCase {
} );
}
@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 class OnlyLazyBasicUpdateTest extends BaseCoreFunctionalTestCase {
}
@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 class OnlyLazyBasicUpdateTest extends BaseCoreFunctionalTestCase {
} );
}
@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 class OnlyLazyBasicUpdateTest extends BaseCoreFunctionalTestCase {
} );
}
@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 class OnlyLazyBasicUpdateTest extends BaseCoreFunctionalTestCase {
}
@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 class OnlyLazyBasicUpdateTest extends BaseCoreFunctionalTestCase {
} );
}
@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();

View File

@ -19,6 +19,8 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import org.assertj.core.api.Assertions;
/**
* @author Andrea Boriero
*/
@ -111,6 +113,12 @@ public class SQLStatementInspector implements StatementInspector {
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();
}