HHH-3602: bug fix with test (generating a CollectionChangeWorkUnit for the proper entity in case a relation is owned by a superclass, when inheritance is used)
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@15565 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
edf3822cfb
commit
044efaeeb3
|
@ -41,6 +41,7 @@ import org.hibernate.envers.tools.Tools;
|
|||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
import org.hibernate.engine.CollectionEntry;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.event.AbstractCollectionEvent;
|
||||
import org.hibernate.event.Initializable;
|
||||
import org.hibernate.event.PostCollectionRecreateEvent;
|
||||
|
@ -66,7 +67,8 @@ public class AuditEventListener implements PostInsertEventListener, PostUpdateEv
|
|||
private AuditConfiguration verCfg;
|
||||
|
||||
private void generateBidirectionalCollectionChangeWorkUnits(AuditSync verSync, EntityPersister entityPersister,
|
||||
String entityName, Object[] newState, Object[] oldState) {
|
||||
String entityName, Object[] newState, Object[] oldState,
|
||||
SessionImplementor session) {
|
||||
// Checking if this is enabled in configuration ...
|
||||
if (!verCfg.getGlobalCfg().isGenerateRevisionsForCollections()) {
|
||||
return;
|
||||
|
@ -86,18 +88,26 @@ public class AuditEventListener implements PostInsertEventListener, PostUpdateEv
|
|||
Object newValue = newState == null ? null : newState[i];
|
||||
|
||||
if (!Tools.objectsEqual(oldValue, newValue)) {
|
||||
IdMapper idMapper = verCfg.getEntCfg().get(relDesc.getToEntityName()).getIdMapper();
|
||||
|
||||
// We have to generate changes both in the old collection (size decreses) and new collection
|
||||
// (size increases).
|
||||
if (newValue != null) {
|
||||
// relDesc.getToEntityName() doesn't always return the entity name of the value - in case
|
||||
// of subclasses, this will be root class, no the actual class. So it can't be used here.
|
||||
String toEntityName = session.guessEntityName(newValue);
|
||||
|
||||
IdMapper idMapper = verCfg.getEntCfg().get(toEntityName).getIdMapper();
|
||||
|
||||
Serializable id = (Serializable) idMapper.mapToIdFromEntity(newValue);
|
||||
verSync.addWorkUnit(new CollectionChangeWorkUnit(relDesc.getToEntityName(), verCfg, id, newValue));
|
||||
verSync.addWorkUnit(new CollectionChangeWorkUnit(toEntityName, verCfg, id, newValue));
|
||||
}
|
||||
|
||||
if (oldValue != null) {
|
||||
String toEntityName = session.guessEntityName(oldValue);
|
||||
|
||||
IdMapper idMapper = verCfg.getEntCfg().get(toEntityName).getIdMapper();
|
||||
|
||||
Serializable id = (Serializable) idMapper.mapToIdFromEntity(oldValue);
|
||||
verSync.addWorkUnit(new CollectionChangeWorkUnit(relDesc.getToEntityName(), verCfg, id, oldValue));
|
||||
verSync.addWorkUnit(new CollectionChangeWorkUnit(toEntityName, verCfg, id, oldValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +123,8 @@ public class AuditEventListener implements PostInsertEventListener, PostUpdateEv
|
|||
verSync.addWorkUnit(new AddWorkUnit(event.getPersister().getEntityName(), verCfg, event.getId(),
|
||||
event.getPersister(), event.getState()));
|
||||
|
||||
generateBidirectionalCollectionChangeWorkUnits(verSync, event.getPersister(), entityName, event.getState(), null);
|
||||
generateBidirectionalCollectionChangeWorkUnits(verSync, event.getPersister(), entityName, event.getState(),
|
||||
null, event.getSession());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,7 +137,8 @@ public class AuditEventListener implements PostInsertEventListener, PostUpdateEv
|
|||
verSync.addWorkUnit(new ModWorkUnit(event.getPersister().getEntityName(), verCfg, event.getId(),
|
||||
event.getPersister(), event.getState(), event.getOldState()));
|
||||
|
||||
generateBidirectionalCollectionChangeWorkUnits(verSync, event.getPersister(), entityName, event.getState(), event.getOldState());
|
||||
generateBidirectionalCollectionChangeWorkUnits(verSync, event.getPersister(), entityName, event.getState(),
|
||||
event.getOldState(), event.getSession());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,7 +150,8 @@ public class AuditEventListener implements PostInsertEventListener, PostUpdateEv
|
|||
|
||||
verSync.addWorkUnit(new DelWorkUnit(event.getPersister().getEntityName(), verCfg, event.getId()));
|
||||
|
||||
generateBidirectionalCollectionChangeWorkUnits(verSync, event.getPersister(), entityName, null, event.getDeletedState());
|
||||
generateBidirectionalCollectionChangeWorkUnits(verSync, event.getPersister(), entityName, null,
|
||||
event.getDeletedState(), event.getSession());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
package org.hibernate.envers.test.integration.inheritance.single.inheritedrelation;
|
||||
|
||||
import org.hibernate.envers.Audited;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
@Entity
|
||||
@Audited
|
||||
public class Address implements Serializable {
|
||||
@Id @GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String address1;
|
||||
|
||||
@ManyToOne
|
||||
private Contact contact;
|
||||
|
||||
public Address() {
|
||||
}
|
||||
|
||||
public Address(Long id, String address1) {
|
||||
this.id = id;
|
||||
this.address1 = address1;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getAddress1() {
|
||||
return address1;
|
||||
}
|
||||
|
||||
public void setAddress1(String address1) {
|
||||
this.address1 = address1;
|
||||
}
|
||||
|
||||
public Contact getContact() {
|
||||
return contact;
|
||||
}
|
||||
|
||||
public void setContact(Contact contact) {
|
||||
this.contact = contact;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Address)) return false;
|
||||
|
||||
Address address = (Address) o;
|
||||
|
||||
if (address1 != null ? !address1.equals(address.address1) : address.address1 != null) return false;
|
||||
if (id != null ? !id.equals(address.id) : address.id != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int result;
|
||||
result = (id != null ? id.hashCode() : 0);
|
||||
result = 31 * result + (address1 != null ? address1.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package org.hibernate.envers.test.integration.inheritance.single.inheritedrelation;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.DiscriminatorColumn;
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
import org.hibernate.envers.Audited;
|
||||
|
||||
@Entity
|
||||
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
|
||||
@DiscriminatorValue("Contact")
|
||||
@DiscriminatorColumn(name="contactType",discriminatorType=javax.persistence.DiscriminatorType.STRING)
|
||||
@Audited
|
||||
public class Contact implements Serializable {
|
||||
@Id @GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String email;
|
||||
|
||||
@OneToMany(mappedBy="contact")
|
||||
private Set<Address> addresses;
|
||||
|
||||
public Contact() {
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public Set<Address> getAddresses() {
|
||||
return addresses;
|
||||
}
|
||||
public void setAddresses(Set<Address> addresses) {
|
||||
this.addresses = addresses;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package org.hibernate.envers.test.integration.inheritance.single.inheritedrelation;
|
||||
|
||||
import java.util.Arrays;
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.hibernate.envers.test.AbstractEntityTest;
|
||||
import org.hibernate.envers.test.tools.TestTools;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import org.hibernate.ejb.Ejb3Configuration;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class InheritedBidirectional extends AbstractEntityTest {
|
||||
private Long pc_id;
|
||||
private Long a1_id;
|
||||
private Long a2_id;
|
||||
|
||||
public void configure(Ejb3Configuration cfg) {
|
||||
cfg.addAnnotatedClass(Address.class);
|
||||
cfg.addAnnotatedClass(Contact.class);
|
||||
cfg.addAnnotatedClass(PersonalContact.class);
|
||||
}
|
||||
|
||||
@BeforeClass(dependsOnMethods = "init")
|
||||
public void initData() {
|
||||
EntityManager em = getEntityManager();
|
||||
|
||||
// Rev 1
|
||||
em.getTransaction().begin();
|
||||
|
||||
PersonalContact pc = new PersonalContact();
|
||||
pc.setEmail("e");
|
||||
pc.setFirstname("f");
|
||||
|
||||
Address a1 = new Address();
|
||||
a1.setAddress1("a1");
|
||||
a1.setContact(pc);
|
||||
|
||||
em.persist(pc);
|
||||
em.persist(a1);
|
||||
|
||||
em.getTransaction().commit();
|
||||
|
||||
// Rev 2
|
||||
em.getTransaction().begin();
|
||||
|
||||
pc = em.find(PersonalContact.class, pc.getId());
|
||||
|
||||
Address a2 = new Address();
|
||||
a2.setAddress1("a2");
|
||||
a2.setContact(pc);
|
||||
|
||||
em.persist(a2);
|
||||
|
||||
em.getTransaction().commit();
|
||||
|
||||
//
|
||||
|
||||
pc_id = pc.getId();
|
||||
a1_id = a1.getId();
|
||||
a2_id = a2.getId();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevisionsCounts() {
|
||||
assert Arrays.asList(1, 2).equals(getAuditReader().getRevisions(Contact.class, pc_id));
|
||||
assert Arrays.asList(1, 2).equals(getAuditReader().getRevisions(PersonalContact.class, pc_id));
|
||||
|
||||
assert Arrays.asList(1).equals(getAuditReader().getRevisions(Address.class, a1_id));
|
||||
assert Arrays.asList(1).equals(getAuditReader().getRevisions(Address.class, a1_id));
|
||||
|
||||
assert Arrays.asList(2).equals(getAuditReader().getRevisions(Address.class, a2_id));
|
||||
assert Arrays.asList(2).equals(getAuditReader().getRevisions(Address.class, a2_id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistoryOfContact() {
|
||||
assert getAuditReader().find(Contact.class, pc_id, 1).getAddresses().equals(
|
||||
TestTools.makeSet(new Address(a1_id, "a1")));
|
||||
|
||||
assert getAuditReader().find(Contact.class, pc_id, 2).getAddresses().equals(
|
||||
TestTools.makeSet(new Address(a1_id, "a1"), new Address(a2_id, "a2")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistoryOfPersonalContact() {
|
||||
assert getAuditReader().find(PersonalContact.class, pc_id, 1).getAddresses().equals(
|
||||
TestTools.makeSet(new Address(a1_id, "a1")));
|
||||
|
||||
assert getAuditReader().find(PersonalContact.class, pc_id, 2).getAddresses().equals(
|
||||
TestTools.makeSet(new Address(a1_id, "a1"), new Address(a2_id, "a2")));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package org.hibernate.envers.test.integration.inheritance.single.inheritedrelation;
|
||||
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
import org.hibernate.envers.Audited;
|
||||
|
||||
@Entity
|
||||
@DiscriminatorValue("PersonalContact")
|
||||
@Audited
|
||||
public class PersonalContact extends Contact {
|
||||
private String firstname;
|
||||
|
||||
public String getFirstname() {
|
||||
return firstname;
|
||||
}
|
||||
|
||||
public void setFirstname(String firstname) {
|
||||
this.firstname = firstname;
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@
|
|||
<package name="org.hibernate.envers.test.integration.ids" />
|
||||
<package name="org.hibernate.envers.test.integration.inheritance.single" />
|
||||
<package name="org.hibernate.envers.test.integration.inheritance.single.childrelation" />
|
||||
<package name="org.hibernate.envers.test.integration.inheritance.single.inheritedrelation" />
|
||||
<package name="org.hibernate.envers.test.integration.inheritance.single.relation" />
|
||||
<package name="org.hibernate.envers.test.integration.manytomany" />
|
||||
<package name="org.hibernate.envers.test.integration.manytomany.ternary" />
|
||||
|
|
Loading…
Reference in New Issue