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:
parent
8465009b4b
commit
5d08386293
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -231,7 +232,7 @@ public final class CollectionMetadataGenerator {
|
|||
// middle table for mapping this relation.
|
||||
return StringTools.getLastComponent(entityName) + "_" + StringTools.getLastComponent(getReferencedEntityName(value.getElement()));
|
||||
} else {
|
||||
// Hibernate uses a middle table for mapping this relation, so we get it's name directly.
|
||||
// Hibernate uses a middle table for mapping this relation, so we get it's name directly.
|
||||
return value.getCollectionTable().getName();
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
@ -203,7 +204,7 @@ public class AuditedPropertiesReader {
|
|||
|
||||
/***
|
||||
* Add the {@link org.hibernate.envers.AuditOverride} annotations.
|
||||
*
|
||||
*
|
||||
* @param property the property being processed
|
||||
* @param propertyData the Envers auditing data for this property
|
||||
*/
|
||||
|
@ -220,13 +221,13 @@ public class AuditedPropertiesReader {
|
|||
|
||||
/**
|
||||
* Process the {@link org.hibernate.envers.AuditOverride} annotations for this property.
|
||||
*
|
||||
*
|
||||
* @param property
|
||||
* the property for which the {@link org.hibernate.envers.AuditOverride}
|
||||
* annotations are being processed
|
||||
* @param propertyData
|
||||
* the Envers auditing data for this property
|
||||
* @return {@code false} if isAudited() of the override annotation was set to
|
||||
* @return {@code false} if isAudited() of the override annotation was set to
|
||||
*/
|
||||
private boolean processPropertyAuditingOverrides(XProperty property, PropertyAuditingData propertyData) {
|
||||
// if this property is part of a component, process all override annotations
|
||||
|
@ -236,7 +237,7 @@ public class AuditedPropertiesReader {
|
|||
if (property.getName().equals(override.name())) {
|
||||
// the override applies to this property
|
||||
if (!override.isAudited()) {
|
||||
return false;
|
||||
return false;
|
||||
} else {
|
||||
if (override.auditJoinTable() != null) {
|
||||
propertyData.setJoinTable(override.auditJoinTable());
|
||||
|
@ -267,7 +268,7 @@ public class AuditedPropertiesReader {
|
|||
} catch (ClassNotFoundException e) {
|
||||
throw new MappingException(e);
|
||||
}
|
||||
|
||||
|
||||
this.component = component;
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
@ -108,7 +112,7 @@ public class PropertyAuditingData {
|
|||
}
|
||||
|
||||
public List<AuditOverride> getAuditingOverrides() {
|
||||
return auditJoinTableOverrides;
|
||||
return auditJoinTableOverrides;
|
||||
}
|
||||
|
||||
public void addAuditingOverride(AuditOverride annotation) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 + ")";
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue