diff --git a/envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java b/envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java index 11b0e2615d..4c9c689bb5 100644 --- a/envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java +++ b/envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java @@ -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, diff --git a/envers/src/main/java/org/hibernate/envers/configuration/AuditEntitiesConfiguration.java b/envers/src/main/java/org/hibernate/envers/configuration/AuditEntitiesConfiguration.java index 1b5e0e992d..7835b570e5 100644 --- a/envers/src/main/java/org/hibernate/envers/configuration/AuditEntitiesConfiguration.java +++ b/envers/src/main/java/org/hibernate/envers/configuration/AuditEntitiesConfiguration.java @@ -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 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(); revisionNumberPath = originalIdPropName + "." + revisionFieldName + ".id"; @@ -133,4 +155,12 @@ public class AuditEntitiesConfiguration { return customHistoryTableName; } + + public String getAuditStrategyName() { + return auditStrategyName; + } + + public String getRevisionEndFieldName() { + return revisionEndFieldName; + } } diff --git a/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java b/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java index 60b66b8f5e..e9fd78d277 100644 --- a/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java +++ b/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java @@ -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"}) diff --git a/envers/src/main/java/org/hibernate/envers/query/impl/AbstractAuditQuery.java b/envers/src/main/java/org/hibernate/envers/query/impl/AbstractAuditQuery.java index 715f1ed80f..6cbb1098c6 100644 --- a/envers/src/main/java/org/hibernate/envers/query/impl/AbstractAuditQuery.java +++ b/envers/src/main/java/org/hibernate/envers/query/impl/AbstractAuditQuery.java @@ -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 queryParamValues = new HashMap(); - - qb.build(querySb, queryParamValues); - - Query query = versionsReader.getSession().createQuery(querySb.toString()); - for (Map.Entry paramValue : queryParamValues.entrySet()) { - query.setParameter(paramValue.getKey(), paramValue.getValue()); - } + Query query = qb.toQuery(versionsReader.getSession()); setQueryProperties(query); diff --git a/envers/src/main/java/org/hibernate/envers/strategy/AuditStrategy.java b/envers/src/main/java/org/hibernate/envers/strategy/AuditStrategy.java new file mode 100755 index 0000000000..88f71e682e --- /dev/null +++ b/envers/src/main/java/org/hibernate/envers/strategy/AuditStrategy.java @@ -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); +} diff --git a/envers/src/main/java/org/hibernate/envers/strategy/DefaultAuditStrategy.java b/envers/src/main/java/org/hibernate/envers/strategy/DefaultAuditStrategy.java new file mode 100755 index 0000000000..4f66211e96 --- /dev/null +++ b/envers/src/main/java/org/hibernate/envers/strategy/DefaultAuditStrategy.java @@ -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()); + } +} diff --git a/envers/src/main/java/org/hibernate/envers/strategy/ValidTimeAuditStrategy.java b/envers/src/main/java/org/hibernate/envers/strategy/ValidTimeAuditStrategy.java new file mode 100755 index 0000000000..c6c3950197 --- /dev/null +++ b/envers/src/main/java/org/hibernate/envers/strategy/ValidTimeAuditStrategy.java @@ -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 originalId = (Map) persistentCollectionChangeData.getData().get( + originalIdPropName); + for (Map.Entry 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) 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) 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); + } + } +} diff --git a/envers/src/main/java/org/hibernate/envers/synchronization/work/AbstractAuditWorkUnit.java b/envers/src/main/java/org/hibernate/envers/synchronization/work/AbstractAuditWorkUnit.java index baf5d62f4a..b319742196 100644 --- a/envers/src/main/java/org/hibernate/envers/synchronization/work/AbstractAuditWorkUnit.java +++ b/envers/src/main/java/org/hibernate/envers/synchronization/work/AbstractAuditWorkUnit.java @@ -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 data, Object revision, RevisionType revisionType) { @@ -67,7 +71,7 @@ public abstract class AbstractAuditWorkUnit implements AuditWorkUnit { public void perform(Session session, Object revisionData) { Map data = generateData(revisionData); - session.save(verCfg.getAuditEntCfg().getAuditEntityName(getEntityName()), data); + auditStrategy.perform(session, getEntityName(), verCfg, id, data, revisionData); setPerformed(data); } diff --git a/envers/src/main/java/org/hibernate/envers/synchronization/work/PersistentCollectionChangeWorkUnit.java b/envers/src/main/java/org/hibernate/envers/synchronization/work/PersistentCollectionChangeWorkUnit.java index 8da1abdf99..46a6ae533b 100644 --- a/envers/src/main/java/org/hibernate/envers/synchronization/work/PersistentCollectionChangeWorkUnit.java +++ b/envers/src/main/java/org/hibernate/envers/synchronization/work/PersistentCollectionChangeWorkUnit.java @@ -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) 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); diff --git a/envers/src/main/java/org/hibernate/envers/tools/query/QueryBuilder.java b/envers/src/main/java/org/hibernate/envers/tools/query/QueryBuilder.java index 6afdcf348c..3042ee94e7 100644 --- a/envers/src/main/java/org/hibernate/envers/tools/query/QueryBuilder.java +++ b/envers/src/main/java/org/hibernate/envers/tools/query/QueryBuilder.java @@ -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 queryParamValues = new HashMap(); + + build(querySb, queryParamValues); + + Query query = session.createQuery(querySb.toString()); + for (Map.Entry paramValue : queryParamValues.entrySet()) { + query.setParameter(paramValue.getKey(), paramValue.getValue()); + } + + return query; + } } diff --git a/envers/src/test/java/org/hibernate/envers/test/AbstractEntityTest.java b/envers/src/test/java/org/hibernate/envers/test/AbstractEntityTest.java index 79bea7a900..fe93c59fd4 100644 --- a/envers/src/test/java/org/hibernate/envers/test/AbstractEntityTest.java +++ b/envers/src/test/java/org/hibernate/envers/test/AbstractEntityTest.java @@ -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(); diff --git a/envers/src/test/java/org/hibernate/envers/test/entities/customtype/CompositeTestUserType.java b/envers/src/test/java/org/hibernate/envers/test/entities/customtype/CompositeTestUserType.java index 5642cf41ae..10e6c7f6d7 100644 --- a/envers/src/test/java/org/hibernate/envers/test/entities/customtype/CompositeTestUserType.java +++ b/envers/src/test/java/org/hibernate/envers/test/entities/customtype/CompositeTestUserType.java @@ -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; diff --git a/envers/src/test/java/org/hibernate/envers/test/integration/manytomany/sametable/BasicSametable.java b/envers/src/test/java/org/hibernate/envers/test/integration/manytomany/sametable/BasicSametable.java index b9c731cd8f..075d61ab6c 100644 --- a/envers/src/test/java/org/hibernate/envers/test/integration/manytomany/sametable/BasicSametable.java +++ b/envers/src/test/java/org/hibernate/envers/test/integration/manytomany/sametable/BasicSametable.java @@ -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(); diff --git a/envers/src/test/java/org/hibernate/envers/test/performance/AbstractPerformanceTest.java b/envers/src/test/java/org/hibernate/envers/test/performance/AbstractPerformanceTest.java index 8c493ccfc9..7d4a3f6a16 100644 --- a/envers/src/test/java/org/hibernate/envers/test/performance/AbstractPerformanceTest.java +++ b/envers/src/test/java/org/hibernate/envers/test/performance/AbstractPerformanceTest.java @@ -88,11 +88,11 @@ public abstract class AbstractPerformanceTest extends AbstractEntityTest { List unauditedRuns = new ArrayList(); List auditedRuns = new ArrayList(); - init(true); + init(true, null); long audited = run(numberOfRuns, auditedRuns); close(); - init(false); + init(false, null); long unaudited = run(numberOfRuns, unauditedRuns); close(); diff --git a/envers/src/test/resources/hibernate.test.cfg.xml b/envers/src/test/resources/hibernate.test.cfg.xml index 9ea50a9d33..423f61c0cd 100644 --- a/envers/src/test/resources/hibernate.test.cfg.xml +++ b/envers/src/test/resources/hibernate.test.cfg.xml @@ -23,6 +23,8 @@ + +