HHH-4010:

- applying patch: allow audited relations to non-audited entities
- doc update

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@17248 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Adam Warski 2009-08-06 18:21:38 +00:00
parent 8465009b4b
commit 5d08386293
15 changed files with 450 additions and 32 deletions

View File

@ -218,4 +218,11 @@
please see <xref linkend="exceptions"/> for a description of the additional
<literal>@AuditJoinTable</literal> annotation that you'll probably want to use.
</para>
<para>
If you want to audit a relation, where the target entity is not audited (that is the case for example with
dictionary-like entities, which don't change and don't have to be audited), just annotate it with
<literal>@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)</literal>. Then, when reading historic
versions of your entity, the relation will always point to the "current" related entity.
</para>
</chapter>

View File

@ -32,9 +32,17 @@ import java.lang.annotation.Target;
* When applied to a class, indicates that all of its properties should be audited.
* When applied to a field, indicates that this field should be audited.
* @author Adam Warski (adam at warski dot org)
* @author Tomasz Bech
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
public @interface Audited {
ModificationStore modStore() default ModificationStore.FULL;
/**
* @return Specifies if the entity that is the target of the relation should be audited or not. If not, then when
* reading a historic version an audited entity, the realtion will always point to the "current" entity.
* This is useful for dictionary-like entities, which don't change and don't need to be audited.
*/
RelationTargetAuditMode targetAuditMode() default RelationTargetAuditMode.AUDITED;
}

View File

@ -0,0 +1,32 @@
/*
* 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;
/**
* @author Tomasz Bech
*/
public enum RelationTargetAuditMode {
AUDITED,
NOT_AUDITED
}

View File

@ -84,9 +84,13 @@ public class EntitiesConfigurator {
}
EntityXmlMappingData xmlMappingData = new EntityXmlMappingData();
auditMetaGen.generateFirstPass(pc, auditData, xmlMappingData);
auditMetaGen.generateFirstPass(pc, auditData, xmlMappingData, true);
xmlMappings.put(pc, xmlMappingData);
}
} else {
EntityXmlMappingData xmlMappingData = new EntityXmlMappingData();
auditMetaGen.generateFirstPass(pc, auditData, xmlMappingData, false);
xmlMappings.put(pc, xmlMappingData);
}
}
// Second pass
@ -123,7 +127,8 @@ public class EntitiesConfigurator {
}
}
return new EntitiesConfigurations(auditMetaGen.getEntitiesConfigurations());
return new EntitiesConfigurations(auditMetaGen.getEntitiesConfigurations(),
auditMetaGen.getNotAuditedEntitiesConfigurations());
}
// todo

View File

@ -53,6 +53,7 @@ import org.hibernate.type.*;
/**
* @author Adam Warski (adam at warski dot org)
* @author Sebastian Komander
* @author Tomasz Bech
*/
public final class AuditMetadataGenerator {
private final Configuration cfg;
@ -66,6 +67,7 @@ public final class AuditMetadataGenerator {
private final ToOneRelationMetadataGenerator toOneRelationMetadataGenerator;
private final Map<String, EntityConfiguration> entitiesConfigurations;
private final Map<String, EntityConfiguration> notAuditedEntitiesConfigurations;
// Map entity name -> (join descriptor -> element describing the "versioned" join)
private final Map<String, Map<Join, Element>> entitiesJoins;
@ -84,6 +86,7 @@ public final class AuditMetadataGenerator {
this.toOneRelationMetadataGenerator = new ToOneRelationMetadataGenerator(this);
entitiesConfigurations = new HashMap<String, EntityConfiguration>();
notAuditedEntitiesConfigurations = new HashMap<String, EntityConfiguration>();
entitiesJoins = new HashMap<String, Map<Join, Element>>();
}
@ -278,7 +281,7 @@ public final class AuditMetadataGenerator {
@SuppressWarnings({"unchecked"})
public void generateFirstPass(PersistentClass pc, ClassAuditingData auditingData,
EntityXmlMappingData xmlMappingData) {
EntityXmlMappingData xmlMappingData, boolean isAudited) {
String schema = auditingData.getAuditTable().schema();
if (StringTools.isEmpty(schema)) {
schema = pc.getTable().getSchema();
@ -289,6 +292,17 @@ public final class AuditMetadataGenerator {
catalog = pc.getTable().getCatalog();
}
if (!isAudited) {
String entityName = pc.getEntityName();
IdMappingData idMapper = idMetadataGenerator.addId(pc);
ExtendedPropertyMapper propertyMapper = null;
String parentEntityName = null;
EntityConfiguration entityCfg = new EntityConfiguration(entityName, idMapper, propertyMapper,
parentEntityName);
notAuditedEntitiesConfigurations.put(pc.getEntityName(), entityCfg);
return;
}
String entityName = pc.getEntityName();
String auditEntityName = verEntCfg.getAuditEntityName(entityName);
String auditTableName = verEntCfg.getAuditTableName(entityName, pc.getTable().getName());
@ -400,4 +414,13 @@ public final class AuditMetadataGenerator {
throw new MappingException(message);
}
/**
* Get the notAuditedEntitiesConfigurations property.
*
* @return the notAuditedEntitiesConfigurations property value
*/
public Map<String, EntityConfiguration> getNotAuditedEntitiesConfigurations() {
return notAuditedEntitiesConfigurations;
}
}

View File

@ -36,6 +36,7 @@ import javax.persistence.JoinColumn;
import org.dom4j.Element;
import org.hibernate.envers.ModificationStore;
import org.hibernate.envers.RelationTargetAuditMode;
import org.hibernate.envers.configuration.metadata.reader.PropertyAuditingData;
import org.hibernate.envers.entities.EntityConfiguration;
import org.hibernate.envers.entities.IdMappingData;
@ -413,7 +414,7 @@ public final class CollectionMetadataGenerator {
} else {
// Last but one parameter: collection components are always insertable
boolean mapped = mainGenerator.getBasicMetadataGenerator().addBasic(xmlMapping,
new PropertyAuditingData(prefix, "field", ModificationStore.FULL), value, null,
new PropertyAuditingData(prefix, "field", ModificationStore.FULL, RelationTargetAuditMode.AUDITED), value, null,
true, true);
if (mapped) {

View File

@ -28,6 +28,7 @@ import java.util.Iterator;
import org.dom4j.Element;
import org.dom4j.tree.DefaultElement;
import org.hibernate.envers.ModificationStore;
import org.hibernate.envers.RelationTargetAuditMode;
import org.hibernate.envers.configuration.metadata.reader.PropertyAuditingData;
import org.hibernate.envers.entities.IdMappingData;
import org.hibernate.envers.entities.PropertyData;
@ -133,6 +134,6 @@ public final class IdMetadataGenerator {
private PropertyAuditingData getIdPersistentPropertyAuditingData(Property property) {
return new PropertyAuditingData(property.getName(), property.getPropertyAccessorName(),
ModificationStore.FULL);
ModificationStore.FULL, RelationTargetAuditMode.AUDITED);
}
}

View File

@ -24,6 +24,7 @@
package org.hibernate.envers.configuration.metadata;
import org.dom4j.Element;
import org.hibernate.envers.RelationTargetAuditMode;
import org.hibernate.envers.entities.EntityConfiguration;
import org.hibernate.envers.entities.IdMappingData;
import org.hibernate.envers.entities.PropertyData;
@ -54,10 +55,22 @@ public final class ToOneRelationMetadataGenerator {
CompositeMapperBuilder mapper, String entityName, boolean insertable) {
String referencedEntityName = ((ToOne) value).getReferencedEntityName();
EntityConfiguration configuration = mainGenerator.getEntitiesConfigurations().get(referencedEntityName);
if (configuration == null) {
throw new MappingException("An audited relation to a non-audited entity " + referencedEntityName + "!");
}
EntityConfiguration configuration = mainGenerator.getEntitiesConfigurations().get(referencedEntityName);
if (configuration == null) {
configuration = mainGenerator.getNotAuditedEntitiesConfigurations().get(referencedEntityName);
if (configuration != null) {
RelationTargetAuditMode relationTargetAuditMode = propertyAuditingData.getRelationTargetAuditMode();
if (!RelationTargetAuditMode.NOT_AUDITED.equals(relationTargetAuditMode)) {
throw new MappingException("An audited relation from " + entityName + "."
+ propertyAuditingData.getName() + " to a not audited entity " + referencedEntityName + "!"
+ ". Such mapping is possible, but has to be strictly defined using RelationTargetAuditMode.NOT_AUDITED in @Audited.");
}
}
}
if (configuration == null) {
throw new MappingException("An audited relation from " + entityName + "."
+ propertyAuditingData.getName() + " to a not audited entity " + referencedEntityName + "!");
}
IdMappingData idMapping = configuration.getIdMappingData();

View File

@ -160,6 +160,7 @@ public class AuditedPropertiesReader {
Versioned ver = property.getAnnotation(Versioned.class);
if (aud != null) {
propertyData.setStore(aud.modStore());
propertyData.setRelationTargetAuditMode(aud.targetAuditMode());
} else if (ver != null) {
propertyData.setStore(ModificationStore.FULL);
} else {

View File

@ -31,6 +31,7 @@ import org.hibernate.envers.AuditOverride;
import org.hibernate.envers.AuditOverrides;
import org.hibernate.envers.ModificationStore;
import org.hibernate.envers.AuditJoinTable;
import org.hibernate.envers.RelationTargetAuditMode;
import org.hibernate.envers.entities.PropertyData;
/**
@ -44,15 +45,18 @@ public class PropertyAuditingData {
private AuditJoinTable joinTable;
private String accessType;
private final List<AuditOverride> auditJoinTableOverrides = new ArrayList<AuditOverride>(0);
private RelationTargetAuditMode relationTargetAuditMode;
public PropertyAuditingData() {
public PropertyAuditingData() {
}
public PropertyAuditingData(String name, String accessType, ModificationStore store) {
public PropertyAuditingData(String name, String accessType, ModificationStore store,
RelationTargetAuditMode relationTargetAuditMode) {
this.name = name;
this.beanName = name;
this.accessType = accessType;
this.store = store;
this.relationTargetAuditMode = relationTargetAuditMode;
}
public String getName() {
@ -135,4 +139,22 @@ public class PropertyAuditingData {
}
}
/**
* Get the relationTargetAuditMode property.
*
* @return the relationTargetAuditMode property value
*/
public RelationTargetAuditMode getRelationTargetAuditMode() {
return relationTargetAuditMode;
}
/**
* Set the relationTargetAuditMode property value.
*
* @param relationTargetAuditMode the relationTargetAuditMode to set
*/
public void setRelationTargetAuditMode(RelationTargetAuditMode relationTargetAuditMode) {
this.relationTargetAuditMode = relationTargetAuditMode;
}
}

View File

@ -32,12 +32,15 @@ import java.util.Map;
*/
public class EntitiesConfigurations {
private Map<String, EntityConfiguration> entitiesConfigurations;
private Map<String, EntityConfiguration> notAuditedEntitiesConfigurations;
// Map versions entity name -> entity name
private Map<String, String> entityNamesForVersionsEntityNames = new HashMap<String, String>();
public EntitiesConfigurations(Map<String, EntityConfiguration> entitiesConfigurations) {
public EntitiesConfigurations(Map<String, EntityConfiguration> entitiesConfigurations,
Map<String, EntityConfiguration> notAuditedEntitiesConfigurations) {
this.entitiesConfigurations = entitiesConfigurations;
this.notAuditedEntitiesConfigurations = notAuditedEntitiesConfigurations;
generateBidirectionRelationInfo();
generateVersionsEntityToEntityNames();
@ -61,14 +64,17 @@ public class EntitiesConfigurations {
// If this is an "owned" relation, checking the related entity, if it has a relation that has
// a mapped-by attribute to the currently checked. If so, this is a bidirectional relation.
if (relDesc.getRelationType() == RelationType.TO_ONE ||
relDesc.getRelationType() == RelationType.TO_MANY_MIDDLE) {
for (RelationDescription other : entitiesConfigurations.get(relDesc.getToEntityName()).getRelationsIterator()) {
if (relDesc.getFromPropertyName().equals(other.getMappedByPropertyName()) &&
(entityName.equals(other.getToEntityName()))) {
relDesc.setBidirectional(true);
other.setBidirectional(true);
}
}
relDesc.getRelationType() == RelationType.TO_MANY_MIDDLE) {
EntityConfiguration entityConfiguration = entitiesConfigurations.get(relDesc.getToEntityName());
if (entityConfiguration != null) {
for (RelationDescription other : entityConfiguration.getRelationsIterator()) {
if (relDesc.getFromPropertyName().equals(other.getMappedByPropertyName()) &&
(entityName.equals(other.getToEntityName()))) {
relDesc.setBidirectional(true);
other.setBidirectional(true);
}
}
}
}
}
}
@ -78,6 +84,10 @@ public class EntitiesConfigurations {
return entitiesConfigurations.get(entityName);
}
public EntityConfiguration getNotVersionEntityConfiguration(String entityName) {
return notAuditedEntitiesConfigurations.get(entityName);
}
public String getEntityNameForVersionsEntityName(String versionsEntityName) {
return entityNamesForVersionsEntityNames.get(versionsEntityName);
}
@ -98,4 +108,5 @@ public class EntitiesConfigurations {
return null;
}
}
}

View File

@ -82,7 +82,7 @@ public class ToOneIdMapper implements PropertyMapper {
Class<?> entityClass = ReflectionTools.loadClass(referencedEntityName);
value = versionsReader.getSessionImplementor().getFactory().getEntityPersister(referencedEntityName).
createProxy(null, new ToOneDelegateSessionImplementor(versionsReader, entityClass, entityId, revision));
createProxy(null, new ToOneDelegateSessionImplementor(versionsReader, entityClass, entityId, revision, verCfg));
}
}

View File

@ -23,29 +23,47 @@
*/
package org.hibernate.envers.entities.mapper.relation.lazy;
import java.io.Serializable;
import org.hibernate.envers.configuration.AuditConfiguration;
import org.hibernate.envers.entities.EntitiesConfigurations;
import org.hibernate.envers.entities.EntityConfiguration;
import org.hibernate.envers.reader.AuditReaderImplementor;
import org.hibernate.HibernateException;
import org.hibernate.Session;
/**
* @author Adam Warski (adam at warski dot org)
* @author Tomasz Bech
*/
public class ToOneDelegateSessionImplementor extends AbstractDelegateSessionImplementor {
private static final long serialVersionUID = 4770438372940785488L;
private final AuditReaderImplementor versionsReader;
private final Class<?> entityClass;
private final Object entityId;
private final Number revision;
private EntityConfiguration notVersionedEntityConfiguration;
public ToOneDelegateSessionImplementor(AuditReaderImplementor versionsReader,
Class<?> entityClass, Object entityId, Number revision) {
public ToOneDelegateSessionImplementor(AuditReaderImplementor versionsReader,
Class<?> entityClass, Object entityId, Number revision,
AuditConfiguration verCfg) {
super(versionsReader.getSessionImplementor());
this.versionsReader = versionsReader;
this.entityClass = entityClass;
this.entityId = entityId;
this.revision = revision;
EntitiesConfigurations entCfg = verCfg.getEntCfg();
notVersionedEntityConfiguration = entCfg.getNotVersionEntityConfiguration(entityClass.getName());
}
public Object doImmediateLoad(String entityName) throws HibernateException {
return versionsReader.find(entityClass, entityId, revision);
if (notVersionedEntityConfiguration == null) {
return versionsReader.find(entityClass, entityId, revision);
} else {
Session session = versionsReader.getSession();
return session.get(entityClass, (Serializable) entityId);
}
}
}

View File

@ -0,0 +1,115 @@
/*
* 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.entities.manytoone.unidirectional;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import org.hibernate.envers.Audited;
import org.hibernate.envers.RelationTargetAuditMode;
import org.hibernate.envers.test.entities.UnversionedStrTestEntity;
/**
* Audited entity with a reference to not audited entity.
* @author Toamsz Bech
*/
@Entity
public class TargetNotAuditedEntity {
@Id
private Integer id;
@Audited
private String data;
@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
@ManyToOne(fetch = FetchType.EAGER)
private UnversionedStrTestEntity reference;
public TargetNotAuditedEntity() { }
public TargetNotAuditedEntity(Integer id, String data, UnversionedStrTestEntity reference) {
this.id = id;
this.data = data;
this.reference = reference;
}
public TargetNotAuditedEntity(String data, UnversionedStrTestEntity reference) {
this.data = data;
this.reference = reference;
}
public TargetNotAuditedEntity(Integer id, String data) {
this.id = id;
this.data = data;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public UnversionedStrTestEntity getReference() {
return reference;
}
public void setReference(UnversionedStrTestEntity reference) {
this.reference = reference;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof TargetNotAuditedEntity)) return false;
TargetNotAuditedEntity that = (TargetNotAuditedEntity) o;
if (data != null ? !data.equals(that.data) : that.data != null) return false;
if (id != null ? !id.equals(that.id) : that.id != null) return false;
return true;
}
public int hashCode() {
int result;
result = (id != null ? id.hashCode() : 0);
result = 31 * result + (data != null ? data.hashCode() : 0);
return result;
}
public String toString() {
return "TargetNotAuditedEntity(id = " + id + ", data = " + data + ")";
}
}

View File

@ -0,0 +1,161 @@
/*
* 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.manytoone.unidirectional;
import java.util.Arrays;
import java.util.List;
import javax.persistence.EntityManager;
import org.hibernate.ejb.Ejb3Configuration;
import org.hibernate.envers.test.AbstractEntityTest;
import org.hibernate.envers.test.entities.UnversionedStrTestEntity;
import org.hibernate.envers.test.entities.manytoone.unidirectional.TargetNotAuditedEntity;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
* @author Tomasz Bech
*/
public class RelationNotAuditedTarget extends AbstractEntityTest {
private Integer tnae1_id;
private Integer tnae2_id;
private Integer uste1_id;
private Integer uste2_id;
public void configure(Ejb3Configuration cfg) {
cfg.addAnnotatedClass(TargetNotAuditedEntity.class);
cfg.addAnnotatedClass(UnversionedStrTestEntity.class);
}
@BeforeClass(dependsOnMethods = "init")
public void initData() {
EntityManager em = getEntityManager();
UnversionedStrTestEntity uste1 = new UnversionedStrTestEntity("str1");
UnversionedStrTestEntity uste2 = new UnversionedStrTestEntity("str2");
// No revision
em.getTransaction().begin();
em.persist(uste1);
em.persist(uste2);
em.getTransaction().commit();
// Revision 1
em.getTransaction().begin();
uste1 = em.find(UnversionedStrTestEntity.class, uste1.getId());
uste2 = em.find(UnversionedStrTestEntity.class, uste2.getId());
TargetNotAuditedEntity tnae1 = new TargetNotAuditedEntity(1, "tnae1", uste1);
TargetNotAuditedEntity tnae2 = new TargetNotAuditedEntity(2, "tnae2", uste2);
em.persist(tnae1);
em.persist(tnae2);
em.getTransaction().commit();
// Revision 2
em.getTransaction().begin();
tnae1 = em.find(TargetNotAuditedEntity.class, tnae1.getId());
tnae2 = em.find(TargetNotAuditedEntity.class, tnae2.getId());
tnae1.setReference(uste2);
tnae2.setReference(uste1);
em.getTransaction().commit();
// Revision 3
em.getTransaction().begin();
tnae1 = em.find(TargetNotAuditedEntity.class, tnae1.getId());
tnae2 = em.find(TargetNotAuditedEntity.class, tnae2.getId());
//field not changed!!!
tnae1.setReference(uste2);
tnae2.setReference(uste2);
em.getTransaction().commit();
// Revision 4
em.getTransaction().begin();
tnae1 = em.find(TargetNotAuditedEntity.class, tnae1.getId());
tnae2 = em.find(TargetNotAuditedEntity.class, tnae2.getId());
tnae1.setReference(uste1);
tnae2.setReference(uste1);
em.getTransaction().commit();
//
tnae1_id = tnae1.getId();
tnae2_id = tnae2.getId();
uste1_id = uste1.getId();
uste2_id = uste2.getId();
}
@Test
public void testRevisionsCounts() {
List<Number> revisions = getAuditReader().getRevisions(TargetNotAuditedEntity.class, tnae1_id);
assert Arrays.asList(1, 2, 4).equals(revisions);
revisions = getAuditReader().getRevisions(TargetNotAuditedEntity.class, tnae2_id);
assert Arrays.asList(1, 2, 3, 4).equals(revisions);
}
@Test
public void testHistoryOfTnae1_id() {
UnversionedStrTestEntity uste1 = getEntityManager().find(UnversionedStrTestEntity.class, uste1_id);
UnversionedStrTestEntity uste2 = getEntityManager().find(UnversionedStrTestEntity.class, uste2_id);
TargetNotAuditedEntity rev1 = getAuditReader().find(TargetNotAuditedEntity.class, tnae1_id, 1);
TargetNotAuditedEntity rev2 = getAuditReader().find(TargetNotAuditedEntity.class, tnae1_id, 2);
TargetNotAuditedEntity rev3 = getAuditReader().find(TargetNotAuditedEntity.class, tnae1_id, 3);
TargetNotAuditedEntity rev4 = getAuditReader().find(TargetNotAuditedEntity.class, tnae1_id, 4);
assert rev1.getReference().equals(uste1);
assert rev2.getReference().equals(uste2);
assert rev3.getReference().equals(uste2);
assert rev4.getReference().equals(uste1);
}
@Test
public void testHistoryOfTnae2_id() {
UnversionedStrTestEntity uste1 = getEntityManager().find(UnversionedStrTestEntity.class, uste1_id);
UnversionedStrTestEntity uste2 = getEntityManager().find(UnversionedStrTestEntity.class, uste2_id);
TargetNotAuditedEntity rev1 = getAuditReader().find(TargetNotAuditedEntity.class, tnae2_id, 1);
TargetNotAuditedEntity rev2 = getAuditReader().find(TargetNotAuditedEntity.class, tnae2_id, 2);
TargetNotAuditedEntity rev3 = getAuditReader().find(TargetNotAuditedEntity.class, tnae2_id, 3);
TargetNotAuditedEntity rev4 = getAuditReader().find(TargetNotAuditedEntity.class, tnae2_id, 4);
assert rev1.getReference().equals(uste2);
assert rev2.getReference().equals(uste1);
assert rev3.getReference().equals(uste2);
assert rev4.getReference().equals(uste1);
}
}