mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-22 11:06:08 +00:00
HHH5371 - Rollback until after 3.6.0 release as per Adam's request via IM
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@20745 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
b258e58e69
commit
558d9469e0
@ -249,33 +249,6 @@
|
||||
valid if the validity audit strategy is used.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<property>org.hibernate.envers.audit_strategy_validity_store_revend_timestamp</property>
|
||||
</entry>
|
||||
<entry>
|
||||
false
|
||||
</entry>
|
||||
<entry>
|
||||
Should the timestamp of the end revision be stored, until which the data was valid, in addition to the end revision itself.
|
||||
This is useful to be able to purge old Audit records out of a relational database by using table partitioning.
|
||||
Partitioning requires a column that exists within the table.
|
||||
This property is only evaluated if the ValidityAuditStrategy is used.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<property>org.hibernate.envers.audit_strategy_validity_revend_timestamp_field_name</property>
|
||||
</entry>
|
||||
<entry>
|
||||
REVEND_TSTMP
|
||||
</entry>
|
||||
<entry>
|
||||
Column name of the timestamp of the end revision until which the data was valid.
|
||||
Only used if the ValidityAuditStrategy is used, and
|
||||
org.hibernate.envers.audit_strategy_validity_store_revend_timestamp evaluates to true
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
@ -28,17 +28,15 @@
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.envers.entities.EntitiesConfigurations;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
import org.hibernate.envers.revisioninfo.RevisionInfoNumberReader;
|
||||
import org.hibernate.envers.revisioninfo.RevisionInfoQueryCreator;
|
||||
import org.hibernate.envers.strategy.AuditStrategy;
|
||||
import org.hibernate.envers.strategy.ValidityAuditStrategy;
|
||||
import org.hibernate.envers.synchronization.AuditProcessManager;
|
||||
import org.hibernate.envers.tools.reflection.ReflectionTools;
|
||||
import org.hibernate.property.Getter;
|
||||
import org.hibernate.envers.strategy.AuditStrategy;
|
||||
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.AnnotationConfiguration;
|
||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
@ -81,6 +79,7 @@ public AuditStrategy getAuditStrategy() {
|
||||
return auditStrategy;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public AuditConfiguration(Configuration cfg) {
|
||||
Properties properties = cfg.getProperties();
|
||||
|
||||
@ -90,32 +89,19 @@ public AuditConfiguration(Configuration cfg) {
|
||||
auditEntCfg = new AuditEntitiesConfiguration(properties, revInfoCfgResult.getRevisionInfoEntityName());
|
||||
globalCfg = new GlobalConfiguration(properties);
|
||||
auditProcessManager = new AuditProcessManager(revInfoCfgResult.getRevisionInfoGenerator());
|
||||
revisionInfoQueryCreator = revInfoCfgResult.getRevisionInfoQueryCreator();
|
||||
revisionInfoNumberReader = revInfoCfgResult.getRevisionInfoNumberReader();
|
||||
auditStrategy = initializeAuditStrategy(revInfoCfgResult.getRevisionInfoClass(),
|
||||
revInfoCfgResult.getRevisionInfoTimestampData());
|
||||
entCfg = new EntitiesConfigurator().configure(cfg, reflectionManager, globalCfg, auditEntCfg, auditStrategy,
|
||||
revInfoCfgResult.getRevisionInfoXmlMapping(), revInfoCfgResult.getRevisionInfoRelationMapping());
|
||||
}
|
||||
|
||||
private AuditStrategy initializeAuditStrategy(Class<?> revisionInfoClass, PropertyData revisionInfoTimestampData) {
|
||||
AuditStrategy strategy;
|
||||
|
||||
try {
|
||||
Class<?> auditStrategyClass = Thread.currentThread().getContextClassLoader().loadClass(auditEntCfg.getAuditStrategyName());
|
||||
strategy = (AuditStrategy) auditStrategyClass.newInstance();
|
||||
try {
|
||||
Class auditStrategyClass = Thread.currentThread().getContextClassLoader().loadClass(auditEntCfg.getAuditStrategyName());
|
||||
auditStrategy = (AuditStrategy) auditStrategyClass.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new MappingException(String.format("Unable to create AuditStrategy[%s] instance." , auditEntCfg.getAuditStrategyName()));
|
||||
}
|
||||
|
||||
if (strategy instanceof ValidityAuditStrategy) {
|
||||
// further initialization required
|
||||
Getter revisionTimestampGetter = ReflectionTools.getGetter(revisionInfoClass, revisionInfoTimestampData);
|
||||
((ValidityAuditStrategy) strategy).setRevisionTimestampGetter(revisionTimestampGetter);
|
||||
}
|
||||
|
||||
return strategy;
|
||||
}
|
||||
revisionInfoQueryCreator = revInfoCfgResult.getRevisionInfoQueryCreator();
|
||||
revisionInfoNumberReader = revInfoCfgResult.getRevisionInfoNumberReader();
|
||||
entCfg = new EntitiesConfigurator().configure(cfg, reflectionManager, globalCfg, auditEntCfg, auditStrategy,
|
||||
revInfoCfgResult.getRevisionInfoXmlMapping(), revInfoCfgResult.getRevisionInfoRelationMapping());
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
|
@ -25,11 +25,17 @@
|
||||
|
||||
import static org.hibernate.envers.tools.Tools.getProperty;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.envers.strategy.DefaultAuditStrategy;
|
||||
import org.hibernate.envers.strategy.ValidityAuditStrategy;
|
||||
|
||||
/**
|
||||
* Configuration of versions entities - names of fields, entities and tables created to store versioning information.
|
||||
@ -55,9 +61,6 @@ public class AuditEntitiesConfiguration {
|
||||
private final Map<String, String> customAuditTablesNames;
|
||||
|
||||
private final String revisionEndFieldName;
|
||||
|
||||
private final boolean revisionEndTimestampEnabled;
|
||||
private final String revisionEndTimestampFieldName;
|
||||
|
||||
public AuditEntitiesConfiguration(Properties properties, String revisionInfoEntityName) {
|
||||
this.revisionInfoEntityName = revisionInfoEntityName;
|
||||
@ -94,21 +97,6 @@ public AuditEntitiesConfiguration(Properties properties, String revisionInfoEnti
|
||||
"org.hibernate.envers.audit_strategy_valid_time_end_name",
|
||||
"REVEND");
|
||||
|
||||
String revisionEndTimestampEnabledStr = getProperty(properties,
|
||||
"org.hibernate.envers.audit_strategy_validity_store_revend_timestamp",
|
||||
"org.hibernate.envers.audit_strategy_validity_store_revend_timestamp",
|
||||
"false");
|
||||
revisionEndTimestampEnabled = Boolean.parseBoolean(revisionEndTimestampEnabledStr);
|
||||
|
||||
if (revisionEndTimestampEnabled) {
|
||||
revisionEndTimestampFieldName = getProperty(properties,
|
||||
"org.hibernate.envers.audit_strategy_validity_revend_timestamp_field_name",
|
||||
"org.hibernate.envers.audit_strategy_validity_revend_timestamp_field_name",
|
||||
"REVEND_TSTMP");
|
||||
} else {
|
||||
revisionEndTimestampFieldName = null;
|
||||
}
|
||||
|
||||
customAuditTablesNames = new HashMap<String, String>();
|
||||
|
||||
revisionNumberPath = originalIdPropName + "." + revisionFieldName + ".id";
|
||||
@ -123,14 +111,6 @@ public String getRevisionFieldName() {
|
||||
return revisionFieldName;
|
||||
}
|
||||
|
||||
public boolean isRevisionEndTimestampEnabled() {
|
||||
return revisionEndTimestampEnabled;
|
||||
}
|
||||
|
||||
public String getRevisionEndTimestampFieldName() {
|
||||
return revisionEndTimestampFieldName;
|
||||
}
|
||||
|
||||
public String getRevisionNumberPath() {
|
||||
return revisionNumberPath;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentHelper;
|
||||
import org.dom4j.Element;
|
||||
import org.hibernate.envers.Audited;
|
||||
import org.hibernate.envers.*;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
import org.hibernate.envers.configuration.metadata.MetadataTools;
|
||||
@ -175,6 +176,7 @@ private void searchForRevisionInfoCfg(XClass clazz, ReflectionManager reflection
|
||||
"property");
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public RevisionInfoConfigurationResult configure(Configuration cfg, ReflectionManager reflectionManager) {
|
||||
Iterator<PersistentClass> classes = (Iterator<PersistentClass>) cfg.getClassMappings();
|
||||
boolean revisionEntityFound = false;
|
||||
@ -243,8 +245,7 @@ public RevisionInfoConfigurationResult configure(Configuration cfg, ReflectionMa
|
||||
new RevisionInfoQueryCreator(revisionInfoEntityName, revisionInfoIdData.getName(),
|
||||
revisionInfoTimestampData.getName(), isTimestampAsDate()),
|
||||
generateRevisionInfoRelationMapping(),
|
||||
new RevisionInfoNumberReader(revisionInfoClass, revisionInfoIdData), revisionInfoEntityName,
|
||||
revisionInfoClass, revisionInfoTimestampData);
|
||||
new RevisionInfoNumberReader(revisionInfoClass, revisionInfoIdData), revisionInfoEntityName);
|
||||
}
|
||||
|
||||
private boolean isTimestampAsDate() {
|
||||
@ -260,22 +261,17 @@ class RevisionInfoConfigurationResult {
|
||||
private final Element revisionInfoRelationMapping;
|
||||
private final RevisionInfoNumberReader revisionInfoNumberReader;
|
||||
private final String revisionInfoEntityName;
|
||||
private final Class<?> revisionInfoClass;
|
||||
private final PropertyData revisionInfoTimestampData;
|
||||
|
||||
RevisionInfoConfigurationResult(RevisionInfoGenerator revisionInfoGenerator,
|
||||
Document revisionInfoXmlMapping, RevisionInfoQueryCreator revisionInfoQueryCreator,
|
||||
Element revisionInfoRelationMapping,
|
||||
RevisionInfoNumberReader revisionInfoNumberReader, String revisionInfoEntityName, Class<?> revisionInfoClass,
|
||||
PropertyData revisionInfoTimestampData) {
|
||||
RevisionInfoNumberReader revisionInfoNumberReader, String revisionInfoEntityName) {
|
||||
this.revisionInfoGenerator = revisionInfoGenerator;
|
||||
this.revisionInfoXmlMapping = revisionInfoXmlMapping;
|
||||
this.revisionInfoQueryCreator = revisionInfoQueryCreator;
|
||||
this.revisionInfoRelationMapping = revisionInfoRelationMapping;
|
||||
this.revisionInfoNumberReader = revisionInfoNumberReader;
|
||||
this.revisionInfoEntityName = revisionInfoEntityName;
|
||||
this.revisionInfoClass = revisionInfoClass;
|
||||
this.revisionInfoTimestampData = revisionInfoTimestampData;
|
||||
}
|
||||
|
||||
public RevisionInfoGenerator getRevisionInfoGenerator() {
|
||||
@ -301,13 +297,4 @@ public RevisionInfoNumberReader getRevisionInfoNumberReader() {
|
||||
public String getRevisionInfoEntityName() {
|
||||
return revisionInfoEntityName;
|
||||
}
|
||||
|
||||
public Class<?> getRevisionInfoClass() {
|
||||
return revisionInfoClass;
|
||||
}
|
||||
|
||||
public PropertyData getRevisionInfoTimestampData() {
|
||||
return revisionInfoTimestampData;
|
||||
}
|
||||
|
||||
}
|
@ -55,7 +55,6 @@
|
||||
import org.hibernate.type.ComponentType;
|
||||
import org.hibernate.type.ManyToOneType;
|
||||
import org.hibernate.type.OneToOneType;
|
||||
import org.hibernate.type.TimestampType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -65,7 +64,7 @@
|
||||
* @author Sebastian Komander
|
||||
* @author Tomasz Bech
|
||||
* @author Stephanie Pau at Markit Group Plc
|
||||
* @author Hernán Chanfreau
|
||||
* @author Hern<EFBFBD>n Chanfreau
|
||||
*/
|
||||
public final class AuditMetadataGenerator {
|
||||
private static final Logger log = LoggerFactory.getLogger(AuditMetadataGenerator.class);
|
||||
@ -145,7 +144,7 @@ void addRevisionType(Element any_mapping) {
|
||||
addEndRevision(any_mapping);
|
||||
}
|
||||
|
||||
private void addEndRevision(Element any_mapping ) {
|
||||
private void addEndRevision(Element any_mapping) {
|
||||
// Add the end-revision field, if the appropriate strategy is used.
|
||||
if (auditStrategy instanceof ValidityAuditStrategy) {
|
||||
Element end_rev_mapping = (Element) revisionInfoRelationMapping.clone();
|
||||
@ -154,16 +153,10 @@ private void addEndRevision(Element any_mapping ) {
|
||||
MetadataTools.addOrModifyColumn(end_rev_mapping, verEntCfg.getRevisionEndFieldName());
|
||||
|
||||
any_mapping.add(end_rev_mapping);
|
||||
|
||||
if (verEntCfg.isRevisionEndTimestampEnabled()) {
|
||||
// add a column for the timestamp of the end revision
|
||||
String revisionInfoTimestampSqlType = TimestampType.INSTANCE.getName();
|
||||
Element timestampProperty = MetadataTools.addProperty(any_mapping, verEntCfg.getRevisionEndTimestampFieldName(), revisionInfoTimestampSqlType, true, true, false);
|
||||
MetadataTools.addColumn(timestampProperty, verEntCfg.getRevisionEndTimestampFieldName(), 0, 0, 0, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
void addValue(Element parent, Value value, CompositeMapperBuilder currentMapper, String entityName,
|
||||
EntityXmlMappingData xmlMappingData, PropertyAuditingData propertyAuditingData,
|
||||
boolean insertable, boolean firstPass) {
|
||||
@ -211,6 +204,7 @@ void addValue(Element parent, Value value, CompositeMapperBuilder currentMapper,
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addProperties(Element parent, Iterator<Property> properties, CompositeMapperBuilder currentMapper,
|
||||
ClassAuditingData auditingData, String entityName, EntityXmlMappingData xmlMappingData,
|
||||
boolean firstPass) {
|
||||
|
@ -49,7 +49,7 @@ public static Element addNativelyGeneratedId(Element parent, String name, String
|
||||
return id_mapping;
|
||||
}
|
||||
|
||||
public static Element addProperty(Element parent, String name, String type, boolean insertable, boolean updateable, boolean key) {
|
||||
public static Element addProperty(Element parent, String name, String type, boolean insertable, boolean key) {
|
||||
Element prop_mapping;
|
||||
if (key) {
|
||||
prop_mapping = parent.addElement("key-property");
|
||||
@ -59,7 +59,7 @@ public static Element addProperty(Element parent, String name, String type, bool
|
||||
|
||||
prop_mapping.addAttribute("name", name);
|
||||
prop_mapping.addAttribute("insert", Boolean.toString(insertable));
|
||||
prop_mapping.addAttribute("update", Boolean.toString(updateable));
|
||||
prop_mapping.addAttribute("update", "false");
|
||||
|
||||
if (type != null) {
|
||||
prop_mapping.addAttribute("type", type);
|
||||
@ -68,10 +68,6 @@ public static Element addProperty(Element parent, String name, String type, bool
|
||||
return prop_mapping;
|
||||
}
|
||||
|
||||
public static Element addProperty(Element parent, String name, String type, boolean insertable, boolean key) {
|
||||
return addProperty(parent, name, type, insertable, false, key);
|
||||
}
|
||||
|
||||
private static void addOrModifyAttribute(Element parent, String name, String value) {
|
||||
Attribute attribute = parent.attribute(name);
|
||||
if (attribute == null) {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package org.hibernate.envers.strategy;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@ -16,7 +15,6 @@
|
||||
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
|
||||
import org.hibernate.envers.tools.query.Parameters;
|
||||
import org.hibernate.envers.tools.query.QueryBuilder;
|
||||
import org.hibernate.property.Getter;
|
||||
|
||||
/**
|
||||
* Audit strategy which persists and retrieves audit information using a validity algorithm, based on the
|
||||
@ -41,11 +39,7 @@
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class ValidityAuditStrategy implements AuditStrategy {
|
||||
|
||||
/** getter for the revision entity field annotated with @RevisionTimestamp */
|
||||
private Getter revisionTimestampGetter = null;
|
||||
|
||||
public void perform(Session session, String entityName, AuditConfiguration auditCfg, Serializable id, Object data,
|
||||
public void perform(Session session, String entityName, AuditConfiguration auditCfg, Serializable id, Object data,
|
||||
Object revision) {
|
||||
AuditEntitiesConfiguration audEntCfg = auditCfg.getAuditEntCfg();
|
||||
String auditedEntityName = audEntCfg.getAuditEntityName(entityName);
|
||||
@ -74,22 +68,27 @@ public void perform(Session session, String entityName, AuditConfiguration audit
|
||||
public void performCollectionChange(Session session, AuditConfiguration auditCfg,
|
||||
PersistentCollectionChangeData persistentCollectionChangeData, Object revision) {
|
||||
// Update the end date of the previous row if this operation is expected to have a previous row
|
||||
// Constructing a query (there are multiple id fields):
|
||||
// select e from audited_middle_ent e where e.end_rev is null and e.id1 = :id1 and e.id2 = :id2 ...
|
||||
if (getRevisionType(auditCfg, persistentCollectionChangeData.getData()) != RevisionType.ADD) {
|
||||
/*
|
||||
Constructing a query (there are multiple id fields):
|
||||
select e from audited_middle_ent e where e.end_rev is null and e.id1 = :id1 and e.id2 = :id2 ...
|
||||
*/
|
||||
|
||||
QueryBuilder qb = new QueryBuilder(persistentCollectionChangeData.getEntityName(), "e");
|
||||
QueryBuilder qb = new QueryBuilder(persistentCollectionChangeData.getEntityName(), "e");
|
||||
|
||||
// Adding a parameter for each id component, except the rev number
|
||||
String originalIdPropName = auditCfg.getAuditEntCfg().getOriginalIdPropName();
|
||||
Map<String, Object> originalId = (Map<String, Object>) persistentCollectionChangeData.getData().get(
|
||||
// Adding a parameter for each id component, except the rev number
|
||||
String originalIdPropName = auditCfg.getAuditEntCfg().getOriginalIdPropName();
|
||||
Map<String, Object> originalId = (Map<String, Object>) persistentCollectionChangeData.getData().get(
|
||||
originalIdPropName);
|
||||
for (Map.Entry<String, Object> originalIdEntry : originalId.entrySet()) {
|
||||
if (!auditCfg.getAuditEntCfg().getRevisionFieldName().equals(originalIdEntry.getKey())) {
|
||||
qb.getRootParameters().addWhereWithParam(originalIdPropName + "." + originalIdEntry.getKey(),
|
||||
true, "=", originalIdEntry.getValue());
|
||||
}
|
||||
for (Map.Entry<String, Object> originalIdEntry : originalId.entrySet()) {
|
||||
if (!auditCfg.getAuditEntCfg().getRevisionFieldName().equals(originalIdEntry.getKey())) {
|
||||
qb.getRootParameters().addWhereWithParam(originalIdPropName + "." + originalIdEntry.getKey(),
|
||||
true, "=", originalIdEntry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
updateLastRevision(session, auditCfg, qb, originalId, persistentCollectionChangeData.getEntityName(), revision);
|
||||
}
|
||||
updateLastRevision(session, auditCfg, qb, originalId, persistentCollectionChangeData.getEntityName(), revision);
|
||||
|
||||
// Save the audit data
|
||||
session.save(persistentCollectionChangeData.getEntityName(), persistentCollectionChangeData.getData());
|
||||
@ -111,11 +110,7 @@ public void addAssociationAtRevisionRestriction(QueryBuilder rootQueryBuilder,
|
||||
addRevisionRestriction(rootParameters, revisionProperty, revisionEndProperty, addAlias);
|
||||
}
|
||||
|
||||
public void setRevisionTimestampGetter(Getter revisionTimestampGetter) {
|
||||
this.revisionTimestampGetter = revisionTimestampGetter;
|
||||
}
|
||||
|
||||
private void addRevisionRestriction(Parameters rootParameters,
|
||||
private void addRevisionRestriction(Parameters rootParameters,
|
||||
String revisionProperty, String revisionEndProperty, boolean addAlias) {
|
||||
|
||||
// e.revision <= _revision and (e.endRevision > _revision or e.endRevision is null)
|
||||
@ -134,7 +129,7 @@ private RevisionType getRevisionType(AuditConfiguration auditCfg, Object data) {
|
||||
private void updateLastRevision(Session session, AuditConfiguration auditCfg, QueryBuilder qb,
|
||||
Object id, String auditedEntityName, Object revision) {
|
||||
String revisionEndFieldName = auditCfg.getAuditEntCfg().getRevisionEndFieldName();
|
||||
|
||||
|
||||
// e.end_rev is null
|
||||
qb.getRootParameters().addWhere(revisionEndFieldName, true, "is", "null", false);
|
||||
|
||||
@ -146,28 +141,10 @@ private void updateLastRevision(Session session, AuditConfiguration auditCfg, Qu
|
||||
Object previousData = l.get(0);
|
||||
((Map<String, Object>) previousData).put(revisionEndFieldName, revision);
|
||||
|
||||
if (auditCfg.getAuditEntCfg().isRevisionEndTimestampEnabled()) {
|
||||
// Determine the value of the revision property annotated with @RevisionTimestamp
|
||||
Date revisionEndTimestamp;
|
||||
String revEndTimestampFieldName = auditCfg.getAuditEntCfg().getRevisionEndTimestampFieldName();
|
||||
Object revEndTimestampObj = this.revisionTimestampGetter.get(revision);
|
||||
|
||||
// convert to a java.util.Date
|
||||
if (revEndTimestampObj instanceof Date) {
|
||||
revisionEndTimestamp = (Date) revEndTimestampObj;
|
||||
} else {
|
||||
revisionEndTimestamp = new Date((Long) revEndTimestampObj);
|
||||
}
|
||||
|
||||
// Setting the end revision timestamp
|
||||
((Map<String, Object>) previousData).put(revEndTimestampFieldName, revisionEndTimestamp);
|
||||
}
|
||||
|
||||
// Saving the previous version
|
||||
session.save(auditedEntityName, previousData);
|
||||
|
||||
} else if(l.size() > 1) {
|
||||
throw new RuntimeException("Cannot find previous revision for entity " + auditedEntityName + " and id " + id + " received " + l.size() + " rows back");
|
||||
} else {
|
||||
throw new RuntimeException("Cannot find previous revision for entity " + auditedEntityName + " and id " + id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,433 +0,0 @@
|
||||
/*
|
||||
* 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.strategy;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.ejb.Ejb3Configuration;
|
||||
import org.hibernate.envers.strategy.ValidityAuditStrategy;
|
||||
import org.hibernate.envers.test.AbstractEntityTest;
|
||||
import org.hibernate.envers.test.entities.manytomany.sametable.Child1Entity;
|
||||
import org.hibernate.envers.test.entities.manytomany.sametable.Child2Entity;
|
||||
import org.hibernate.envers.test.entities.manytomany.sametable.ParentEntity;
|
||||
import org.hibernate.envers.test.entities.reventity.CustomDateRevEntity;
|
||||
import org.hibernate.envers.test.tools.TestTools;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Test which checks that the revision end timestamp is correctly set for
|
||||
* {@link ValidityAuditStrategy}.
|
||||
*
|
||||
* @author Erik-Berndt Scheper
|
||||
*/
|
||||
public class ValidityAuditStrategyRevEndTestCustomRevEnt extends AbstractEntityTest {
|
||||
private final String revendTimestampColumName = "REVEND_TIMESTAMP";
|
||||
|
||||
private Integer p1_id;
|
||||
private Integer p2_id;
|
||||
private Integer c1_1_id;
|
||||
private Integer c1_2_id;
|
||||
private Integer c2_1_id;
|
||||
private Integer c2_2_id;
|
||||
private Map<Number, CustomDateRevEntity> revisions;
|
||||
|
||||
public void configure(Ejb3Configuration cfg) {
|
||||
cfg.addAnnotatedClass(ParentEntity.class);
|
||||
cfg.addAnnotatedClass(Child1Entity.class);
|
||||
cfg.addAnnotatedClass(Child2Entity.class);
|
||||
cfg.addAnnotatedClass(CustomDateRevEntity.class);
|
||||
|
||||
cfg.setProperty("org.hibernate.envers.audit_strategy",
|
||||
"org.hibernate.envers.strategy.ValidityAuditStrategy");
|
||||
cfg
|
||||
.setProperty(
|
||||
"org.hibernate.envers.audit_strategy_validity_store_revend_timestamp",
|
||||
"true");
|
||||
cfg
|
||||
.setProperty(
|
||||
"org.hibernate.envers.audit_strategy_validity_revend_timestamp_field_name",
|
||||
revendTimestampColumName);
|
||||
}
|
||||
|
||||
@BeforeClass(enabled = true, dependsOnMethods = "init")
|
||||
public void initData() {
|
||||
EntityManager em = getEntityManager();
|
||||
|
||||
// We need first to modify the columns in the middle (join table) to
|
||||
// allow null values. Hbm2ddl doesn't seem
|
||||
// to allow this.
|
||||
em.getTransaction().begin();
|
||||
Session session = (Session) em.getDelegate();
|
||||
session.createSQLQuery("DROP TABLE children").executeUpdate();
|
||||
session
|
||||
.createSQLQuery(
|
||||
"CREATE TABLE children(parent_id integer, child1_id integer NULL, child2_id integer NULL)")
|
||||
.executeUpdate();
|
||||
session.createSQLQuery("DROP TABLE children_AUD").executeUpdate();
|
||||
session
|
||||
.createSQLQuery(
|
||||
"CREATE TABLE children_AUD(REV integer NOT NULL, REVEND integer, "
|
||||
+ revendTimestampColumName
|
||||
+ " timestamp, REVTYPE tinyint, "
|
||||
+ "parent_id integer, child1_id integer NULL, child2_id integer NULL)")
|
||||
.executeUpdate();
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
ParentEntity p1 = new ParentEntity("parent_1");
|
||||
ParentEntity p2 = new ParentEntity("parent_2");
|
||||
|
||||
Child1Entity c1_1 = new Child1Entity("child1_1");
|
||||
Child1Entity c1_2 = new Child1Entity("child1_2");
|
||||
|
||||
Child2Entity c2_1 = new Child2Entity("child2_1");
|
||||
Child2Entity c2_2 = new Child2Entity("child2_2");
|
||||
|
||||
// Revision 1
|
||||
em.getTransaction().begin();
|
||||
|
||||
em.persist(p1);
|
||||
em.persist(p2);
|
||||
em.persist(c1_1);
|
||||
em.persist(c1_2);
|
||||
em.persist(c2_1);
|
||||
em.persist(c2_2);
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
// Revision 2 - (p1: c1_1, p2: c2_1)
|
||||
|
||||
em.getTransaction().begin();
|
||||
|
||||
p1 = em.find(ParentEntity.class, p1.getId());
|
||||
p2 = em.find(ParentEntity.class, p2.getId());
|
||||
c1_1 = em.find(Child1Entity.class, c1_1.getId());
|
||||
c2_1 = em.find(Child2Entity.class, c2_1.getId());
|
||||
|
||||
p1.getChildren1().add(c1_1);
|
||||
p2.getChildren2().add(c2_1);
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
// Revision 3 - (p1: c1_1, c1_2, c2_2, p2: c1_1, c2_1)
|
||||
em.getTransaction().begin();
|
||||
|
||||
p1 = em.find(ParentEntity.class, p1.getId());
|
||||
p2 = em.find(ParentEntity.class, p2.getId());
|
||||
c1_1 = em.find(Child1Entity.class, c1_1.getId());
|
||||
c1_2 = em.find(Child1Entity.class, c1_2.getId());
|
||||
c2_2 = em.find(Child2Entity.class, c2_2.getId());
|
||||
|
||||
p1.getChildren1().add(c1_2);
|
||||
p1.getChildren2().add(c2_2);
|
||||
|
||||
p2.getChildren1().add(c1_1);
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
// Revision 4 - (p1: c1_2, c2_2, p2: c1_1, c2_1, c2_2)
|
||||
em.getTransaction().begin();
|
||||
|
||||
p1 = em.find(ParentEntity.class, p1.getId());
|
||||
p2 = em.find(ParentEntity.class, p2.getId());
|
||||
c1_1 = em.find(Child1Entity.class, c1_1.getId());
|
||||
c2_2 = em.find(Child2Entity.class, c2_2.getId());
|
||||
|
||||
p1.getChildren1().remove(c1_1);
|
||||
p2.getChildren2().add(c2_2);
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
// Revision 5 - (p1: c2_2, p2: c1_1, c2_1)
|
||||
em.getTransaction().begin();
|
||||
|
||||
p1 = em.find(ParentEntity.class, p1.getId());
|
||||
p2 = em.find(ParentEntity.class, p2.getId());
|
||||
c1_2 = em.find(Child1Entity.class, c1_2.getId());
|
||||
c2_2 = em.find(Child2Entity.class, c2_2.getId());
|
||||
|
||||
c2_2.getParents().remove(p2);
|
||||
c1_2.getParents().remove(p1);
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
//
|
||||
|
||||
p1_id = p1.getId();
|
||||
p2_id = p2.getId();
|
||||
c1_1_id = c1_1.getId();
|
||||
c1_2_id = c1_2.getId();
|
||||
c2_1_id = c2_1.getId();
|
||||
c2_2_id = c2_2.getId();
|
||||
|
||||
Set<Number> revisionNumbers = new HashSet<Number>();
|
||||
revisionNumbers.addAll(Arrays.asList(1, 2, 3, 4, 5));
|
||||
revisions = getAuditReader().findRevisions(CustomDateRevEntity.class,
|
||||
revisionNumbers);
|
||||
|
||||
assert revisions.size() == 5;
|
||||
}
|
||||
|
||||
@Test(enabled = true)
|
||||
public void testRevisionsCounts() {
|
||||
assert Arrays.asList(1, 2, 3, 4).equals(
|
||||
getAuditReader().getRevisions(ParentEntity.class, p1_id));
|
||||
assert Arrays.asList(1, 2, 3, 4).equals(
|
||||
getAuditReader().getRevisions(ParentEntity.class, p2_id));
|
||||
|
||||
assert Arrays.asList(1).equals(
|
||||
getAuditReader().getRevisions(Child1Entity.class, c1_1_id));
|
||||
assert Arrays.asList(1, 5).equals(
|
||||
getAuditReader().getRevisions(Child1Entity.class, c1_2_id));
|
||||
|
||||
assert Arrays.asList(1).equals(
|
||||
getAuditReader().getRevisions(Child2Entity.class, c2_1_id));
|
||||
assert Arrays.asList(1, 5).equals(
|
||||
getAuditReader().getRevisions(Child2Entity.class, c2_2_id));
|
||||
}
|
||||
|
||||
@Test(enabled = true)
|
||||
public void testAllRevEndTimeStamps() {
|
||||
List<Map<String, Object>> p1RevList = getRevisions(ParentEntity.class,
|
||||
p1_id);
|
||||
List<Map<String, Object>> p2RevList = getRevisions(ParentEntity.class,
|
||||
p2_id);
|
||||
List<Map<String, Object>> c1_1_List = getRevisions(Child1Entity.class,
|
||||
c1_1_id);
|
||||
List<Map<String, Object>> c1_2_List = getRevisions(Child1Entity.class,
|
||||
c1_2_id);
|
||||
List<Map<String, Object>> c2_1_List = getRevisions(Child2Entity.class,
|
||||
c2_1_id);
|
||||
List<Map<String, Object>> c2_2_List = getRevisions(Child2Entity.class,
|
||||
c2_2_id);
|
||||
|
||||
verifyRevEndTimeStamps("ParentEntity: " + p1_id, p1RevList);
|
||||
verifyRevEndTimeStamps("ParentEntity: " + p2_id, p2RevList);
|
||||
verifyRevEndTimeStamps("Child1Entity: " + c1_1_id, c1_1_List);
|
||||
verifyRevEndTimeStamps("Child1Entity: " + c1_2_id, c1_2_List);
|
||||
verifyRevEndTimeStamps("Child2Entity: " + c2_1_id, c2_1_List);
|
||||
verifyRevEndTimeStamps("Child2Entity: " + c2_2_id, c2_2_List);
|
||||
|
||||
}
|
||||
|
||||
@Test(enabled = true)
|
||||
public void testHistoryOfParent1() {
|
||||
|
||||
Child1Entity c1_1 = getEntityManager()
|
||||
.find(Child1Entity.class, c1_1_id);
|
||||
Child1Entity c1_2 = getEntityManager()
|
||||
.find(Child1Entity.class, c1_2_id);
|
||||
Child2Entity c2_2 = getEntityManager()
|
||||
.find(Child2Entity.class, c2_2_id);
|
||||
|
||||
ParentEntity rev1 = getAuditReader().find(ParentEntity.class, p1_id, 1);
|
||||
ParentEntity rev2 = getAuditReader().find(ParentEntity.class, p1_id, 2);
|
||||
ParentEntity rev3 = getAuditReader().find(ParentEntity.class, p1_id, 3);
|
||||
ParentEntity rev4 = getAuditReader().find(ParentEntity.class, p1_id, 4);
|
||||
ParentEntity rev5 = getAuditReader().find(ParentEntity.class, p1_id, 5);
|
||||
|
||||
assert TestTools.checkList(rev1.getChildren1());
|
||||
assert TestTools.checkList(rev2.getChildren1(), c1_1);
|
||||
assert TestTools.checkList(rev3.getChildren1(), c1_1, c1_2);
|
||||
assert TestTools.checkList(rev4.getChildren1(), c1_2);
|
||||
assert TestTools.checkList(rev5.getChildren1());
|
||||
|
||||
assert TestTools.checkList(rev1.getChildren2());
|
||||
assert TestTools.checkList(rev2.getChildren2());
|
||||
assert TestTools.checkList(rev3.getChildren2(), c2_2);
|
||||
assert TestTools.checkList(rev4.getChildren2(), c2_2);
|
||||
assert TestTools.checkList(rev5.getChildren2(), c2_2);
|
||||
}
|
||||
|
||||
@Test(enabled = true)
|
||||
public void testHistoryOfParent2() {
|
||||
Child1Entity c1_1 = getEntityManager()
|
||||
.find(Child1Entity.class, c1_1_id);
|
||||
Child2Entity c2_1 = getEntityManager()
|
||||
.find(Child2Entity.class, c2_1_id);
|
||||
Child2Entity c2_2 = getEntityManager()
|
||||
.find(Child2Entity.class, c2_2_id);
|
||||
|
||||
ParentEntity rev1 = getAuditReader().find(ParentEntity.class, p2_id, 1);
|
||||
ParentEntity rev2 = getAuditReader().find(ParentEntity.class, p2_id, 2);
|
||||
ParentEntity rev3 = getAuditReader().find(ParentEntity.class, p2_id, 3);
|
||||
ParentEntity rev4 = getAuditReader().find(ParentEntity.class, p2_id, 4);
|
||||
ParentEntity rev5 = getAuditReader().find(ParentEntity.class, p2_id, 5);
|
||||
|
||||
assert TestTools.checkList(rev1.getChildren1());
|
||||
assert TestTools.checkList(rev2.getChildren1());
|
||||
assert TestTools.checkList(rev3.getChildren1(), c1_1);
|
||||
assert TestTools.checkList(rev4.getChildren1(), c1_1);
|
||||
assert TestTools.checkList(rev5.getChildren1(), c1_1);
|
||||
|
||||
assert TestTools.checkList(rev1.getChildren2());
|
||||
assert TestTools.checkList(rev2.getChildren2(), c2_1);
|
||||
assert TestTools.checkList(rev3.getChildren2(), c2_1);
|
||||
assert TestTools.checkList(rev4.getChildren2(), c2_1, c2_2);
|
||||
assert TestTools.checkList(rev5.getChildren2(), c2_1);
|
||||
}
|
||||
|
||||
@Test(enabled = true)
|
||||
public void testHistoryOfChild1_1() {
|
||||
ParentEntity p1 = getEntityManager().find(ParentEntity.class, p1_id);
|
||||
ParentEntity p2 = getEntityManager().find(ParentEntity.class, p2_id);
|
||||
|
||||
Child1Entity rev1 = getAuditReader().find(Child1Entity.class, c1_1_id,
|
||||
1);
|
||||
Child1Entity rev2 = getAuditReader().find(Child1Entity.class, c1_1_id,
|
||||
2);
|
||||
Child1Entity rev3 = getAuditReader().find(Child1Entity.class, c1_1_id,
|
||||
3);
|
||||
Child1Entity rev4 = getAuditReader().find(Child1Entity.class, c1_1_id,
|
||||
4);
|
||||
Child1Entity rev5 = getAuditReader().find(Child1Entity.class, c1_1_id,
|
||||
5);
|
||||
|
||||
assert TestTools.checkList(rev1.getParents());
|
||||
assert TestTools.checkList(rev2.getParents(), p1);
|
||||
assert TestTools.checkList(rev3.getParents(), p1, p2);
|
||||
assert TestTools.checkList(rev4.getParents(), p2);
|
||||
assert TestTools.checkList(rev5.getParents(), p2);
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
public void testHistoryOfChild1_2() {
|
||||
ParentEntity p1 = getEntityManager().find(ParentEntity.class, p1_id);
|
||||
|
||||
Child1Entity rev1 = getAuditReader().find(Child1Entity.class, c1_2_id,
|
||||
1);
|
||||
Child1Entity rev2 = getAuditReader().find(Child1Entity.class, c1_2_id,
|
||||
2);
|
||||
Child1Entity rev3 = getAuditReader().find(Child1Entity.class, c1_2_id,
|
||||
3);
|
||||
Child1Entity rev4 = getAuditReader().find(Child1Entity.class, c1_2_id,
|
||||
4);
|
||||
Child1Entity rev5 = getAuditReader().find(Child1Entity.class, c1_2_id,
|
||||
5);
|
||||
|
||||
assert TestTools.checkList(rev1.getParents());
|
||||
assert TestTools.checkList(rev2.getParents());
|
||||
assert TestTools.checkList(rev3.getParents(), p1);
|
||||
assert TestTools.checkList(rev4.getParents(), p1);
|
||||
assert TestTools.checkList(rev5.getParents());
|
||||
}
|
||||
|
||||
@Test(enabled = true)
|
||||
public void testHistoryOfChild2_1() {
|
||||
ParentEntity p2 = getEntityManager().find(ParentEntity.class, p2_id);
|
||||
|
||||
Child2Entity rev1 = getAuditReader().find(Child2Entity.class, c2_1_id,
|
||||
1);
|
||||
Child2Entity rev2 = getAuditReader().find(Child2Entity.class, c2_1_id,
|
||||
2);
|
||||
Child2Entity rev3 = getAuditReader().find(Child2Entity.class, c2_1_id,
|
||||
3);
|
||||
Child2Entity rev4 = getAuditReader().find(Child2Entity.class, c2_1_id,
|
||||
4);
|
||||
Child2Entity rev5 = getAuditReader().find(Child2Entity.class, c2_1_id,
|
||||
5);
|
||||
|
||||
assert TestTools.checkList(rev1.getParents());
|
||||
assert TestTools.checkList(rev2.getParents(), p2);
|
||||
assert TestTools.checkList(rev3.getParents(), p2);
|
||||
assert TestTools.checkList(rev4.getParents(), p2);
|
||||
assert TestTools.checkList(rev5.getParents(), p2);
|
||||
}
|
||||
|
||||
@Test(enabled = true)
|
||||
public void testHistoryOfChild2_2() {
|
||||
ParentEntity p1 = getEntityManager().find(ParentEntity.class, p1_id);
|
||||
ParentEntity p2 = getEntityManager().find(ParentEntity.class, p2_id);
|
||||
|
||||
Child2Entity rev1 = getAuditReader().find(Child2Entity.class, c2_2_id,
|
||||
1);
|
||||
Child2Entity rev2 = getAuditReader().find(Child2Entity.class, c2_2_id,
|
||||
2);
|
||||
Child2Entity rev3 = getAuditReader().find(Child2Entity.class, c2_2_id,
|
||||
3);
|
||||
Child2Entity rev4 = getAuditReader().find(Child2Entity.class, c2_2_id,
|
||||
4);
|
||||
Child2Entity rev5 = getAuditReader().find(Child2Entity.class, c2_2_id,
|
||||
5);
|
||||
|
||||
assert TestTools.checkList(rev1.getParents());
|
||||
assert TestTools.checkList(rev2.getParents());
|
||||
assert TestTools.checkList(rev3.getParents(), p1);
|
||||
assert TestTools.checkList(rev4.getParents(), p1, p2);
|
||||
assert TestTools.checkList(rev5.getParents(), p1);
|
||||
}
|
||||
|
||||
private List<Map<String, Object>> getRevisions(
|
||||
Class<?> originalEntityClazz, Integer originalEntityId) {
|
||||
// Build the query:
|
||||
// select auditEntity from
|
||||
// org.hibernate.envers.test.entities.manytomany.sametable.ParentEntity_AUD
|
||||
// auditEntity where auditEntity.originalId.id = :originalEntityId
|
||||
|
||||
StringBuilder builder = new StringBuilder("select auditEntity from ");
|
||||
builder.append(originalEntityClazz.getName())
|
||||
.append("_AUD auditEntity");
|
||||
builder.append(" where auditEntity.originalId.id = :originalEntityId");
|
||||
|
||||
Query qry = getEntityManager().createQuery(builder.toString());
|
||||
qry.setParameter("originalEntityId", originalEntityId);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> resultList = qry.getResultList();
|
||||
return resultList;
|
||||
}
|
||||
|
||||
private void verifyRevEndTimeStamps(String debugInfo,
|
||||
List<Map<String, Object>> revisionEntities) {
|
||||
for (Map<String, Object> revisionEntity : revisionEntities) {
|
||||
|
||||
Date revendTimestamp = (Date) revisionEntity
|
||||
.get(revendTimestampColumName);
|
||||
CustomDateRevEntity revEnd = (CustomDateRevEntity) revisionEntity
|
||||
.get("REVEND");
|
||||
|
||||
if (revendTimestamp == null) {
|
||||
assert revEnd == null;
|
||||
} else {
|
||||
assert revendTimestamp.getTime() == revEnd.getDateTimestamp().getTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,432 +0,0 @@
|
||||
/*
|
||||
* 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.strategy;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.ejb.Ejb3Configuration;
|
||||
import org.hibernate.envers.DefaultRevisionEntity;
|
||||
import org.hibernate.envers.strategy.ValidityAuditStrategy;
|
||||
import org.hibernate.envers.test.AbstractEntityTest;
|
||||
import org.hibernate.envers.test.entities.manytomany.sametable.Child1Entity;
|
||||
import org.hibernate.envers.test.entities.manytomany.sametable.Child2Entity;
|
||||
import org.hibernate.envers.test.entities.manytomany.sametable.ParentEntity;
|
||||
import org.hibernate.envers.test.tools.TestTools;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Test which checks that the revision end timestamp is correctly set for
|
||||
* {@link ValidityAuditStrategy}.
|
||||
*
|
||||
* @author Erik-Berndt Scheper
|
||||
*/
|
||||
public class ValidityAuditStrategyRevEndTsTest extends AbstractEntityTest {
|
||||
private final String revendTimestampColumName = "REVEND_TIMESTAMP";
|
||||
|
||||
private Integer p1_id;
|
||||
private Integer p2_id;
|
||||
private Integer c1_1_id;
|
||||
private Integer c1_2_id;
|
||||
private Integer c2_1_id;
|
||||
private Integer c2_2_id;
|
||||
private Map<Number, DefaultRevisionEntity> revisions;
|
||||
|
||||
public void configure(Ejb3Configuration cfg) {
|
||||
cfg.addAnnotatedClass(ParentEntity.class);
|
||||
cfg.addAnnotatedClass(Child1Entity.class);
|
||||
cfg.addAnnotatedClass(Child2Entity.class);
|
||||
|
||||
cfg.setProperty("org.hibernate.envers.audit_strategy",
|
||||
"org.hibernate.envers.strategy.ValidityAuditStrategy");
|
||||
cfg
|
||||
.setProperty(
|
||||
"org.hibernate.envers.audit_strategy_validity_store_revend_timestamp",
|
||||
"true");
|
||||
cfg
|
||||
.setProperty(
|
||||
"org.hibernate.envers.audit_strategy_validity_revend_timestamp_field_name",
|
||||
revendTimestampColumName);
|
||||
}
|
||||
|
||||
@BeforeClass(enabled = true, dependsOnMethods = "init")
|
||||
public void initData() {
|
||||
EntityManager em = getEntityManager();
|
||||
|
||||
// We need first to modify the columns in the middle (join table) to
|
||||
// allow null values. Hbm2ddl doesn't seem
|
||||
// to allow this.
|
||||
em.getTransaction().begin();
|
||||
Session session = (Session) em.getDelegate();
|
||||
session.createSQLQuery("DROP TABLE children").executeUpdate();
|
||||
session
|
||||
.createSQLQuery(
|
||||
"CREATE TABLE children(parent_id integer, child1_id integer NULL, child2_id integer NULL)")
|
||||
.executeUpdate();
|
||||
session.createSQLQuery("DROP TABLE children_AUD").executeUpdate();
|
||||
session
|
||||
.createSQLQuery(
|
||||
"CREATE TABLE children_AUD(REV integer NOT NULL, REVEND integer, "
|
||||
+ revendTimestampColumName
|
||||
+ " timestamp, REVTYPE tinyint, "
|
||||
+ "parent_id integer, child1_id integer NULL, child2_id integer NULL)")
|
||||
.executeUpdate();
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
ParentEntity p1 = new ParentEntity("parent_1");
|
||||
ParentEntity p2 = new ParentEntity("parent_2");
|
||||
|
||||
Child1Entity c1_1 = new Child1Entity("child1_1");
|
||||
Child1Entity c1_2 = new Child1Entity("child1_2");
|
||||
|
||||
Child2Entity c2_1 = new Child2Entity("child2_1");
|
||||
Child2Entity c2_2 = new Child2Entity("child2_2");
|
||||
|
||||
// Revision 1
|
||||
em.getTransaction().begin();
|
||||
|
||||
em.persist(p1);
|
||||
em.persist(p2);
|
||||
em.persist(c1_1);
|
||||
em.persist(c1_2);
|
||||
em.persist(c2_1);
|
||||
em.persist(c2_2);
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
// Revision 2 - (p1: c1_1, p2: c2_1)
|
||||
|
||||
em.getTransaction().begin();
|
||||
|
||||
p1 = em.find(ParentEntity.class, p1.getId());
|
||||
p2 = em.find(ParentEntity.class, p2.getId());
|
||||
c1_1 = em.find(Child1Entity.class, c1_1.getId());
|
||||
c2_1 = em.find(Child2Entity.class, c2_1.getId());
|
||||
|
||||
p1.getChildren1().add(c1_1);
|
||||
p2.getChildren2().add(c2_1);
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
// Revision 3 - (p1: c1_1, c1_2, c2_2, p2: c1_1, c2_1)
|
||||
em.getTransaction().begin();
|
||||
|
||||
p1 = em.find(ParentEntity.class, p1.getId());
|
||||
p2 = em.find(ParentEntity.class, p2.getId());
|
||||
c1_1 = em.find(Child1Entity.class, c1_1.getId());
|
||||
c1_2 = em.find(Child1Entity.class, c1_2.getId());
|
||||
c2_2 = em.find(Child2Entity.class, c2_2.getId());
|
||||
|
||||
p1.getChildren1().add(c1_2);
|
||||
p1.getChildren2().add(c2_2);
|
||||
|
||||
p2.getChildren1().add(c1_1);
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
// Revision 4 - (p1: c1_2, c2_2, p2: c1_1, c2_1, c2_2)
|
||||
em.getTransaction().begin();
|
||||
|
||||
p1 = em.find(ParentEntity.class, p1.getId());
|
||||
p2 = em.find(ParentEntity.class, p2.getId());
|
||||
c1_1 = em.find(Child1Entity.class, c1_1.getId());
|
||||
c2_2 = em.find(Child2Entity.class, c2_2.getId());
|
||||
|
||||
p1.getChildren1().remove(c1_1);
|
||||
p2.getChildren2().add(c2_2);
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
// Revision 5 - (p1: c2_2, p2: c1_1, c2_1)
|
||||
em.getTransaction().begin();
|
||||
|
||||
p1 = em.find(ParentEntity.class, p1.getId());
|
||||
p2 = em.find(ParentEntity.class, p2.getId());
|
||||
c1_2 = em.find(Child1Entity.class, c1_2.getId());
|
||||
c2_2 = em.find(Child2Entity.class, c2_2.getId());
|
||||
|
||||
c2_2.getParents().remove(p2);
|
||||
c1_2.getParents().remove(p1);
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
//
|
||||
|
||||
p1_id = p1.getId();
|
||||
p2_id = p2.getId();
|
||||
c1_1_id = c1_1.getId();
|
||||
c1_2_id = c1_2.getId();
|
||||
c2_1_id = c2_1.getId();
|
||||
c2_2_id = c2_2.getId();
|
||||
|
||||
Set<Number> revisionNumbers = new HashSet<Number>();
|
||||
revisionNumbers.addAll(Arrays.asList(1, 2, 3, 4, 5));
|
||||
revisions = getAuditReader().findRevisions(DefaultRevisionEntity.class,
|
||||
revisionNumbers);
|
||||
|
||||
assert revisions.size() == 5;
|
||||
}
|
||||
|
||||
@Test(enabled = true)
|
||||
public void testRevisionsCounts() {
|
||||
assert Arrays.asList(1, 2, 3, 4).equals(
|
||||
getAuditReader().getRevisions(ParentEntity.class, p1_id));
|
||||
assert Arrays.asList(1, 2, 3, 4).equals(
|
||||
getAuditReader().getRevisions(ParentEntity.class, p2_id));
|
||||
|
||||
assert Arrays.asList(1).equals(
|
||||
getAuditReader().getRevisions(Child1Entity.class, c1_1_id));
|
||||
assert Arrays.asList(1, 5).equals(
|
||||
getAuditReader().getRevisions(Child1Entity.class, c1_2_id));
|
||||
|
||||
assert Arrays.asList(1).equals(
|
||||
getAuditReader().getRevisions(Child2Entity.class, c2_1_id));
|
||||
assert Arrays.asList(1, 5).equals(
|
||||
getAuditReader().getRevisions(Child2Entity.class, c2_2_id));
|
||||
}
|
||||
|
||||
@Test(enabled = true)
|
||||
public void testAllRevEndTimeStamps() {
|
||||
List<Map<String, Object>> p1RevList = getRevisions(ParentEntity.class,
|
||||
p1_id);
|
||||
List<Map<String, Object>> p2RevList = getRevisions(ParentEntity.class,
|
||||
p2_id);
|
||||
List<Map<String, Object>> c1_1_List = getRevisions(Child1Entity.class,
|
||||
c1_1_id);
|
||||
List<Map<String, Object>> c1_2_List = getRevisions(Child1Entity.class,
|
||||
c1_2_id);
|
||||
List<Map<String, Object>> c2_1_List = getRevisions(Child2Entity.class,
|
||||
c2_1_id);
|
||||
List<Map<String, Object>> c2_2_List = getRevisions(Child2Entity.class,
|
||||
c2_2_id);
|
||||
|
||||
verifyRevEndTimeStamps("ParentEntity: " + p1_id, p1RevList);
|
||||
verifyRevEndTimeStamps("ParentEntity: " + p2_id, p2RevList);
|
||||
verifyRevEndTimeStamps("Child1Entity: " + c1_1_id, c1_1_List);
|
||||
verifyRevEndTimeStamps("Child1Entity: " + c1_2_id, c1_2_List);
|
||||
verifyRevEndTimeStamps("Child2Entity: " + c2_1_id, c2_1_List);
|
||||
verifyRevEndTimeStamps("Child2Entity: " + c2_2_id, c2_2_List);
|
||||
|
||||
}
|
||||
|
||||
@Test(enabled = true)
|
||||
public void testHistoryOfParent1() {
|
||||
|
||||
Child1Entity c1_1 = getEntityManager()
|
||||
.find(Child1Entity.class, c1_1_id);
|
||||
Child1Entity c1_2 = getEntityManager()
|
||||
.find(Child1Entity.class, c1_2_id);
|
||||
Child2Entity c2_2 = getEntityManager()
|
||||
.find(Child2Entity.class, c2_2_id);
|
||||
|
||||
ParentEntity rev1 = getAuditReader().find(ParentEntity.class, p1_id, 1);
|
||||
ParentEntity rev2 = getAuditReader().find(ParentEntity.class, p1_id, 2);
|
||||
ParentEntity rev3 = getAuditReader().find(ParentEntity.class, p1_id, 3);
|
||||
ParentEntity rev4 = getAuditReader().find(ParentEntity.class, p1_id, 4);
|
||||
ParentEntity rev5 = getAuditReader().find(ParentEntity.class, p1_id, 5);
|
||||
|
||||
assert TestTools.checkList(rev1.getChildren1());
|
||||
assert TestTools.checkList(rev2.getChildren1(), c1_1);
|
||||
assert TestTools.checkList(rev3.getChildren1(), c1_1, c1_2);
|
||||
assert TestTools.checkList(rev4.getChildren1(), c1_2);
|
||||
assert TestTools.checkList(rev5.getChildren1());
|
||||
|
||||
assert TestTools.checkList(rev1.getChildren2());
|
||||
assert TestTools.checkList(rev2.getChildren2());
|
||||
assert TestTools.checkList(rev3.getChildren2(), c2_2);
|
||||
assert TestTools.checkList(rev4.getChildren2(), c2_2);
|
||||
assert TestTools.checkList(rev5.getChildren2(), c2_2);
|
||||
}
|
||||
|
||||
@Test(enabled = true)
|
||||
public void testHistoryOfParent2() {
|
||||
Child1Entity c1_1 = getEntityManager()
|
||||
.find(Child1Entity.class, c1_1_id);
|
||||
Child2Entity c2_1 = getEntityManager()
|
||||
.find(Child2Entity.class, c2_1_id);
|
||||
Child2Entity c2_2 = getEntityManager()
|
||||
.find(Child2Entity.class, c2_2_id);
|
||||
|
||||
ParentEntity rev1 = getAuditReader().find(ParentEntity.class, p2_id, 1);
|
||||
ParentEntity rev2 = getAuditReader().find(ParentEntity.class, p2_id, 2);
|
||||
ParentEntity rev3 = getAuditReader().find(ParentEntity.class, p2_id, 3);
|
||||
ParentEntity rev4 = getAuditReader().find(ParentEntity.class, p2_id, 4);
|
||||
ParentEntity rev5 = getAuditReader().find(ParentEntity.class, p2_id, 5);
|
||||
|
||||
assert TestTools.checkList(rev1.getChildren1());
|
||||
assert TestTools.checkList(rev2.getChildren1());
|
||||
assert TestTools.checkList(rev3.getChildren1(), c1_1);
|
||||
assert TestTools.checkList(rev4.getChildren1(), c1_1);
|
||||
assert TestTools.checkList(rev5.getChildren1(), c1_1);
|
||||
|
||||
assert TestTools.checkList(rev1.getChildren2());
|
||||
assert TestTools.checkList(rev2.getChildren2(), c2_1);
|
||||
assert TestTools.checkList(rev3.getChildren2(), c2_1);
|
||||
assert TestTools.checkList(rev4.getChildren2(), c2_1, c2_2);
|
||||
assert TestTools.checkList(rev5.getChildren2(), c2_1);
|
||||
}
|
||||
|
||||
@Test(enabled = true)
|
||||
public void testHistoryOfChild1_1() {
|
||||
ParentEntity p1 = getEntityManager().find(ParentEntity.class, p1_id);
|
||||
ParentEntity p2 = getEntityManager().find(ParentEntity.class, p2_id);
|
||||
|
||||
Child1Entity rev1 = getAuditReader().find(Child1Entity.class, c1_1_id,
|
||||
1);
|
||||
Child1Entity rev2 = getAuditReader().find(Child1Entity.class, c1_1_id,
|
||||
2);
|
||||
Child1Entity rev3 = getAuditReader().find(Child1Entity.class, c1_1_id,
|
||||
3);
|
||||
Child1Entity rev4 = getAuditReader().find(Child1Entity.class, c1_1_id,
|
||||
4);
|
||||
Child1Entity rev5 = getAuditReader().find(Child1Entity.class, c1_1_id,
|
||||
5);
|
||||
|
||||
assert TestTools.checkList(rev1.getParents());
|
||||
assert TestTools.checkList(rev2.getParents(), p1);
|
||||
assert TestTools.checkList(rev3.getParents(), p1, p2);
|
||||
assert TestTools.checkList(rev4.getParents(), p2);
|
||||
assert TestTools.checkList(rev5.getParents(), p2);
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
public void testHistoryOfChild1_2() {
|
||||
ParentEntity p1 = getEntityManager().find(ParentEntity.class, p1_id);
|
||||
|
||||
Child1Entity rev1 = getAuditReader().find(Child1Entity.class, c1_2_id,
|
||||
1);
|
||||
Child1Entity rev2 = getAuditReader().find(Child1Entity.class, c1_2_id,
|
||||
2);
|
||||
Child1Entity rev3 = getAuditReader().find(Child1Entity.class, c1_2_id,
|
||||
3);
|
||||
Child1Entity rev4 = getAuditReader().find(Child1Entity.class, c1_2_id,
|
||||
4);
|
||||
Child1Entity rev5 = getAuditReader().find(Child1Entity.class, c1_2_id,
|
||||
5);
|
||||
|
||||
assert TestTools.checkList(rev1.getParents());
|
||||
assert TestTools.checkList(rev2.getParents());
|
||||
assert TestTools.checkList(rev3.getParents(), p1);
|
||||
assert TestTools.checkList(rev4.getParents(), p1);
|
||||
assert TestTools.checkList(rev5.getParents());
|
||||
}
|
||||
|
||||
@Test(enabled = true)
|
||||
public void testHistoryOfChild2_1() {
|
||||
ParentEntity p2 = getEntityManager().find(ParentEntity.class, p2_id);
|
||||
|
||||
Child2Entity rev1 = getAuditReader().find(Child2Entity.class, c2_1_id,
|
||||
1);
|
||||
Child2Entity rev2 = getAuditReader().find(Child2Entity.class, c2_1_id,
|
||||
2);
|
||||
Child2Entity rev3 = getAuditReader().find(Child2Entity.class, c2_1_id,
|
||||
3);
|
||||
Child2Entity rev4 = getAuditReader().find(Child2Entity.class, c2_1_id,
|
||||
4);
|
||||
Child2Entity rev5 = getAuditReader().find(Child2Entity.class, c2_1_id,
|
||||
5);
|
||||
|
||||
assert TestTools.checkList(rev1.getParents());
|
||||
assert TestTools.checkList(rev2.getParents(), p2);
|
||||
assert TestTools.checkList(rev3.getParents(), p2);
|
||||
assert TestTools.checkList(rev4.getParents(), p2);
|
||||
assert TestTools.checkList(rev5.getParents(), p2);
|
||||
}
|
||||
|
||||
@Test(enabled = true)
|
||||
public void testHistoryOfChild2_2() {
|
||||
ParentEntity p1 = getEntityManager().find(ParentEntity.class, p1_id);
|
||||
ParentEntity p2 = getEntityManager().find(ParentEntity.class, p2_id);
|
||||
|
||||
Child2Entity rev1 = getAuditReader().find(Child2Entity.class, c2_2_id,
|
||||
1);
|
||||
Child2Entity rev2 = getAuditReader().find(Child2Entity.class, c2_2_id,
|
||||
2);
|
||||
Child2Entity rev3 = getAuditReader().find(Child2Entity.class, c2_2_id,
|
||||
3);
|
||||
Child2Entity rev4 = getAuditReader().find(Child2Entity.class, c2_2_id,
|
||||
4);
|
||||
Child2Entity rev5 = getAuditReader().find(Child2Entity.class, c2_2_id,
|
||||
5);
|
||||
|
||||
assert TestTools.checkList(rev1.getParents());
|
||||
assert TestTools.checkList(rev2.getParents());
|
||||
assert TestTools.checkList(rev3.getParents(), p1);
|
||||
assert TestTools.checkList(rev4.getParents(), p1, p2);
|
||||
assert TestTools.checkList(rev5.getParents(), p1);
|
||||
}
|
||||
|
||||
private List<Map<String, Object>> getRevisions(
|
||||
Class<?> originalEntityClazz, Integer originalEntityId) {
|
||||
// Build the query:
|
||||
// select auditEntity from
|
||||
// org.hibernate.envers.test.entities.manytomany.sametable.ParentEntity_AUD
|
||||
// auditEntity where auditEntity.originalId.id = :originalEntityId
|
||||
|
||||
StringBuilder builder = new StringBuilder("select auditEntity from ");
|
||||
builder.append(originalEntityClazz.getName())
|
||||
.append("_AUD auditEntity");
|
||||
builder.append(" where auditEntity.originalId.id = :originalEntityId");
|
||||
|
||||
Query qry = getEntityManager().createQuery(builder.toString());
|
||||
qry.setParameter("originalEntityId", originalEntityId);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> resultList = qry.getResultList();
|
||||
return resultList;
|
||||
}
|
||||
|
||||
private void verifyRevEndTimeStamps(String debugInfo,
|
||||
List<Map<String, Object>> revisionEntities) {
|
||||
for (Map<String, Object> revisionEntity : revisionEntities) {
|
||||
|
||||
Date revendTimestamp = (Date) revisionEntity
|
||||
.get(revendTimestampColumName);
|
||||
DefaultRevisionEntity revEnd = (DefaultRevisionEntity) revisionEntity
|
||||
.get("REVEND");
|
||||
|
||||
if (revendTimestamp == null) {
|
||||
assert revEnd == null;
|
||||
} else {
|
||||
assert revendTimestamp.getTime() == revEnd.getTimestamp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -68,7 +68,6 @@
|
||||
<package name="org.hibernate.envers.test.integration.secondary" />
|
||||
<package name="org.hibernate.envers.test.integration.secondary.ids" />
|
||||
<package name="org.hibernate.envers.test.integration.serialization" />
|
||||
<package name="org.hibernate.envers.test.integration.strategy" />
|
||||
<package name="org.hibernate.envers.test.integration.superclass" />
|
||||
<package name="org.hibernate.envers.test.integration.entityNames.auditedEntity" />
|
||||
<package name="org.hibernate.envers.test.integration.entityNames.manyToManyAudited" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user