HHH-12992 - Added test cases.

This commit is contained in:
Chris Cranford 2018-10-04 11:11:59 -04:00
parent 10148324d1
commit 334e064272
4 changed files with 1143 additions and 0 deletions

View File

@ -0,0 +1,262 @@
/*
* 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.query;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.envers.AuditMappedBy;
import org.hibernate.envers.Audited;
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
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.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* Test the use of the {@link OrderBy} annotation on a one-to-many collection where
* both sides of the association are audited.
*
* This mapping invokes the use of the OneAuditEntityQueryGenerator which we want to
* verify orders the collection results properly.
*
* @author Chris Cranford
*/
@TestForIssue(jiraKey = "HHH-12992")
public class OrderByOneAuditEntityTest extends BaseEnversJPAFunctionalTestCase {
@Entity(name = "Parent")
@Audited
public static class Parent {
@Id
@GeneratedValue
private Integer id;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
@OrderBy("index, index2 desc")
@AuditMappedBy(mappedBy = "parent", positionMappedBy = "index")
@Fetch(FetchMode.SELECT)
@BatchSize(size = 100)
private List<Child> children = new ArrayList<>();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public List<Child> getChildren() {
return children;
}
public void setChildren(List<Child> children) {
this.children = children;
}
}
@Entity(name = "Child")
@Audited
public static class Child {
@Id
private Integer id;
private Integer index;
private Integer index2;
@ManyToOne
private Parent parent;
public Child() {
}
public Child(Integer id, Integer index) {
this.id = id;
this.index = index;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getIndex() {
return index;
}
public void setIndex(Integer index) {
this.index = index;
}
public Integer getIndex2() {
return index2;
}
public void setIndex2(Integer index2) {
this.index2 = index2;
}
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
Child child = (Child) o;
return Objects.equals( id, child.id ) &&
Objects.equals( index, child.index );
}
@Override
public int hashCode() {
return Objects.hash( id, index );
}
@Override
public String toString() {
return "Child{" +
"id=" + id +
", index=" + index +
'}';
}
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { Parent.class, Child.class };
}
private Integer parentId;
@Test
public void initData() {
// Rev 1
this.parentId = doInJPA( this::entityManagerFactory, entityManager -> {
final Parent parent = new Parent();
final Child child1 = new Child();
child1.setId( 1 );
child1.setIndex( 1 );
child1.setIndex2( 1 );
child1.setParent( parent );
parent.getChildren().add( child1 );
final Child child2 = new Child();
child2.setId( 2 );
child2.setIndex( 2 );
child2.setIndex2( 2 );
child2.setParent( parent );
parent.getChildren().add( child2 );
entityManager.persist( parent );
return parent.getId();
} );
// Rev 2
doInJPA( this::entityManagerFactory, entityManager -> {
final Parent parent = entityManager.find( Parent.class, parentId );
final Child child = new Child();
child.setId( 3 );
child.setIndex( 3 );
child.setIndex2( 3 );
child.setParent( parent );
parent.getChildren().add( child );
entityManager.merge( parent );
} );
// Rev 3
doInJPA( this::entityManagerFactory, entityManager -> {
final Parent parent = entityManager.find( Parent.class, parentId );
parent.getChildren().removeIf( c -> c.getIndex() == 2 );
entityManager.merge( parent );
} );
// Rev 4
doInJPA( this::entityManagerFactory, entityManager -> {
final Parent parent = entityManager.find( Parent.class, parentId );
parent.getChildren().clear();
entityManager.merge( parent );
} );
}
@Test
public void testRevisionCounts() {
assertEquals( Arrays.asList( 1, 2, 3, 4 ), getAuditReader().getRevisions( Parent.class, this.parentId ) );
assertEquals( Arrays.asList( 1, 4 ), getAuditReader().getRevisions( Child.class, 1 ) );
assertEquals( Arrays.asList( 1, 3 ), getAuditReader().getRevisions( Child.class, 2 ) );
assertEquals( Arrays.asList( 2, 4 ), getAuditReader().getRevisions( Child.class, 3 ) );
}
@Test
public void testRevision1History() {
final Parent parent = getAuditReader().find( Parent.class, this.parentId, 1 );
assertNotNull( parent );
assertTrue( !parent.getChildren().isEmpty() );
assertEquals( 2, parent.getChildren().size() );
assertEquals( Arrays.asList( new Child( 1, 1 ), new Child( 2, 2 ) ), parent.getChildren() );
}
@Test
public void testRevision2History() {
final Parent parent = getAuditReader().find( Parent.class, this.parentId, 2 );
assertNotNull( parent );
assertTrue( !parent.getChildren().isEmpty() );
assertEquals( 3, parent.getChildren().size() );
assertEquals( Arrays.asList( new Child( 1, 1 ), new Child( 2, 2 ), new Child( 3, 3 ) ), parent.getChildren() );
}
@Test
public void testRevision3History() {
final Parent parent = getAuditReader().find( Parent.class, this.parentId, 3 );
assertNotNull( parent );
assertTrue( !parent.getChildren().isEmpty() );
assertEquals( 2, parent.getChildren().size() );
assertEquals( Arrays.asList( new Child( 1, 1 ), new Child( 3, 3 ) ), parent.getChildren() );
}
@Test
public void testRevision4History() {
final Parent parent = getAuditReader().find( Parent.class, this.parentId, 4 );
assertNotNull( parent );
assertTrue( parent.getChildren().isEmpty() );
}
}

View File

@ -0,0 +1,343 @@
/*
* 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.query;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OrderBy;
import org.hibernate.envers.Audited;
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
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.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* Test the use of the {@link OrderBy} annotation on a map-based element-collection
* that uses entities for the key and value.
*
* This mapping and association invokes the use of the ThreeEntityQueryGenerator which
* we want to verify orders the collection results properly.
*
* It's worth noting that a mapping like this orders the collection based on the value
* and not the key.
*
* @author Chris Cranford
*/
@TestForIssue(jiraKey = "HHH-12992")
public class OrderByThreeEntityTest extends BaseEnversJPAFunctionalTestCase {
@Entity(name = "Container")
@Audited
public static class Container {
@Id
@GeneratedValue
private Integer id;
@ElementCollection
@OrderBy("value desc")
private Map<Key, Item> data = new HashMap<>();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Map<Key, Item> getData() {
return data;
}
public void setData(Map<Key, Item> data) {
this.data = data;
}
}
@Entity(name = "Key")
@Audited
public static class Key {
@Id
private Integer id;
private String value;
public Key() {
}
public Key(Integer id, String value) {
this.id = id;
this.value = value;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
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;
}
Key key = (Key) o;
return Objects.equals( id, key.id ) &&
Objects.equals( value, key.value );
}
@Override
public int hashCode() {
return Objects.hash( id, value );
}
@Override
public String toString() {
return "Key{" +
"id=" + id +
", value='" + value + '\'' +
'}';
}
}
@Entity(name = "Item")
@Audited
public static class Item {
@Id
private Integer id;
private String value;
public Item() {
}
public Item(Integer id, String value) {
this.id = id;
this.value = value;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
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;
}
Item item = (Item) o;
return Objects.equals( id, item.id ) &&
Objects.equals( value, item.value );
}
@Override
public int hashCode() {
return Objects.hash( id, value );
}
@Override
public String toString() {
return "Item{" +
"id=" + id +
", value='" + value + '\'' +
'}';
}
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { Container.class, Key.class, Item.class };
}
private Integer containerId;
@Test
public void initData() {
// Rev 1
this.containerId = doInJPA( this::entityManagerFactory, entityManager -> {
final Container container = new Container();
final Key key1 = new Key( 1, "A" );
final Key key2 = new Key( 2, "B" );
final Item item1 = new Item( 1, "I1" );
final Item item2 = new Item( 2, "I2" );
entityManager.persist( item1 );
entityManager.persist( item2 );
entityManager.persist( key1 );
entityManager.persist( key2 );
container.getData().put( key1, item2 );
container.getData().put( key2, item1 );
entityManager.persist( container );
return container.getId();
} );
// Rev 2
doInJPA( this::entityManagerFactory, entityManager -> {
final Container container = entityManager.find( Container.class, containerId );
final Key key = new Key( 3, "C" );
final Item item = new Item( 3, "I3" );
entityManager.persist( key );
entityManager.persist( item );
container.getData().put( key, item );
entityManager.merge( container );
} );
// Rev 3
doInJPA( this::entityManagerFactory, entityManager -> {
final Container container = entityManager.find( Container.class, containerId );
container.getData().keySet().forEach(
key -> {
if ( "B".equals( key.getValue() ) ) {
final Item item = container.getData().get( key );
container.getData().remove( key );
entityManager.remove( key );
entityManager.remove( item );
}
}
);
entityManager.merge( container );
} );
// Rev 4
doInJPA( this::entityManagerFactory, entityManager -> {
final Container container = entityManager.find( Container.class, containerId );
container.getData().entrySet().forEach(
entry -> {
entityManager.remove( entry.getKey() );
entityManager.remove( entry.getValue() );
}
);
container.getData().clear();
entityManager.merge( container );
} );
}
@Test
public void testRevisionCounts() {
assertEquals( Arrays.asList( 1, 2, 3, 4 ), getAuditReader().getRevisions( Container.class, this.containerId ) );
assertEquals( Arrays.asList( 1, 4 ), getAuditReader().getRevisions( Key.class, 1 ) );
assertEquals( Arrays.asList( 1, 3 ), getAuditReader().getRevisions( Key.class, 2 ) );
assertEquals( Arrays.asList( 2, 4 ), getAuditReader().getRevisions( Key.class, 3 ) );
assertEquals( Arrays.asList( 1, 3 ), getAuditReader().getRevisions( Item.class, 1 ) );
assertEquals( Arrays.asList( 1, 4 ), getAuditReader().getRevisions( Item.class, 2 ) );
assertEquals( Arrays.asList( 2, 4 ), getAuditReader().getRevisions( Item.class, 3 ) );
}
@Test
public void testRevision1History() {
final Container container = getAuditReader().find( Container.class, this.containerId, 1 );
assertNotNull( container );
assertTrue( !container.getData().isEmpty() );
assertEquals( 2, container.getData().size() );
final Iterator<Map.Entry<Key, Item>> iterator = container.getData().entrySet().iterator();
final Map.Entry<Key, Item> first = iterator.next();
assertEquals( new Key( 1, "A" ), first.getKey() );
assertEquals( new Item( 2, "I2" ), first.getValue() );
final Map.Entry<Key, Item> second = iterator.next();
assertEquals( new Key( 2, "B" ), second.getKey() );
assertEquals( new Item( 1, "I1" ), second.getValue() );
}
@Test
public void testRevision2History() {
final Container container = getAuditReader().find( Container.class, this.containerId, 2 );
assertNotNull( container );
assertTrue( !container.getData().isEmpty() );
assertEquals( 3, container.getData().size() );
final Iterator<Map.Entry<Key, Item>> iterator = container.getData().entrySet().iterator();
final Map.Entry<Key, Item> first = iterator.next();
assertEquals( new Key( 3, "C" ), first.getKey() );
assertEquals( new Item( 3, "I3" ), first.getValue() );
final Map.Entry<Key, Item> second = iterator.next();
assertEquals( new Key( 1, "A" ), second.getKey() );
assertEquals( new Item( 2, "I2" ), second.getValue() );
final Map.Entry<Key, Item> third = iterator.next();
assertEquals( new Key( 2, "B" ), third.getKey() );
assertEquals( new Item( 1, "I1" ), third.getValue() );
}
@Test
public void testRevision3History() {
final Container container = getAuditReader().find( Container.class, this.containerId, 3 );
assertNotNull( container );
assertTrue( !container.getData().isEmpty() );
assertEquals( 2, container.getData().size() );
final Iterator<Map.Entry<Key, Item>> iterator = container.getData().entrySet().iterator();
final Map.Entry<Key, Item> first = iterator.next();
assertEquals( new Key( 3, "C" ), first.getKey() );
assertEquals( new Item( 3, "I3" ), first.getValue() );
final Map.Entry<Key, Item> second = iterator.next();
assertEquals( new Key( 1, "A" ), second.getKey() );
assertEquals( new Item( 2, "I2" ), second.getValue() );
}
@Test
public void testRevision4History() {
final Container container = getAuditReader().find( Container.class, this.containerId, 4 );
assertNotNull( container );
assertTrue( container.getData().isEmpty() );
}
}

View File

@ -0,0 +1,269 @@
/*
* 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.query;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OrderBy;
import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.envers.Audited;
import org.hibernate.envers.RelationTargetAuditMode;
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
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.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* Test the use of the {@link OrderBy} annotation on a many-to-many collection
* where the two entities are audited but the association is not.
*
* The double audited entity but no association audited mapping invokes the use
* of the TwoEntityOneAuditedGenerator which we want to verify orders the
* collection results properly.
*
* @author Chris Cranford
*/
@TestForIssue(jiraKey = "HHH-12992")
public class OrderByTwoEntityOneAuditedTest extends BaseEnversJPAFunctionalTestCase {
@Entity(name = "Parent")
@Audited
public static class Parent {
@Id
@GeneratedValue
private Integer id;
@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
@ManyToMany(mappedBy = "parents", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@OrderBy("index, index2 desc")
@Fetch(FetchMode.SELECT)
@BatchSize(size = 100)
private List<Child> children = new ArrayList<>();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public List<Child> getChildren() {
return children;
}
public void setChildren(List<Child> children) {
this.children = children;
}
}
@Entity(name = "Child")
@Audited
public static class Child {
@Id
private Integer id;
private Integer index;
private Integer index2;
@ManyToMany
private List<Parent> parents = new ArrayList<>();
public Child() {
}
public Child(Integer id, Integer index) {
this.id = id;
this.index = index;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getIndex() {
return index;
}
public void setIndex(Integer index) {
this.index = index;
}
public Integer getIndex2() {
return index2;
}
public void setIndex2(Integer index2) {
this.index2 = index2;
}
public List<Parent> getParents() {
return parents;
}
public void setParents(List<Parent> parents) {
this.parents = parents;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
Child child = (Child) o;
return Objects.equals( id, child.id ) &&
Objects.equals( index, child.index );
}
@Override
public int hashCode() {
return Objects.hash( id, index );
}
@Override
public String toString() {
return "Child{" +
"id=" + id +
", index=" + index +
'}';
}
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { Parent.class, Child.class };
}
private Integer parentId;
@Test
public void initData() {
// Rev 1
this.parentId = doInJPA( this::entityManagerFactory, entityManager -> {
final Parent parent = new Parent();
final Child child1 = new Child();
child1.setId( 1 );
child1.setIndex( 1 );
child1.setIndex2( 1 );
child1.getParents().add( parent );
parent.getChildren().add( child1 );
final Child child2 = new Child();
child2.setId( 2 );
child2.setIndex( 2 );
child2.setIndex2( 2 );
child2.getParents().add( parent );
parent.getChildren().add( child2 );
entityManager.persist( parent );
return parent.getId();
} );
// Rev 2
doInJPA( this::entityManagerFactory, entityManager -> {
final Parent parent = entityManager.find( Parent.class, parentId );
final Child child = new Child();
child.setId( 3 );
child.setIndex( 3 );
child.setIndex2( 3 );
child.getParents().add( parent );
parent.getChildren().add( child );
entityManager.merge( parent );
} );
// Rev 3
doInJPA( this::entityManagerFactory, entityManager -> {
final Parent parent = entityManager.find( Parent.class, parentId );
parent.getChildren().removeIf( c -> {
if ( c.getIndex() == 2 ) {
c.getParents().remove( parent );
return true;
}
return false;
} );
entityManager.merge( parent );
} );
// Rev 4
doInJPA( this::entityManagerFactory, entityManager -> {
final Parent parent = entityManager.find( Parent.class, parentId );
parent.getChildren().forEach( c -> c.getParents().clear() );
parent.getChildren().clear();
entityManager.merge( parent );
} );
}
@Test
public void testRevisionCounts() {
assertEquals( Arrays.asList( 1, 2, 3, 4 ), getAuditReader().getRevisions( Parent.class, this.parentId ) );
assertEquals( Arrays.asList( 1, 4 ), getAuditReader().getRevisions( Child.class, 1 ) );
assertEquals( Arrays.asList( 1, 3 ), getAuditReader().getRevisions( Child.class, 2 ) );
assertEquals( Arrays.asList( 2, 4 ), getAuditReader().getRevisions( Child.class, 3 ) );
}
@Test
public void testRevision1History() {
final Parent parent = getAuditReader().find( Parent.class, this.parentId, 1 );
assertNotNull( parent );
assertTrue( !parent.getChildren().isEmpty() );
assertEquals( 2, parent.getChildren().size() );
assertEquals( Arrays.asList( new Child( 1, 1 ), new Child( 2, 2 ) ), parent.getChildren() );
}
@Test
public void testRevision2History() {
final Parent parent = getAuditReader().find( Parent.class, this.parentId, 2 );
assertNotNull( parent );
assertTrue( !parent.getChildren().isEmpty() );
assertEquals( 3, parent.getChildren().size() );
assertEquals( Arrays.asList( new Child( 1, 1 ), new Child( 2, 2 ), new Child( 3, 3 ) ), parent.getChildren() );
}
@Test
public void testRevision3History() {
final Parent parent = getAuditReader().find( Parent.class, this.parentId, 3 );
assertNotNull( parent );
assertTrue( !parent.getChildren().isEmpty() );
assertEquals( 2, parent.getChildren().size() );
assertEquals( Arrays.asList( new Child( 1, 1 ), new Child( 3, 3 ) ), parent.getChildren() );
}
@Test
public void testRevision4History() {
final Parent parent = getAuditReader().find( Parent.class, this.parentId, 4 );
assertNotNull( parent );
assertTrue( parent.getChildren().isEmpty() );
}
}

View File

@ -0,0 +1,269 @@
/*
* 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.query;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OrderBy;
import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.envers.AuditMappedBy;
import org.hibernate.envers.Audited;
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
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.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* Test the use of the {@link OrderBy} annotation on a many-to-many collection
* where the two entities and the association are audited.
*
* The double auditd entity and association mapping invokes the use of the
* TwoEntityQueryGenerator which we want to verify orders the collection
* results properly.
*
* @author Chris Cranford
*/
@TestForIssue(jiraKey = "HHH-12992")
public class OrderByTwoEntityTest extends BaseEnversJPAFunctionalTestCase {
@Entity(name = "Parent")
@Audited
public static class Parent {
@Id
@GeneratedValue
private Integer id;
@ManyToMany(mappedBy = "parents", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@OrderBy("index, index2 desc")
@AuditMappedBy(mappedBy = "parents", positionMappedBy = "index")
@Fetch(FetchMode.SELECT)
@BatchSize(size = 100)
private List<Child> children = new ArrayList<>();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public List<Child> getChildren() {
return children;
}
public void setChildren(List<Child> children) {
this.children = children;
}
}
@Entity(name = "Child")
@Audited
public static class Child {
@Id
private Integer id;
private Integer index;
private Integer index2;
@ManyToMany
private List<Parent> parents = new ArrayList<>();
public Child() {
}
public Child(Integer id, Integer index) {
this.id = id;
this.index = index;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getIndex() {
return index;
}
public void setIndex(Integer index) {
this.index = index;
}
public Integer getIndex2() {
return index2;
}
public void setIndex2(Integer index2) {
this.index2 = index2;
}
public List<Parent> getParents() {
return parents;
}
public void setParents(List<Parent> parents) {
this.parents = parents;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
Child child = (Child) o;
return Objects.equals( id, child.id ) &&
Objects.equals( index, child.index );
}
@Override
public int hashCode() {
return Objects.hash( id, index );
}
@Override
public String toString() {
return "Child{" +
"id=" + id +
", index=" + index +
'}';
}
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { Parent.class, Child.class };
}
private Integer parentId;
@Test
public void initData() {
// Rev 1
this.parentId = doInJPA( this::entityManagerFactory, entityManager -> {
final Parent parent = new Parent();
final Child child1 = new Child();
child1.setId( 1 );
child1.setIndex( 1 );
child1.setIndex2( 1 );
child1.getParents().add( parent );
parent.getChildren().add( child1 );
final Child child2 = new Child();
child2.setId( 2 );
child2.setIndex( 2 );
child2.setIndex2( 2 );
child2.getParents().add( parent );
parent.getChildren().add( child2 );
entityManager.persist( parent );
return parent.getId();
} );
// Rev 2
doInJPA( this::entityManagerFactory, entityManager -> {
final Parent parent = entityManager.find( Parent.class, parentId );
final Child child = new Child();
child.setId( 3 );
child.setIndex( 3 );
child.setIndex2( 3 );
child.getParents().add( parent );
parent.getChildren().add( child );
entityManager.merge( parent );
} );
// Rev 3
doInJPA( this::entityManagerFactory, entityManager -> {
final Parent parent = entityManager.find( Parent.class, parentId );
parent.getChildren().removeIf( c -> {
if ( c.getIndex() == 2 ) {
c.getParents().remove( parent );
return true;
}
return false;
} );
entityManager.merge( parent );
} );
// Rev 4
doInJPA( this::entityManagerFactory, entityManager -> {
final Parent parent = entityManager.find( Parent.class, parentId );
parent.getChildren().forEach( c -> c.getParents().clear() );
parent.getChildren().clear();
entityManager.merge( parent );
} );
}
@Test
public void testRevisionCounts() {
assertEquals( Arrays.asList( 1, 2, 3, 4 ), getAuditReader().getRevisions( Parent.class, this.parentId ) );
assertEquals( Arrays.asList( 1, 4 ), getAuditReader().getRevisions( Child.class, 1 ) );
assertEquals( Arrays.asList( 1, 3 ), getAuditReader().getRevisions( Child.class, 2 ) );
assertEquals( Arrays.asList( 2, 4 ), getAuditReader().getRevisions( Child.class, 3 ) );
}
@Test
public void testRevision1History() {
final Parent parent = getAuditReader().find( Parent.class, this.parentId, 1 );
assertNotNull( parent );
assertTrue( !parent.getChildren().isEmpty() );
assertEquals( 2, parent.getChildren().size() );
assertEquals( Arrays.asList( new Child( 1, 1 ), new Child( 2, 2 ) ), parent.getChildren() );
}
@Test
public void testRevision2History() {
final Parent parent = getAuditReader().find( Parent.class, this.parentId, 2 );
assertNotNull( parent );
assertTrue( !parent.getChildren().isEmpty() );
assertEquals( 3, parent.getChildren().size() );
assertEquals( Arrays.asList( new Child( 1, 1 ), new Child( 2, 2 ), new Child( 3, 3 ) ), parent.getChildren() );
}
@Test
public void testRevision3History() {
final Parent parent = getAuditReader().find( Parent.class, this.parentId, 3 );
assertNotNull( parent );
assertTrue( !parent.getChildren().isEmpty() );
assertEquals( 2, parent.getChildren().size() );
assertEquals( Arrays.asList( new Child( 1, 1 ), new Child( 3, 3 ) ), parent.getChildren() );
}
@Test
public void testRevision4History() {
final Parent parent = getAuditReader().find( Parent.class, this.parentId, 4 );
assertNotNull( parent );
assertTrue( parent.getChildren().isEmpty() );
}
}