HHH-12607 - Reworked and introduced more test cases.

This commit is contained in:
Chris Cranford 2018-06-20 11:42:58 -04:00
parent 0b7c1e2fcb
commit e41e5445f8
6 changed files with 1154 additions and 100 deletions

View File

@ -0,0 +1,208 @@
/*
* 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.envers.test.integration.collection.embeddable;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OrderColumn;
import javax.persistence.Tuple;
import org.hibernate.envers.Audited;
import org.hibernate.envers.strategy.ValidityAuditStrategy;
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
import org.hibernate.envers.test.Priority;
import org.junit.Test;
import org.hibernate.testing.TestForIssue;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
/**
* This test verifies that when a list-based {@link ElementCollection} of {@link Embeddable} objects
* are audited that the same number of audit rows are generated regardless whether the embeddable
* implements proper {@code equals} and {@code hashCode} methods.
*
* @author Chris Cranford
*/
@TestForIssue(jiraKey = "HHH-12607")
public class ListEqualsHashCodeTest extends BaseEnversJPAFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { TestEntity.class };
}
@Test
@Priority(10)
public void initData() {
final Emb emb1 = new Emb( "value1" );
final Emb emb2 = new Emb( "value2" );
doInJPA( this::entityManagerFactory, entityManager -> {
TestEntity e = new TestEntity( 1 );
e.setEmbs1( new ArrayList<>() );
e.getEmbs1().add( emb1 );
e.getEmbs1().add( emb2 );
entityManager.persist( e );
} );
doInJPA( this::entityManagerFactory, entityManager -> {
TestEntity e = entityManager.find( TestEntity.class, 1 );
for ( Emb emb : e.getEmbs1() ) {
if ( emb.getValue().equals( "value1" ) ) {
e.getEmbs1().remove( emb );
break;
}
}
e.getEmbs1().add( new Emb( "value3" ) );
} );
}
@Test
public void testAuditRowsForValidityAuditStrategy() {
if ( ValidityAuditStrategy.class.getName().equals( getAuditStrategy() ) ) {
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery(
"SELECT COUNT(1) FROM TestEntity_embs1_AUD WHERE REVEND IS NULL",
Tuple.class
)
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 4 ), results.get( 0 ).get( 0 ) );
} );
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery(
"SELECT COUNT(1) FROM TestEntity_embs1_AUD",
Tuple.class
)
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 6 ), results.get( 0 ).get( 0 ) );
} );
}
}
@Test
public void testAuditRowsForDefaultAuditStrategy() {
if ( !ValidityAuditStrategy.class.getName().equals( getAuditStrategy() ) ) {
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery(
"SELECT COUNT(1) FROM TestEntity_embs1_AUD",
Tuple.class
)
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 6 ), results.get( 0 ).get( 0 ) );
} );
}
}
@Test
public void testRevisionHistory1() {
TestEntity e = getAuditReader().find( TestEntity.class, 1, 1 );
assertEquals( 2, e.getEmbs1().size() );
assertHasEmbeddableWithValue( e, "value1" );
assertHasEmbeddableWithValue( e, "value2" );
}
@Test
public void testRevisionHistory2() {
TestEntity e = getAuditReader().find( TestEntity.class, 1, 2 );
assertEquals( 2, e.getEmbs1().size() );
assertHasEmbeddableWithValue( e, "value3" );
assertHasEmbeddableWithValue( e, "value2" );
}
private static void assertHasEmbeddableWithValue(TestEntity entity, String value) {
for ( Emb embeddable : entity.getEmbs1() ) {
if ( embeddable.getValue().equals( value ) ) {
return;
}
}
fail( "Failed to find embeddable with value [" + value + "]" );
}
@Entity(name = "TestEntity")
@Audited
public static class TestEntity {
@Id
private Integer id;
@ElementCollection
@OrderColumn
private List<Emb> embs1;
public TestEntity() {
}
public TestEntity(Integer id) {
this.id = id;
}
public List<Emb> getEmbs1() {
return embs1;
}
public void setEmbs1(List<Emb> embs1) {
this.embs1 = embs1;
}
}
@Embeddable
public static class Emb implements Serializable {
private String value;
public Emb() {
}
public Emb(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
Emb emb = (Emb) o;
return Objects.equals( value, emb.value );
}
@Override
public int hashCode() {
return Objects.hash( value );
}
}
}

View File

@ -0,0 +1,190 @@
/*
* 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.envers.test.integration.collection.embeddable;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OrderColumn;
import javax.persistence.Tuple;
import org.hibernate.envers.Audited;
import org.hibernate.envers.strategy.ValidityAuditStrategy;
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
import org.hibernate.envers.test.Priority;
import org.junit.Test;
import org.hibernate.testing.TestForIssue;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
/**
* This test verifies that when a list-based {@link ElementCollection} of {@link Embeddable} objects
* are audited that the same number of audit rows are generated regardless whether the embeddable
* implements proper {@code equals} and {@code hashCode} methods.
*
* @author Chris Cranford
*/
@TestForIssue(jiraKey = "HHH-12607")
public class ListNoEqualsHashCodeTest extends BaseEnversJPAFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { TestEntity.class };
}
@Test
@Priority(10)
public void initData() {
final Emb emb1 = new Emb( "value1" );
final Emb emb2 = new Emb( "value2" );
doInJPA( this::entityManagerFactory, entityManager -> {
TestEntity e = new TestEntity( 1 );
e.setEmbs1( new ArrayList<>() );
e.getEmbs1().add( emb1 );
e.getEmbs1().add( emb2 );
entityManager.persist( e );
} );
doInJPA( this::entityManagerFactory, entityManager -> {
TestEntity e = entityManager.find( TestEntity.class, 1 );
for ( Emb emb : e.getEmbs1() ) {
if ( emb.getValue().equals( "value1" ) ) {
e.getEmbs1().remove( emb );
break;
}
}
e.getEmbs1().add( new Emb( "value3" ) );
} );
}
@Test
public void testAuditRowsForValidityAuditStrategy() {
if ( ValidityAuditStrategy.class.getName().equals( getAuditStrategy() ) ) {
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery(
"SELECT COUNT(1) FROM TestEntity_embs1_AUD WHERE REVEND IS NULL",
Tuple.class
)
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 4 ), results.get( 0 ).get( 0 ) );
} );
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery(
"SELECT COUNT(1) FROM TestEntity_embs1_AUD",
Tuple.class
)
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 6 ), results.get( 0 ).get( 0 ) );
} );
}
}
@Test
public void testAuditRowsForDefaultAuditStrategy() {
if ( !ValidityAuditStrategy.class.getName().equals( getAuditStrategy() ) ) {
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery(
"SELECT COUNT(1) FROM TestEntity_embs1_AUD",
Tuple.class
)
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 6 ), results.get( 0 ).get( 0 ) );
} );
}
}
@Test
public void testRevisionHistory1() {
TestEntity e = getAuditReader().find( TestEntity.class, 1, 1 );
assertEquals( 2, e.getEmbs1().size() );
assertHasEmbeddableWithValue( e, "value1" );
assertHasEmbeddableWithValue( e, "value2" );
}
@Test
public void testRevisionHistory2() {
TestEntity e = getAuditReader().find( TestEntity.class, 1, 2 );
assertEquals( 2, e.getEmbs1().size() );
assertHasEmbeddableWithValue( e, "value3" );
assertHasEmbeddableWithValue( e, "value2" );
}
private static void assertHasEmbeddableWithValue(TestEntity entity, String value) {
for ( Emb embeddable : entity.getEmbs1() ) {
if ( embeddable.getValue().equals( value ) ) {
return;
}
}
fail( "Failed to find embeddable with value [" + value + "]" );
}
@Entity(name = "TestEntity")
@Audited
public static class TestEntity {
@Id
private Integer id;
@ElementCollection
@OrderColumn
private List<Emb> embs1;
public TestEntity() {
}
public TestEntity(Integer id) {
this.id = id;
}
public List<Emb> getEmbs1() {
return embs1;
}
public void setEmbs1(List<Emb> embs1) {
this.embs1 = embs1;
}
}
@Embeddable
public static class Emb implements Serializable {
private String value;
public Emb() {
}
public Emb(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}

View File

@ -0,0 +1,214 @@
/*
* 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.envers.test.integration.collection.embeddable;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Tuple;
import org.hibernate.envers.Audited;
import org.hibernate.envers.strategy.ValidityAuditStrategy;
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
import org.hibernate.envers.test.Priority;
import org.junit.Test;
import org.hibernate.testing.TestForIssue;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertEquals;
/**
* This test verifies that when a map-based {@link ElementCollection} of {@link Embeddable} objects
* are audited that the same number of audit rows are generated regardless whether the embeddable
* implements proper {@code equals} and {@code hashCode} methods.
*
* The {@link ValidityAuditStrategy} with equals/hashcode.
*
* +-----+---------+---------------+-----------+--------+--------+
* | REV | REVTYPE | TESTENTITY_ID | EMBS1_KEY | REVEND | VALUE |
* +-----+---------+---------------+-----------+--------+--------+
* | 1 | 0 | 1 | a | 2 | value1 |
* | 1 | 0 | 1 | b | null | value2 |
* | 2 | 0 | 1 | a | null | value3 |
* | 2 | 2 | 1 | a | null | value1 |
* +-----+---------+---------------+-----------+--------+--------+
*
* The {@link org.hibernate.envers.strategy.DefaultAuditStrategy} with equals/hashcode.
*
* +-----+---------+---------------+-----------+--------+
* | REV | REVTYPE | TESTENTITY_ID | EMBS1_KEY | VALUE |
* +-----+---------+---------------+-----------+--------+
* | 1 | 0 | 1 | a | value1 |
* | 1 | 0 | 1 | b | value2 |
* | 2 | 0 | 1 | a | value3 |
* | 2 | 2 | 1 | a | value1 |
* +-----+---------+---------------+-----------+--------+
*
* This test uses hashcode and equals as a baseline.
*
* @author Chris Cranford
*/
@TestForIssue(jiraKey = "HHH-12607")
public class MapEqualsHashCodeTest extends BaseEnversJPAFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { TestEntity.class };
}
@Test
@Priority(10)
public void initData() {
doInJPA( this::entityManagerFactory, entityManager -> {
TestEntity e = new TestEntity( 1 );
e.setEmbs1( new HashMap<>() );
e.getEmbs1().put( "a", new Emb( "value1" ) );
e.getEmbs1().put( "b", new Emb( "value2" ) );
entityManager.persist( e );
} );
doInJPA( this::entityManagerFactory, entityManager -> {
TestEntity e = entityManager.find( TestEntity.class, 1 );
e.getEmbs1().put( "a", new Emb( "value3" ) );
} );
}
@Test
public void testAuditRowsForValidityAuditStrategy() {
if ( ValidityAuditStrategy.class.getName().equals( getAuditStrategy() ) ) {
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery(
"SELECT COUNT(1) FROM TestEntity_embs1_AUD WHERE REVEND IS NULL",
Tuple.class
)
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 3 ), results.get( 0 ).get( 0 ) );
} );
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery(
"SELECT COUNT(1) FROM TestEntity_embs1_AUD",
Tuple.class
)
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 4 ), results.get( 0 ).get( 0 ) );
} );
}
}
@Test
public void testAuditRowsForDefaultAuditStrategy() {
if ( !ValidityAuditStrategy.class.getName().equals( getAuditStrategy() ) ) {
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery(
"SELECT COUNT(1) FROM TestEntity_embs1_AUD",
Tuple.class
)
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 4 ), results.get( 0 ).get( 0 ) );
} );
}
}
@Test
public void testRevisionHistory1() {
TestEntity e = getAuditReader().find( TestEntity.class, 1, 1 );
assertEquals( 2, e.getEmbs1().size() );
assertEquals( "value1", e.getEmbs1().get( "a" ).getValue() );
assertEquals( "value2", e.getEmbs1().get( "b" ).getValue() );
}
@Test
public void testRevisionHistory2() {
TestEntity e = getAuditReader().find( TestEntity.class, 1, 2 );
assertEquals( 2, e.getEmbs1().size() );
assertEquals( "value3", e.getEmbs1().get( "a" ).getValue() );
assertEquals( "value2", e.getEmbs1().get( "b" ).getValue() );
}
@Entity(name = "TestEntity")
@Audited
public static class TestEntity {
@Id
private Integer id;
@ElementCollection
private Map<String, Emb> embs1;
public TestEntity() {
}
public TestEntity(Integer id) {
this.id = id;
}
public Map<String, Emb> getEmbs1() {
return embs1;
}
public void setEmbs1(Map<String, Emb> embs1) {
this.embs1 = embs1;
}
}
@Embeddable
public static class Emb implements Serializable {
private String value;
public Emb() {
}
public Emb(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
Emb emb = (Emb) o;
return Objects.equals( value, emb.value );
}
@Override
public int hashCode() {
return Objects.hash( value );
}
}
}

View File

@ -4,7 +4,7 @@
* 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.envers.test;
package org.hibernate.envers.test.integration.collection.embeddable;
import java.io.Serializable;
import java.math.BigInteger;
@ -20,7 +20,8 @@ import javax.persistence.Tuple;
import org.hibernate.envers.Audited;
import org.hibernate.envers.strategy.ValidityAuditStrategy;
import org.hibernate.envers.test.tools.TablePrinter;
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
import org.hibernate.envers.test.Priority;
import org.junit.Test;
import org.hibernate.testing.TestForIssue;
@ -29,10 +30,120 @@ import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertEquals;
/**
* This test verifies that when a map-based {@link ElementCollection} of {@link Embeddable} objects
* are audited that the same number of audit rows are generated regardless whether the embeddable
* implements proper {@code equals} and {@code hashCode} methods.
*
* The {@link org.hibernate.envers.strategy.ValidityAuditStrategy} with equals/hashcode.
*
* +-----+---------+---------------+-----------+--------+--------+
* | REV | REVTYPE | TESTENTITY_ID | EMBS1_KEY | REVEND | VALUE |
* +-----+---------+---------------+-----------+--------+--------+
* | 1 | 0 | 1 | a | 2 | value1 |
* | 1 | 0 | 1 | b | null | value2 |
* | 2 | 0 | 1 | a | null | value3 |
* | 2 | 2 | 1 | a | null | value1 |
* +-----+---------+---------------+-----------+--------+--------+
*
* The {@link org.hibernate.envers.strategy.DefaultAuditStrategy} with equals/hashcode.
*
* +-----+---------+---------------+-----------+--------+
* | REV | REVTYPE | TESTENTITY_ID | EMBS1_KEY | VALUE |
* +-----+---------+---------------+-----------+--------+
* | 1 | 0 | 1 | a | value1 |
* | 1 | 0 | 1 | b | value2 |
* | 2 | 0 | 1 | a | value3 |
* | 2 | 2 | 1 | a | value1 |
* +-----+---------+---------------+-----------+--------+
*
* @author Chris Cranford
*/
@TestForIssue(jiraKey = "HHH-12607")
public class ElementCollectionTest extends BaseEnversJPAFunctionalTestCase {
public class MapNoEqualsHashCodeTest extends BaseEnversJPAFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { TestEntity.class };
}
@Test
@Priority(10)
public void initData() {
doInJPA( this::entityManagerFactory, entityManager -> {
TestEntity e = new TestEntity( 1 );
e.setEmbs1( new HashMap<>() );
e.getEmbs1().put( "a", new Emb( "value1" ) );
e.getEmbs1().put( "b", new Emb( "value2" ) );
entityManager.persist( e );
} );
doInJPA( this::entityManagerFactory, entityManager -> {
TestEntity e = entityManager.find( TestEntity.class, 1 );
e.getEmbs1().put( "a", new Emb( "value3" ) );
} );
}
@Test
public void testAuditRowsForValidityAuditStrategy() {
if ( ValidityAuditStrategy.class.getName().equals( getAuditStrategy() ) ) {
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery(
"SELECT COUNT(1) FROM TestEntity_embs1_AUD WHERE REVEND IS NULL",
Tuple.class
)
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 3 ), results.get( 0 ).get( 0 ) );
} );
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery(
"SELECT COUNT(1) FROM TestEntity_embs1_AUD",
Tuple.class
)
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 4 ), results.get( 0 ).get( 0 ) );
} );
}
}
@Test
public void testAuditRowsForDefaultAuditStrategy() {
if ( !ValidityAuditStrategy.class.getName().equals( getAuditStrategy() ) ) {
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery(
"SELECT COUNT(1) FROM TestEntity_embs1_AUD",
Tuple.class
)
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 4 ), results.get( 0 ).get( 0 ) );
} );
}
}
@Test
public void testRevisionHistory1() {
TestEntity e = getAuditReader().find( TestEntity.class, 1, 1 );
assertEquals( 2, e.getEmbs1().size() );
assertEquals( "value1", e.getEmbs1().get( "a" ).getValue() );
assertEquals( "value2", e.getEmbs1().get( "b" ).getValue() );
}
@Test
public void testRevisionHistory2() {
TestEntity e = getAuditReader().find( TestEntity.class, 1, 2 );
assertEquals( 2, e.getEmbs1().size() );
assertEquals( "value3", e.getEmbs1().get( "a" ).getValue() );
assertEquals( "value2", e.getEmbs1().get( "b" ).getValue() );
}
@Entity(name = "TestEntity")
@Audited
@ -80,101 +191,4 @@ public class ElementCollectionTest extends BaseEnversJPAFunctionalTestCase {
this.value = value;
}
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { TestEntity.class };
}
@Test
@Priority(10)
public void initData() {
System.out.println( "************************************************************ " );
System.out.println( "REV1 - Insert 2 rows into collection" );
doInJPA( this::entityManagerFactory, entityManager -> {
TestEntity e = new TestEntity( 1 );
e.setEmbs1( new HashMap<>() );
e.getEmbs1().put( "a", new Emb( "value1" ) );
e.getEmbs1().put( "b", new Emb( "value2" ) );
entityManager.persist( e );
} );
TablePrinter.print( this::entityManagerFactory, "TestEntity_AUD", "TestEntity_embs1_AUD" );
System.out.println( "************************************************************ " );
System.out.println( "REV2 - Replace A with value1 as A with value 3 in collection" );
doInJPA( this::entityManagerFactory, entityManager -> {
TestEntity e = entityManager.find( TestEntity.class, 1 );
e.getEmbs1().put( "a", new Emb( "value3" ) );
} );
// ValidityAuditStrategy
// always 4 values when equals/hashCode is implemented
// +-----+---------+---------------+-----------+--------+--------+
// | REV | REVTYPE | TESTENTITY_ID | EMBS1_KEY | REVEND | VALUE |
// +-----+---------+---------------+-----------+--------+--------+
// | 1 | 0 | 1 | a | 2 | value1 |
// | 1 | 0 | 1 | b | null | value2 |
// | 2 | 0 | 1 | a | null | value3 |
// | 2 | 2 | 1 | a | null | value1 |
// +-----+---------+---------------+-----------+--------+--------+
// DefaultAuditStrategy
// always 4 values when equals/hashCode is implemented
// +-----+---------+---------------+-----------+--------+
// | REV | REVTYPE | TESTENTITY_ID | EMBS1_KEY | VALUE |
// +-----+---------+---------------+-----------+--------+
// | 1 | 0 | 1 | a | value1 |
// | 1 | 0 | 1 | b | value2 |
// | 2 | 0 | 1 | a | value3 |
// | 2 | 2 | 1 | a | value1 |
// +-----+---------+---------------+-----------+--------+
TablePrinter.print( this::entityManagerFactory, "TestEntity_AUD", "TestEntity_embs1_AUD" );
if ( ValidityAuditStrategy.class.getName().equals( getAuditStrategy() ) ) {
System.out.println( "************************************************************ " );
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery( "SELECT COUNT(1) FROM TestEntity_embs1_AUD WHERE REVEND IS NULL", Tuple.class )
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 3 ), results.get( 0 ).get( 0 ) );
} );
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery( "SELECT COUNT(1) FROM TestEntity_embs1_AUD", Tuple.class )
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 4 ), results.get( 0 ).get( 0 ) );
} );
}
else {
System.out.println( "************************************************************ " );
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery( "SELECT COUNT(1) FROM TestEntity_embs1_AUD", Tuple.class )
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 4 ), results.get( 0 ).get( 0 ) );
} );
}
}
@Test
public void testRevisionHistory1() {
TestEntity e = getAuditReader().find( TestEntity.class, 1, 1 );
assertEquals( 2, e.getEmbs1().size() );
assertEquals( "value1", e.getEmbs1().get( "a" ).getValue() );
assertEquals( "value2", e.getEmbs1().get( "b" ).getValue() );
}
@Test
public void testRevisionHistory2() {
TestEntity e = getAuditReader().find( TestEntity.class, 1, 2 );
assertEquals( 2, e.getEmbs1().size() );
assertEquals( "value3", e.getEmbs1().get( "a" ).getValue() );
assertEquals( "value2", e.getEmbs1().get( "b" ).getValue() );
}
}

View File

@ -0,0 +1,215 @@
/*
* 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.envers.test.integration.collection.embeddable;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Tuple;
import org.hibernate.envers.Audited;
import org.hibernate.envers.strategy.ValidityAuditStrategy;
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
import org.hibernate.envers.test.Priority;
import org.hibernate.envers.test.tools.TestTools;
import org.junit.Test;
import org.hibernate.testing.TestForIssue;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertEquals;
/**
* This test verifies that when a set-based {@link ElementCollection} of {@link Embeddable} objects
* are audited that the same number of audit rows are generated regardless whether the embeddable
* implements proper {@code equals} and {@code hashCode} methods.
*
* The {@link org.hibernate.envers.strategy.ValidityAuditStrategy} with equals/hashcode.
*
* +-----+---------+---------------+-----------+--------+--------+
* | REV | REVTYPE | TESTENTITY_ID | EMBS1_KEY | REVEND | VALUE |
* +-----+---------+---------------+-----------+--------+--------+
* | 1 | 0 | 1 | a | 2 | value1 |
* | 1 | 0 | 1 | b | null | value2 |
* | 2 | 0 | 1 | a | null | value3 |
* | 2 | 2 | 1 | a | null | value1 |
* +-----+---------+---------------+-----------+--------+--------+
*
* The {@link org.hibernate.envers.strategy.DefaultAuditStrategy} with equals/hashcode.
*
* +-----+---------+---------------+-----------+--------+
* | REV | REVTYPE | TESTENTITY_ID | EMBS1_KEY | VALUE |
* +-----+---------+---------------+-----------+--------+
* | 1 | 0 | 1 | a | value1 |
* | 1 | 0 | 1 | b | value2 |
* | 2 | 0 | 1 | a | value3 |
* | 2 | 2 | 1 | a | value1 |
* +-----+---------+---------------+-----------+--------+
*
* This test uses hashcode and equals as a baseline.
*
* @author Chris Cranford
*/
@TestForIssue(jiraKey = "HHH-12607")
public class SetEqualsHashCodeTest extends BaseEnversJPAFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { TestEntity.class };
}
@Test
@Priority(10)
public void initData() {
final Emb emb1 = new Emb( "value1" );
final Emb emb2 = new Emb( "value2" );
doInJPA( this::entityManagerFactory, entityManager -> {
TestEntity e = new TestEntity( 1 );
e.setEmbs1( new HashSet<>() );
e.getEmbs1().add( emb1 );
e.getEmbs1().add( emb2 );
entityManager.persist( e );
} );
doInJPA( this::entityManagerFactory, entityManager -> {
TestEntity e = entityManager.find( TestEntity.class, 1 );
e.getEmbs1().remove( emb1 );
e.getEmbs1().add( new Emb( "value3" ) );
} );
}
@Test
public void testAuditRowsForValidityAuditStrategy() {
if ( ValidityAuditStrategy.class.getName().equals( getAuditStrategy() ) ) {
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery(
"SELECT COUNT(1) FROM TestEntity_embs1_AUD WHERE REVEND IS NULL",
Tuple.class
)
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 3 ), results.get( 0 ).get( 0 ) );
} );
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery(
"SELECT COUNT(1) FROM TestEntity_embs1_AUD",
Tuple.class
)
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 4 ), results.get( 0 ).get( 0 ) );
} );
}
}
@Test
public void testAuditRowsForDefaultAuditStrategy() {
if ( !ValidityAuditStrategy.class.getName().equals( getAuditStrategy() ) ) {
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery(
"SELECT COUNT(1) FROM TestEntity_embs1_AUD",
Tuple.class
)
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 4 ), results.get( 0 ).get( 0 ) );
} );
}
}
@Test
public void testRevisionHistory1() {
TestEntity e = getAuditReader().find( TestEntity.class, 1, 1 );
assertEquals( 2, e.getEmbs1().size() );
assertEquals( e.getEmbs1(), TestTools.makeSet( new Emb( "value1" ), new Emb( "value2" ) ) );
}
@Test
public void testRevisionHistory2() {
TestEntity e = getAuditReader().find( TestEntity.class, 1, 2 );
assertEquals( 2, e.getEmbs1().size() );
assertEquals( e.getEmbs1(), TestTools.makeSet( new Emb( "value3" ), new Emb( "value2" ) ) );
}
@Entity(name = "TestEntity")
@Audited
public static class TestEntity {
@Id
private Integer id;
@ElementCollection
private Set<Emb> embs1;
public TestEntity() {
}
public TestEntity(Integer id) {
this.id = id;
}
public Set<Emb> getEmbs1() {
return embs1;
}
public void setEmbs1(Set<Emb> embs1) {
this.embs1 = embs1;
}
}
@Embeddable
public static class Emb implements Serializable {
private String value;
public Emb() {
}
public Emb(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
Emb emb = (Emb) o;
return Objects.equals( value, emb.value );
}
@Override
public int hashCode() {
return Objects.hash( value );
}
}
}

View File

@ -0,0 +1,213 @@
/*
* 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.envers.test.integration.collection.embeddable;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Tuple;
import org.hibernate.envers.Audited;
import org.hibernate.envers.strategy.ValidityAuditStrategy;
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
import org.hibernate.envers.test.Priority;
import org.junit.Test;
import org.hibernate.testing.TestForIssue;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
/**
* This test verifies that when a set-based {@link ElementCollection} of {@link Embeddable} objects
* are audited that the same number of audit rows are generated regardless whether the embeddable
* implements proper {@code equals} and {@code hashCode} methods.
*
* The {@link org.hibernate.envers.strategy.ValidityAuditStrategy} with equals/hashcode.
*
* +-----+---------+---------------+-----------+--------+--------+
* | REV | REVTYPE | TESTENTITY_ID | EMBS1_KEY | REVEND | VALUE |
* +-----+---------+---------------+-----------+--------+--------+
* | 1 | 0 | 1 | a | 2 | value1 |
* | 1 | 0 | 1 | b | null | value2 |
* | 2 | 0 | 1 | a | null | value3 |
* | 2 | 2 | 1 | a | null | value1 |
* +-----+---------+---------------+-----------+--------+--------+
*
* The {@link org.hibernate.envers.strategy.DefaultAuditStrategy} with equals/hashcode.
*
* +-----+---------+---------------+-----------+--------+
* | REV | REVTYPE | TESTENTITY_ID | EMBS1_KEY | VALUE |
* +-----+---------+---------------+-----------+--------+
* | 1 | 0 | 1 | a | value1 |
* | 1 | 0 | 1 | b | value2 |
* | 2 | 0 | 1 | a | value3 |
* | 2 | 2 | 1 | a | value1 |
* +-----+---------+---------------+-----------+--------+
*
* @author Chris Cranford
*/
@TestForIssue(jiraKey = "HHH-12607")
public class SetNoEqualsHashCodeTest extends BaseEnversJPAFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { TestEntity.class };
}
@Test
@Priority(10)
public void initData() {
final Emb emb1 = new Emb( "value1" );
final Emb emb2 = new Emb( "value2" );
doInJPA( this::entityManagerFactory, entityManager -> {
TestEntity e = new TestEntity( 1 );
e.setEmbs1( new HashSet<>() );
e.getEmbs1().add( emb1 );
e.getEmbs1().add( emb2 );
entityManager.persist( e );
} );
doInJPA( this::entityManagerFactory, entityManager -> {
TestEntity e = entityManager.find( TestEntity.class, 1 );
for ( Emb emb : e.getEmbs1() ) {
if ( emb.getValue().equals( "value1" ) ) {
e.getEmbs1().remove( emb );
break;
}
}
e.getEmbs1().add( new Emb( "value3" ) );
} );
}
@Test
public void testAuditRowsForValidityAuditStrategy() {
if ( ValidityAuditStrategy.class.getName().equals( getAuditStrategy() ) ) {
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery(
"SELECT COUNT(1) FROM TestEntity_embs1_AUD WHERE REVEND IS NULL",
Tuple.class
)
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 3 ), results.get( 0 ).get( 0 ) );
} );
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery(
"SELECT COUNT(1) FROM TestEntity_embs1_AUD",
Tuple.class
)
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 4 ), results.get( 0 ).get( 0 ) );
} );
}
}
@Test
public void testAuditRowsForDefaultAuditStrategy() {
if ( !ValidityAuditStrategy.class.getName().equals( getAuditStrategy() ) ) {
doInJPA( this::entityManagerFactory, entityManager -> {
List<Tuple> results = entityManager
.createNativeQuery(
"SELECT COUNT(1) FROM TestEntity_embs1_AUD",
Tuple.class
)
.getResultList();
assertEquals( 1, results.size() );
assertEquals( BigInteger.valueOf( 4 ), results.get( 0 ).get( 0 ) );
} );
}
}
@Test
public void testRevisionHistory1() {
TestEntity e = getAuditReader().find( TestEntity.class, 1, 1 );
assertEquals( 2, e.getEmbs1().size() );
assertHasEmbeddableWithValue( e, "value1" );
assertHasEmbeddableWithValue( e, "value2" );
}
@Test
public void testRevisionHistory2() {
TestEntity e = getAuditReader().find( TestEntity.class, 1, 2 );
assertEquals( 2, e.getEmbs1().size() );
assertHasEmbeddableWithValue( e, "value3" );
assertHasEmbeddableWithValue( e, "value2" );
}
private static void assertHasEmbeddableWithValue(TestEntity entity, String value) {
for ( Emb embeddable : entity.getEmbs1() ) {
if ( embeddable.getValue().equals( value ) ) {
return;
}
}
fail( "Failed to find embeddable with value [" + value + "]" );
}
@Entity(name = "TestEntity")
@Audited
public static class TestEntity {
@Id
private Integer id;
@ElementCollection
private Set<Emb> embs1;
public TestEntity() {
}
public TestEntity(Integer id) {
this.id = id;
}
public Set<Emb> getEmbs1() {
return embs1;
}
public void setEmbs1(Set<Emb> embs1) {
this.embs1 = embs1;
}
}
@Embeddable
public static class Emb implements Serializable {
private String value;
public Emb() {
}
public Emb(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}