HHH-3764:
- adding an end-revision column to the audit entities if the appropraite strategy is used HHH-3765: - filling in the end-revision column on audited entities changes - applying patch by Stephanie Pau - thanks! git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@19888 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
db16c3f29a
commit
f7c7c55e2a
|
@ -27,10 +27,12 @@ import java.util.Map;
|
|||
import java.util.Properties;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.envers.entities.EntitiesConfigurations;
|
||||
import org.hibernate.envers.revisioninfo.RevisionInfoNumberReader;
|
||||
import org.hibernate.envers.revisioninfo.RevisionInfoQueryCreator;
|
||||
import org.hibernate.envers.synchronization.AuditProcessManager;
|
||||
import org.hibernate.envers.strategy.AuditStrategy;
|
||||
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.AnnotationConfiguration;
|
||||
|
@ -38,11 +40,13 @@ import org.hibernate.annotations.common.reflection.ReflectionManager;
|
|||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
* @author Stephanie Pau at Markit Group Plc
|
||||
*/
|
||||
public class AuditConfiguration {
|
||||
private final GlobalConfiguration globalCfg;
|
||||
private final AuditEntitiesConfiguration auditEntCfg;
|
||||
private final AuditProcessManager auditProcessManager;
|
||||
private final AuditStrategy auditStrategy;
|
||||
private final EntitiesConfigurations entCfg;
|
||||
private final RevisionInfoQueryCreator revisionInfoQueryCreator;
|
||||
private final RevisionInfoNumberReader revisionInfoNumberReader;
|
||||
|
@ -71,7 +75,11 @@ public class AuditConfiguration {
|
|||
return revisionInfoNumberReader;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public AuditStrategy getAuditStrategy() {
|
||||
return auditStrategy;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public AuditConfiguration(Configuration cfg) {
|
||||
Properties properties = cfg.getProperties();
|
||||
|
||||
|
@ -81,6 +89,14 @@ public class AuditConfiguration {
|
|||
auditEntCfg = new AuditEntitiesConfiguration(properties, revInfoCfgResult.getRevisionInfoEntityName());
|
||||
globalCfg = new GlobalConfiguration(properties);
|
||||
auditProcessManager = new AuditProcessManager(revInfoCfgResult.getRevisionInfoGenerator());
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
revisionInfoQueryCreator = revInfoCfgResult.getRevisionInfoQueryCreator();
|
||||
revisionInfoNumberReader = revInfoCfgResult.getRevisionInfoNumberReader();
|
||||
entCfg = new EntitiesConfigurator().configure(cfg, reflectionManager, globalCfg, auditEntCfg,
|
||||
|
|
|
@ -25,18 +25,28 @@ package org.hibernate.envers.configuration;
|
|||
|
||||
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.ValidTimeAuditStrategy;
|
||||
|
||||
/**
|
||||
* Configuration of versions entities - names of fields, entities and tables created to store versioning information.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
* @author Stephanie Pau at Markit Group Plc
|
||||
*/
|
||||
public class AuditEntitiesConfiguration {
|
||||
private final String auditTablePrefix;
|
||||
private final String auditTableSuffix;
|
||||
|
||||
private final String auditStrategyName;
|
||||
private final String originalIdPropName;
|
||||
|
||||
private final String revisionFieldName;
|
||||
|
@ -50,6 +60,8 @@ public class AuditEntitiesConfiguration {
|
|||
|
||||
private final Map<String, String> customAuditTablesNames;
|
||||
|
||||
private final String revisionEndFieldName;
|
||||
|
||||
public AuditEntitiesConfiguration(Properties properties, String revisionInfoEntityName) {
|
||||
this.revisionInfoEntityName = revisionInfoEntityName;
|
||||
|
||||
|
@ -62,6 +74,11 @@ public class AuditEntitiesConfiguration {
|
|||
"org.hibernate.envers.auditTableSuffix",
|
||||
"_AUD");
|
||||
|
||||
auditStrategyName = getProperty(properties,
|
||||
"org.hibernate.envers.audit_strategy",
|
||||
"org.hibernate.envers.audit_strategy",
|
||||
DefaultAuditStrategy.class.getName());
|
||||
|
||||
originalIdPropName = "originalId";
|
||||
|
||||
revisionFieldName = getProperty(properties,
|
||||
|
@ -75,6 +92,11 @@ public class AuditEntitiesConfiguration {
|
|||
"REVTYPE");
|
||||
revisionTypePropType = "byte";
|
||||
|
||||
revisionEndFieldName = getProperty(properties,
|
||||
"org.hibernate.envers.audit_strategy_valid_time_end_name",
|
||||
"org.hibernate.envers.audit_strategy_valid_time_end_name",
|
||||
"REVEND");
|
||||
|
||||
customAuditTablesNames = new HashMap<String, String>();
|
||||
|
||||
revisionNumberPath = originalIdPropName + "." + revisionFieldName + ".id";
|
||||
|
@ -133,4 +155,12 @@ public class AuditEntitiesConfiguration {
|
|||
|
||||
return customHistoryTableName;
|
||||
}
|
||||
|
||||
public String getAuditStrategyName() {
|
||||
return auditStrategyName;
|
||||
}
|
||||
|
||||
public String getRevisionEndFieldName() {
|
||||
return revisionEndFieldName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.hibernate.envers.entities.mapper.CompositeMapperBuilder;
|
|||
import org.hibernate.envers.entities.mapper.ExtendedPropertyMapper;
|
||||
import org.hibernate.envers.entities.mapper.MultiPropertyMapper;
|
||||
import org.hibernate.envers.entities.mapper.SubclassPropertyMapper;
|
||||
import org.hibernate.envers.strategy.ValidTimeAuditStrategy;
|
||||
import org.hibernate.envers.tools.StringTools;
|
||||
import org.hibernate.envers.tools.Triple;
|
||||
import org.hibernate.envers.RelationTargetAuditMode;
|
||||
|
@ -53,6 +54,7 @@ import org.slf4j.LoggerFactory;
|
|||
* @author Adam Warski (adam at warski dot org)
|
||||
* @author Sebastian Komander
|
||||
* @author Tomasz Bech
|
||||
* @author Stephanie Pau at Markit Group Plc
|
||||
*/
|
||||
public final class AuditMetadataGenerator {
|
||||
private static final Logger log = LoggerFactory.getLogger(AuditMetadataGenerator.class);
|
||||
|
@ -124,6 +126,21 @@ public final class AuditMetadataGenerator {
|
|||
Element revTypeProperty = MetadataTools.addProperty(any_mapping, verEntCfg.getRevisionTypePropName(),
|
||||
verEntCfg.getRevisionTypePropType(), true, false);
|
||||
revTypeProperty.addAttribute("type", "org.hibernate.envers.entities.RevisionTypeType");
|
||||
|
||||
// Adding the end revision, if appropriate
|
||||
addEndRevision(any_mapping);
|
||||
}
|
||||
|
||||
private void addEndRevision(Element any_mapping) {
|
||||
// Add the end-revision field, if the appropriate strategy is used.
|
||||
if (ValidTimeAuditStrategy.class.getName().equals(verEntCfg.getAuditStrategyName())) {
|
||||
Element end_rev_mapping = (Element) revisionInfoRelationMapping.clone();
|
||||
end_rev_mapping.setName("many-to-one");
|
||||
end_rev_mapping.addAttribute("name", verEntCfg.getRevisionEndFieldName());
|
||||
MetadataTools.addOrModifyColumn(end_rev_mapping, verEntCfg.getRevisionEndFieldName());
|
||||
|
||||
any_mapping.add(end_rev_mapping);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
|
|
|
@ -24,9 +24,7 @@
|
|||
package org.hibernate.envers.query.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.NonUniqueResultException;
|
||||
|
||||
|
@ -80,15 +78,7 @@ public abstract class AbstractAuditQuery implements AuditQuery {
|
|||
}
|
||||
|
||||
protected List buildAndExecuteQuery() {
|
||||
StringBuilder querySb = new StringBuilder();
|
||||
Map<String, Object> queryParamValues = new HashMap<String, Object>();
|
||||
|
||||
qb.build(querySb, queryParamValues);
|
||||
|
||||
Query query = versionsReader.getSession().createQuery(querySb.toString());
|
||||
for (Map.Entry<String, Object> paramValue : queryParamValues.entrySet()) {
|
||||
query.setParameter(paramValue.getKey(), paramValue.getValue());
|
||||
}
|
||||
Query query = qb.toQuery(versionsReader.getSession());
|
||||
|
||||
setQueryProperties(query);
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package org.hibernate.envers.strategy;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||
import org.hibernate.envers.entities.mapper.PersistentCollectionChangeData;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Behaviours of different audit strategy for populating audit data.
|
||||
*
|
||||
* @author Stephanie Pau
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public interface AuditStrategy {
|
||||
/**
|
||||
* Perform the persistence of audited data for regular entities.
|
||||
*
|
||||
* @param session Session, which can be used to persist the data.
|
||||
* @param entityName Name of the entity, in which the audited change happens
|
||||
* @param auditCfg Audit configuration
|
||||
* @param id Id of the entity.
|
||||
* @param data Audit data to persist
|
||||
* @param revision Current revision data
|
||||
*/
|
||||
void perform(Session session, String entityName, AuditConfiguration auditCfg, Serializable id, Object data,
|
||||
Object revision);
|
||||
|
||||
/**
|
||||
* Perform the persistence of audited data for collection ("middle") entities.
|
||||
*
|
||||
* @param session Session, which can be used to persist the data.
|
||||
* @param auditCfg Audit configuration
|
||||
* @param persistentCollectionChangeData Collection change data to be persisted.
|
||||
* @param revision Current revision data
|
||||
*/
|
||||
void performCollectionChange(Session session, AuditConfiguration auditCfg,
|
||||
PersistentCollectionChangeData persistentCollectionChangeData, Object revision);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package org.hibernate.envers.strategy;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||
import org.hibernate.envers.entities.mapper.PersistentCollectionChangeData;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Default strategy is to simply persist the audit data.
|
||||
*
|
||||
* @author Adam Warski
|
||||
* @author Stephanie Pau
|
||||
*/
|
||||
public class DefaultAuditStrategy implements AuditStrategy {
|
||||
public void perform(Session session, String entityName, AuditConfiguration auditCfg, Serializable id, Object data,
|
||||
Object revision) {
|
||||
session.save(auditCfg.getAuditEntCfg().getAuditEntityName(entityName), data);
|
||||
}
|
||||
|
||||
public void performCollectionChange(Session session, AuditConfiguration auditCfg,
|
||||
PersistentCollectionChangeData persistentCollectionChangeData, Object revision) {
|
||||
session.save(persistentCollectionChangeData.getEntityName(), persistentCollectionChangeData.getData());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
package org.hibernate.envers.strategy;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.envers.RevisionType;
|
||||
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
||||
import org.hibernate.envers.entities.mapper.PersistentCollectionChangeData;
|
||||
import org.hibernate.envers.entities.mapper.id.IdMapper;
|
||||
import org.hibernate.envers.tools.query.QueryBuilder;
|
||||
|
||||
/**
|
||||
* Audit strategy which additionally manages the end-revision number: updates the end-revision field on the last
|
||||
* revision that was persisted before the current one.
|
||||
*
|
||||
* @author Stephanie Pau
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class ValidTimeAuditStrategy implements AuditStrategy {
|
||||
public void perform(Session session, String entityName, AuditConfiguration auditCfg, Serializable id, Object data,
|
||||
Object revision) {
|
||||
AuditEntitiesConfiguration audEntCfg = auditCfg.getAuditEntCfg();
|
||||
String auditedEntityName = audEntCfg.getAuditEntityName(entityName);
|
||||
|
||||
// Update the end date of the previous row if this operation is expected to have a previous row
|
||||
if (getRevisionType(auditCfg, data) != RevisionType.ADD) {
|
||||
/*
|
||||
Constructing a query:
|
||||
select e from audited_ent e where e.end_rev is null and e.id = :id
|
||||
*/
|
||||
|
||||
QueryBuilder qb = new QueryBuilder(auditedEntityName, "e");
|
||||
|
||||
// e.id = :id
|
||||
IdMapper idMapper = auditCfg.getEntCfg().get(entityName).getIdMapper();
|
||||
idMapper.addIdEqualsToQuery(qb.getRootParameters(), id, auditCfg.getAuditEntCfg().getOriginalIdPropName(), true);
|
||||
|
||||
updateLastRevision(session, auditCfg, qb, id, auditedEntityName, revision);
|
||||
}
|
||||
|
||||
// Save the audit data
|
||||
session.save(auditedEntityName, data);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
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
|
||||
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");
|
||||
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
||||
updateLastRevision(session, auditCfg, qb, originalId, persistentCollectionChangeData.getEntityName(), revision);
|
||||
}
|
||||
|
||||
// Save the audit data
|
||||
session.save(persistentCollectionChangeData.getEntityName(), persistentCollectionChangeData.getData());
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private RevisionType getRevisionType(AuditConfiguration auditCfg, Object data) {
|
||||
return (RevisionType) ((Map<String, Object>) data).get(auditCfg.getAuditEntCfg().getRevisionTypePropName());
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
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);
|
||||
|
||||
List l = qb.toQuery(session).list();
|
||||
|
||||
// There should be one entry
|
||||
if (l.size() == 1) {
|
||||
// Setting the end revision to be the current rev
|
||||
Object previousData = l.get(0);
|
||||
((Map<String, Object>) previousData).put(revisionEndFieldName, revision);
|
||||
|
||||
// Saving the previous version
|
||||
session.save(auditedEntityName, previousData);
|
||||
} else {
|
||||
throw new RuntimeException("Cannot find previous revision for entity " + auditedEntityName + " and id " + id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,15 +33,18 @@ import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
|||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.envers.strategy.AuditStrategy;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
* @author Stephanie Pau at Markit Group Plc
|
||||
*/
|
||||
public abstract class AbstractAuditWorkUnit implements AuditWorkUnit {
|
||||
protected final SessionImplementor sessionImplementor;
|
||||
protected final AuditConfiguration verCfg;
|
||||
protected final Serializable id;
|
||||
protected final String entityName;
|
||||
protected final AuditStrategy auditStrategy;
|
||||
|
||||
private Object performedData;
|
||||
|
||||
|
@ -51,6 +54,7 @@ public abstract class AbstractAuditWorkUnit implements AuditWorkUnit {
|
|||
this.verCfg = verCfg;
|
||||
this.id = id;
|
||||
this.entityName = entityName;
|
||||
this.auditStrategy = verCfg.getAuditStrategy();
|
||||
}
|
||||
|
||||
protected void fillDataWithId(Map<String, Object> data, Object revision, RevisionType revisionType) {
|
||||
|
@ -67,7 +71,7 @@ public abstract class AbstractAuditWorkUnit implements AuditWorkUnit {
|
|||
public void perform(Session session, Object revisionData) {
|
||||
Map<String, Object> data = generateData(revisionData);
|
||||
|
||||
session.save(verCfg.getAuditEntCfg().getAuditEntityName(getEntityName()), data);
|
||||
auditStrategy.perform(session, getEntityName(), verCfg, id, data, revisionData);
|
||||
|
||||
setPerformed(data);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.Map;
|
|||
import java.util.HashMap;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.hibernate.envers.RevisionType;
|
||||
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
||||
import org.hibernate.envers.entities.mapper.PersistentCollectionChangeData;
|
||||
|
@ -84,7 +85,7 @@ public class PersistentCollectionChangeWorkUnit extends AbstractAuditWorkUnit im
|
|||
((Map<String, Object>) persistentCollectionChangeData.getData().get(entitiesCfg.getOriginalIdPropName()))
|
||||
.put(entitiesCfg.getRevisionFieldName(), revisionData);
|
||||
|
||||
session.save(persistentCollectionChangeData.getEntityName(), persistentCollectionChangeData.getData());
|
||||
auditStrategy.performCollectionChange(session, verCfg, persistentCollectionChangeData, revisionData);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,13 +138,24 @@ public class PersistentCollectionChangeWorkUnit extends AbstractAuditWorkUnit im
|
|||
|
||||
// Including only those original changes, which are not overshadowed by new ones.
|
||||
for (PersistentCollectionChangeData originalCollectionChangeData : original.getCollectionChanges()) {
|
||||
if (!newChangesIdMap.containsKey(getOriginalId(originalCollectionChangeData))) {
|
||||
Object originalOriginalId = getOriginalId(originalCollectionChangeData);
|
||||
if (!newChangesIdMap.containsKey(originalOriginalId)) {
|
||||
mergedChanges.add(originalCollectionChangeData);
|
||||
} else {
|
||||
// If the changes collide, checking if the first one isn't a DEL, and the second a subsequent ADD
|
||||
// If so, removing the change alltogether.
|
||||
String revTypePropName = verCfg.getAuditEntCfg().getRevisionTypePropName();
|
||||
if (RevisionType.ADD.equals(newChangesIdMap.get(originalOriginalId).getData().get(
|
||||
revTypePropName)) && RevisionType.DEL.equals(originalCollectionChangeData.getData().get(
|
||||
revTypePropName))) {
|
||||
newChangesIdMap.remove(originalOriginalId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally adding all of the new changes to the end of the list
|
||||
mergedChanges.addAll(getCollectionChanges());
|
||||
// Finally adding all of the new changes to the end of the list (the map values may differ from
|
||||
// getCollectionChanges() because of the last operation above).
|
||||
mergedChanges.addAll(newChangesIdMap.values());
|
||||
|
||||
return new PersistentCollectionChangeWorkUnit(sessionImplementor, entityName, verCfg, id, mergedChanges,
|
||||
referencingPropertyName);
|
||||
|
|
|
@ -24,9 +24,12 @@
|
|||
package org.hibernate.envers.tools.query;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.envers.tools.MutableInteger;
|
||||
import org.hibernate.envers.tools.Pair;
|
||||
import org.hibernate.envers.tools.StringTools;
|
||||
|
@ -197,4 +200,18 @@ public class QueryBuilder {
|
|||
|
||||
return orderList;
|
||||
}
|
||||
|
||||
public Query toQuery(Session session) {
|
||||
StringBuilder querySb = new StringBuilder();
|
||||
Map<String, Object> queryParamValues = new HashMap<String, Object>();
|
||||
|
||||
build(querySb, queryParamValues);
|
||||
|
||||
Query query = session.createQuery(querySb.toString());
|
||||
for (Map.Entry<String, Object> paramValue : queryParamValues.entrySet()) {
|
||||
query.setParameter(paramValue.getKey(), paramValue.getValue());
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,9 +30,7 @@ import javax.persistence.EntityManagerFactory;
|
|||
import org.hibernate.envers.AuditReader;
|
||||
import org.hibernate.envers.AuditReaderFactory;
|
||||
import org.hibernate.envers.event.AuditEventListener;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.*;
|
||||
|
||||
import org.hibernate.ejb.Ejb3Configuration;
|
||||
import org.hibernate.event.*;
|
||||
|
@ -78,17 +76,23 @@ public abstract class AbstractEntityTest {
|
|||
}
|
||||
|
||||
@BeforeClass
|
||||
public void init() throws IOException {
|
||||
init(true);
|
||||
@Parameters("auditStrategy")
|
||||
public void init(@Optional String auditStrategy) throws IOException {
|
||||
init(true, auditStrategy);
|
||||
}
|
||||
|
||||
protected void init(boolean audited) throws IOException {
|
||||
protected void init(boolean audited, String auditStrategy) throws IOException {
|
||||
this.audited = audited;
|
||||
|
||||
cfg = new Ejb3Configuration();
|
||||
if (audited) {
|
||||
initListeners();
|
||||
}
|
||||
|
||||
if (auditStrategy != null && !"".equals(auditStrategy)) {
|
||||
cfg.setProperty("org.hibernate.envers.audit_strategy", auditStrategy);
|
||||
}
|
||||
|
||||
cfg.configure("hibernate.test.cfg.xml");
|
||||
configure(cfg);
|
||||
emf = cfg.buildEntityManagerFactory();
|
||||
|
|
|
@ -90,9 +90,6 @@ public class CompositeTestUserType implements CompositeUserType {
|
|||
public Object nullSafeGet(final ResultSet rs, final String[] names,
|
||||
final SessionImplementor session,
|
||||
final Object owner) throws HibernateException, SQLException {
|
||||
if (rs.wasNull()) {
|
||||
return null;
|
||||
}
|
||||
final String prop1 = rs.getString(names[0]);
|
||||
if (prop1 == null) {
|
||||
return null;
|
||||
|
|
|
@ -66,7 +66,7 @@ public class BasicSametable extends AbstractEntityTest {
|
|||
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, REVTYPE tinyint, " +
|
||||
session.createSQLQuery("CREATE TABLE children_AUD(REV integer NOT NULL, REVEND integer, REVTYPE tinyint, " +
|
||||
"parent_id integer, child1_id integer NULL, child2_id integer NULL)").executeUpdate();
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
|
|
@ -88,11 +88,11 @@ public abstract class AbstractPerformanceTest extends AbstractEntityTest {
|
|||
List<Long> unauditedRuns = new ArrayList<Long>();
|
||||
List<Long> auditedRuns = new ArrayList<Long>();
|
||||
|
||||
init(true);
|
||||
init(true, null);
|
||||
long audited = run(numberOfRuns, auditedRuns);
|
||||
close();
|
||||
|
||||
init(false);
|
||||
init(false, null);
|
||||
long unaudited = run(numberOfRuns, unauditedRuns);
|
||||
close();
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
<!--<property name="connection.username">root</property>-->
|
||||
<!--<property name="connection.password"></property>-->
|
||||
|
||||
<!--<property name="org.hibernate.envers.audit_strategy">org.hibernate.envers.strategy.ValidTimeAuditStrategy</property>-->
|
||||
|
||||
<!--<property name="hibernate.jdbc.batch_size">100</property>-->
|
||||
|
||||
<!--<event type="post-insert">
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
|
||||
|
||||
<suite name="Envers">
|
||||
<test name="All">
|
||||
<packages>
|
||||
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" [
|
||||
<!ENTITY packages '
|
||||
<package name="org.hibernate.envers.test.integration.accesstype" />
|
||||
<package name="org.hibernate.envers.test.integration.auditReader" />
|
||||
<package name="org.hibernate.envers.test.integration.basic" />
|
||||
|
@ -71,6 +68,19 @@
|
|||
<package name="org.hibernate.envers.test.integration.secondary.ids" />
|
||||
<package name="org.hibernate.envers.test.integration.serialization" />
|
||||
<package name="org.hibernate.envers.test.integration.superclass" />
|
||||
'>
|
||||
]>
|
||||
|
||||
<suite name="Envers">
|
||||
<test name="All">
|
||||
<packages>
|
||||
&packages;
|
||||
</packages>
|
||||
</test>
|
||||
<test name="ValidTimeAuditStrategy">
|
||||
<parameter name="auditStrategy" value="org.hibernate.envers.strategy.ValidTimeAuditStrategy" />
|
||||
<packages>
|
||||
&packages;
|
||||
</packages>
|
||||
</test>
|
||||
</suite>
|
||||
|
|
Loading…
Reference in New Issue