/* * 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.hashcode; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import javax.persistence.ElementCollection; import javax.persistence.Embeddable; import javax.persistence.Entity; import javax.persistence.EntityManager; import javax.persistence.GeneratedValue; import javax.persistence.Id; import org.hibernate.envers.Audited; import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.tools.TestTools; import org.hibernate.testing.TestForIssue; import org.junit.Test; import static org.junit.Assert.assertEquals; /** * @author Chris Cranford */ @TestForIssue(jiraKey = "HHH-11063") public class ComponentCollectionHashcodeChangeTest extends BaseEnversJPAFunctionalTestCase { private Integer id; @Override protected Class<?>[] getAnnotatedClasses() { return new Class<?>[] { ComponentEntity.class, Component.class }; } @Test @Priority(10) public void initData() { EntityManager entityManager = getEntityManager(); try { // Revision 1 - Create entity with 2 components entityManager.getTransaction().begin(); Component component1 = new Component(); component1.setName( "User1" ); component1.setData( "Test1" ); Component component2 = new Component(); component2.setName( "User2" ); component2.setData( "Test2" ); ComponentEntity entity = new ComponentEntity(); entity.getComponents().add( component1 ); entity.getComponents().add( component2 ); entityManager.persist( entity ); entityManager.getTransaction().commit(); id = entity.getId(); // Revision 2 - Change component name inline. // This effectively changes equality and hash of elment. entityManager.getTransaction().begin(); component1.setName( "User1-Inline" ); entityManager.merge( entity ); entityManager.getTransaction().commit(); // Revision 3 - Remove and add entity with same name. entityManager.getTransaction().begin(); entity.getComponents().remove( component2 ); Component component3 = new Component(); component3.setName( "User2" ); component3.setData( "Test3" ); entity.getComponents().add( component3 ); entityManager.merge( entity ); entityManager.getTransaction().commit(); } catch ( Exception e ) { if ( entityManager.getTransaction().isActive() ) { entityManager.getTransaction().rollback(); } } finally { entityManager.close(); } } @Test public void testRevisionCounts() { assertEquals( Arrays.asList( 1, 2, 3 ), getAuditReader().getRevisions( ComponentEntity.class, id ) ); } @Test public void testCollectionHistory() { final ComponentEntity rev1 = getAuditReader().find( ComponentEntity.class, id, 1 ); assertEquals( 2, rev1.getComponents().size() ); assertEquals( TestTools.makeSet( new Component( "User1", "Test1" ), new Component( "User2", "Test2" ) ), rev1.getComponents() ); final ComponentEntity rev2 = getAuditReader().find( ComponentEntity.class, id, 2 ); assertEquals( 2, rev2.getComponents().size() ); assertEquals( TestTools.makeSet( new Component( "User1-Inline", "Test1" ), new Component( "User2", "Test2" ) ), rev2.getComponents() ); final ComponentEntity rev3 = getAuditReader().find( ComponentEntity.class, id, 3 ); assertEquals( 2, rev3.getComponents().size() ); assertEquals( TestTools.makeSet( new Component( "User1-Inline", "Test1" ), new Component( "User2", "Test3" ) ), rev3.getComponents() ); } @Entity(name = "ComponentEntity") @Audited public static class ComponentEntity { @Id @GeneratedValue private Integer id; @ElementCollection private Set<Component> components = new HashSet<Component>(); public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Set<Component> getComponents() { return components; } public void setComponents(Set<Component> components) { this.components = components; } } @Audited @Embeddable public static class Component { private String name; private String data; Component() { } Component(String name, String data) { this.name = name; this.data = data; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getData() { return data; } public void setData(String data) { this.data = data; } @Override public int hashCode() { return ( name != null ? name.hashCode() : 0 ); } @Override public boolean equals(Object object) { if ( object == this ) { return true; } if ( object == null || !( object instanceof Component ) ) { return false; } Component that = (Component) object; return !( name != null ? !name.equals( that.name ) : that.name != null ); } } }