diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/Item.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/Item.java new file mode 100644 index 0000000000..097ba9dac3 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/Item.java @@ -0,0 +1,74 @@ +/* + * 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.envers.test.integration.collection.embeddable; + +import javax.persistence.Embeddable; +import javax.persistence.ManyToOne; + +import org.hibernate.envers.Audited; +import org.hibernate.envers.RelationTargetAuditMode; + +/** + * @author Chris Cranford + */ +@Embeddable +@Audited +public class Item { + private String name; + + @ManyToOne + @Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED) + private Type type; + + Item() { + + } + + Item(String name, Type type) { + this.name = name; + this.type = type; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + @Override + public int hashCode() { + int result = name != null ? name.hashCode() : 0; + result = 31 * result + ( type != null ? type.hashCode() : 0 ); + return result; + } + + @Override + public boolean equals(Object object) { + if ( this == object ) { + return true; + } + if ( object == null || getClass() != object.getClass() ) { + return false; + } + + Item that = (Item) object; + if ( name != null ? !name.equals( that.name ) : that.name != null ) { + return false; + } + return !( type != null ? !type.equals( that.type ) : that.type != null ); + } +} diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/NullPointerExceptionTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/NullPointerExceptionTest.java new file mode 100644 index 0000000000..98d2911349 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/NullPointerExceptionTest.java @@ -0,0 +1,113 @@ +/* + * 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.envers.test.integration.collection.embeddable; + +import java.util.Arrays; +import java.util.Map; + +import javax.persistence.EntityManager; + +import org.hibernate.envers.configuration.EnversSettings; +import org.hibernate.envers.strategy.ValidityAuditStrategy; +import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; +import org.hibernate.envers.test.Priority; +import org.hibernate.testing.TestForIssue; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @author Chris Cranford + */ +@TestForIssue(jiraKey = "HHH-11215") +public class NullPointerExceptionTest extends BaseEnversJPAFunctionalTestCase { + private Integer productId; + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { Product.class, Type.class }; + } + + @Override + protected void addConfigOptions(Map options) { + super.addConfigOptions( options ); + options.put( EnversSettings.AUDIT_STRATEGY, ValidityAuditStrategy.class.getName() ); + } + + @Test + @Priority(10) + public void initData() { + // Revision 1 + EntityManager entityManager = getOrCreateEntityManager(); + entityManager.getTransaction().begin(); + { + Product product = new Product( 1 , "Test" ); + product.getItems().add( new Item( "bread", null ) ); + entityManager.persist( product ); + this.productId = product.getId(); + } + entityManager.getTransaction().commit(); + entityManager.close(); + + // Revision 2 + entityManager = getOrCreateEntityManager(); + entityManager.getTransaction().begin(); + { + Type type = new Type( 2, "T2" ); + entityManager.persist( type ); + Product product = entityManager.find( Product.class, productId ); + product.getItems().add( new Item( "bread2", type ) ); + entityManager.merge( product ); + } + entityManager.getTransaction().commit(); + entityManager.close(); + + // Revision 3 + entityManager = getOrCreateEntityManager(); + entityManager.getTransaction().begin(); + { + Product product = entityManager.find( Product.class, productId ); + product.getItems().remove( 0 ); + entityManager.merge( product ); + } + entityManager.getTransaction().commit(); + entityManager.close(); + } + + @Test + public void testRevisionCounts() { + assertEquals( Arrays.asList( 1, 2, 3 ), getAuditReader().getRevisions( Product.class, productId ) ); + assertEquals( 1, getAuditReader().find( Product.class, productId, 1 ).getItems().size() ); + assertEquals( 2, getAuditReader().find( Product.class, productId, 2 ).getItems().size() ); + assertEquals( 1, getAuditReader().find( Product.class, productId, 3 ).getItems().size() ); + } + + @Test + public void testRevision1() { + final Product product = getAuditReader().find( Product.class, productId, 1 ); + assertEquals( 1, product.getItems().size() ); + assertEquals( "bread", product.getItems().get( 0 ).getName() ); + } + + @Test + public void testRevision2() { + final Product product = getAuditReader().find( Product.class, productId, 2 ); + assertEquals( 2, product.getItems().size() ); + assertEquals( "bread", product.getItems().get( 0 ).getName() ); + assertEquals( "bread2", product.getItems().get( 1 ).getName() ); + assertEquals( new Type( 2, "T2" ), product.getItems().get( 1 ).getType() ); + } + + @Test + public void testRevision3() { + final Product product = getAuditReader().find( Product.class, productId, 3 ); + assertEquals( 1, product.getItems().size() ); + assertEquals( "bread2", product.getItems().get( 0 ).getName() ); + assertEquals( new Type( 2, "T2" ), product.getItems().get( 0 ).getType() ); + } +} + diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/Product.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/Product.java new file mode 100644 index 0000000000..b97177d05e --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/Product.java @@ -0,0 +1,96 @@ +/* + * 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.envers.test.integration.collection.embeddable; + +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.CollectionTable; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OrderColumn; + +import org.hibernate.envers.Audited; + +/** + * @author Chris Cranford + */ +@Entity +@Audited +public class Product { + @Id + private Integer id; + + private String name; + + @ElementCollection + @CollectionTable(name = "items", joinColumns = @JoinColumn(name = "productId")) + @OrderColumn(name = "position") + private List items = new ArrayList(); + + Product() { + + } + + Product(Integer id, String name) { + this.id = id; + this.name = name; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } + + @Override + public int hashCode() { + int result = id != null ? id.hashCode() : 0; + result = 31 * result + ( name != null ? name.hashCode() : 0 ); + result = 31 * result + ( items != null ? items.hashCode() : 0 ); + return result; + } + + @Override + public boolean equals(Object object) { + if ( this == object ) { + return true; + } + if ( object == null | getClass() != object.getClass() ) { + return false; + } + + Product that = (Product) object; + if ( id != null ? !id.equals( that.id ) : that.id != null ) { + return false; + } + if ( name != null ? !name.equals( that.name ) : that.name != null ) { + return false; + } + return !( items != null ? !items.equals( that.items ) : that.items != null ); + } +} diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/Type.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/Type.java new file mode 100644 index 0000000000..f16cd8c7f0 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/collection/embeddable/Type.java @@ -0,0 +1,75 @@ +/* + * 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.envers.test.integration.collection.embeddable; + +import javax.persistence.Entity; +import javax.persistence.Id; + +import org.hibernate.annotations.Immutable; + +/** + * @author Chris Cranford + */ +@Entity +@Immutable +public class Type { + @Id + private Integer id; + private String name; + + Type() { + + } + + Type(Integer id) { + this( id, null ); + } + + Type(Integer id, String name) { + this.id = id; + this.name = name; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public int hashCode() { + int result = id != null ? id.hashCode() : 0; + result = 31 * result + ( name != null ? name.hashCode() : 0 ); + return result; + } + + @Override + public boolean equals(Object object) { + if ( this == object ) { + return true; + } + if ( object == null || getClass() != object.getClass() ) { + return false; + } + + Type that = (Type) object; + if ( id != null ? !id.equals( that.id ) : that.id != null ) { + return false; + } + return !( name != null ? !name.equals( that.name ) : that.name != null ); + } +}