HHH-13051 Make audit tables structure more extensible

This commit is contained in:
Rokko11 2018-10-14 23:33:27 +02:00 committed by Guillaume Smet
parent 82d3793549
commit 68df2792c6
6 changed files with 95 additions and 48 deletions

View File

@ -28,11 +28,9 @@ import org.hibernate.envers.internal.revisioninfo.RevisionInfoQueryCreator;
import org.hibernate.envers.internal.synchronization.AuditProcessManager;
import org.hibernate.envers.internal.tools.ReflectionTools;
import org.hibernate.envers.strategy.AuditStrategy;
import org.hibernate.envers.strategy.ValidityAuditStrategy;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.internal.util.xml.XMLHelper;
import org.hibernate.property.access.spi.Getter;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.spi.Configurable;
import org.hibernate.service.spi.Stoppable;
@ -182,15 +180,8 @@ public class EnversServiceImpl implements EnversService, Configurable, Stoppable
);
}
if ( strategy instanceof ValidityAuditStrategy ) {
// further initialization required
final Getter revisionTimestampGetter = ReflectionTools.getGetter(
revisionInfoClass,
revisionInfoTimestampData,
serviceRegistry
);
( (ValidityAuditStrategy) strategy ).setRevisionTimestampGetter( revisionTimestampGetter );
}
// Strategy-specific initialization
strategy.initialize( revisionInfoClass, revisionInfoTimestampData, serviceRegistry );
return strategy;
}

View File

@ -28,7 +28,6 @@ import org.hibernate.envers.internal.entities.mapper.SubclassPropertyMapper;
import org.hibernate.envers.internal.tools.StringTools;
import org.hibernate.envers.internal.tools.Triple;
import org.hibernate.envers.strategy.AuditStrategy;
import org.hibernate.envers.strategy.ValidityAuditStrategy;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Join;
import org.hibernate.mapping.OneToOne;
@ -172,44 +171,10 @@ public final class AuditMetadataGenerator {
isKey
);
revTypeProperty.addAttribute( "type", "org.hibernate.envers.internal.entities.RevisionTypeType" );
// Adding the end revision, if appropriate
addEndRevision( anyMappingEnd );
}
private void addEndRevision(Element anyMapping) {
// Add the end-revision field, if the appropriate strategy is used.
if ( auditStrategy instanceof ValidityAuditStrategy ) {
final Element endRevMapping = (Element) revisionInfoRelationMapping.clone();
endRevMapping.setName( "many-to-one" );
endRevMapping.addAttribute( "name", verEntCfg.getRevisionEndFieldName() );
MetadataTools.addOrModifyColumn( endRevMapping, verEntCfg.getRevisionEndFieldName() );
anyMapping.add( endRevMapping );
if ( verEntCfg.isRevisionEndTimestampEnabled() ) {
// add a column for the timestamp of the end revision
final String revisionInfoTimestampSqlType = TimestampType.INSTANCE.getName();
final Element timestampProperty = MetadataTools.addProperty(
anyMapping,
verEntCfg.getRevisionEndTimestampFieldName(),
revisionInfoTimestampSqlType,
true,
true,
false
);
MetadataTools.addColumn(
timestampProperty,
verEntCfg.getRevisionEndTimestampFieldName(),
null,
null,
null,
null,
null,
null
);
}
}
void addAdditionalColumns(Element anyMapping) {
auditStrategy.addAdditionalColumns(anyMapping, revisionInfoRelationMapping, verEntCfg);
}
private void addValueInFirstPass(
@ -553,6 +518,8 @@ public final class AuditMetadataGenerator {
// Adding the "revision type" property
addRevisionType( classMapping, classMapping );
addAdditionalColumns( classMapping );
return Triple.make( classMapping, propertyMapper, null );
}

View File

@ -879,6 +879,8 @@ public final class CollectionMetadataGenerator {
isRevisionTypeInId()
);
mainGenerator.addAdditionalColumns( middleEntityXml );
// All other properties should also be part of the primary key of the middle entity.
return middleEntityXmlId;
}

View File

@ -9,14 +9,17 @@ package org.hibernate.envers.strategy;
import java.io.Serializable;
import org.hibernate.Session;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.envers.boot.internal.EnversService;
import org.hibernate.envers.configuration.internal.AuditEntitiesConfiguration;
import org.hibernate.envers.configuration.internal.GlobalConfiguration;
import org.hibernate.envers.internal.entities.PropertyData;
import org.hibernate.envers.internal.entities.mapper.PersistentCollectionChangeData;
import org.hibernate.envers.internal.entities.mapper.relation.MiddleComponentData;
import org.hibernate.envers.internal.entities.mapper.relation.MiddleIdData;
import org.hibernate.envers.internal.tools.query.Parameters;
import org.hibernate.envers.internal.tools.query.QueryBuilder;
import org.dom4j.Element;
/**
* Behaviours of different audit strategy for populating audit data.
@ -199,4 +202,32 @@ public interface AuditStrategy {
String alias1,
boolean inclusive,
MiddleComponentData... componentDatas);
/**
* Method to add additional Columns to the aud-tables.
*
* @param anyMapping the class mapping
* @param revMapping the mapping of the revInfo-relation
* @param auditEntitiesConfiguration the configuration of the audit entities
*/
default void addAdditionalColumns(
Element anyMapping,
Element revMapping,
AuditEntitiesConfiguration auditEntitiesConfiguration) {
//For backward compatibility
}
/**
* Method do add additional initialization behavior
*
* @param revisionInfoClass the class of the revision info
* @param revisionInfoTimestampData the timestamp of the revision info
* @param serviceRegistry the service registry
*/
default void initialize(
Class<?> revisionInfoClass,
PropertyData revisionInfoTimestampData,
ServiceRegistry serviceRegistry) {
//For backward compatibility
}
}

View File

@ -9,14 +9,17 @@ package org.hibernate.envers.strategy;
import java.io.Serializable;
import org.hibernate.Session;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.envers.configuration.internal.AuditEntitiesConfiguration;
import org.hibernate.envers.configuration.internal.GlobalConfiguration;
import org.hibernate.envers.internal.entities.PropertyData;
import org.hibernate.envers.internal.entities.mapper.PersistentCollectionChangeData;
import org.hibernate.envers.internal.entities.mapper.relation.MiddleComponentData;
import org.hibernate.envers.internal.entities.mapper.relation.MiddleIdData;
import org.hibernate.envers.internal.synchronization.SessionCacheCleaner;
import org.hibernate.envers.internal.tools.query.Parameters;
import org.hibernate.envers.internal.tools.query.QueryBuilder;
import org.dom4j.Element;
import static org.hibernate.envers.internal.entities.mapper.relation.query.QueryConstants.MIDDLE_ENTITY_ALIAS_DEF_AUD_STR;
import static org.hibernate.envers.internal.entities.mapper.relation.query.QueryConstants.REVISION_PARAMETER;

View File

@ -13,6 +13,7 @@ import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.dom4j.Element;
import org.hibernate.LockOptions;
import org.hibernate.Session;
@ -22,10 +23,13 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.envers.RevisionType;
import org.hibernate.envers.configuration.internal.AuditEntitiesConfiguration;
import org.hibernate.envers.configuration.internal.GlobalConfiguration;
import org.hibernate.envers.configuration.internal.metadata.MetadataTools;
import org.hibernate.envers.internal.entities.PropertyData;
import org.hibernate.envers.internal.entities.mapper.PersistentCollectionChangeData;
import org.hibernate.envers.internal.entities.mapper.relation.MiddleComponentData;
import org.hibernate.envers.internal.entities.mapper.relation.MiddleIdData;
import org.hibernate.envers.internal.synchronization.SessionCacheCleaner;
import org.hibernate.envers.internal.tools.ReflectionTools;
import org.hibernate.envers.internal.tools.query.Parameters;
import org.hibernate.envers.internal.tools.query.QueryBuilder;
import org.hibernate.event.spi.EventSource;
@ -40,6 +44,8 @@ import org.hibernate.type.MapType;
import org.hibernate.type.MaterializedClobType;
import org.hibernate.type.MaterializedNClobType;
import org.hibernate.type.Type;
import org.hibernate.type.TimestampType;
import org.hibernate.service.ServiceRegistry;
import static org.hibernate.envers.internal.entities.mapper.relation.query.QueryConstants.MIDDLE_ENTITY_ALIAS;
import static org.hibernate.envers.internal.entities.mapper.relation.query.QueryConstants.REVISION_PARAMETER;
@ -395,6 +401,53 @@ public class ValidityAuditStrategy implements AuditStrategy {
}
}
@Override
public void addAdditionalColumns(Element anyMapping, Element revMapping, AuditEntitiesConfiguration auditEntitiesConfiguration) {
// Add the end-revision field, if the appropriate strategy is used.
Element endRevMapping = (Element) revMapping.clone();
endRevMapping.setName( "many-to-one" );
endRevMapping.addAttribute( "name", auditEntitiesConfiguration.getRevisionEndFieldName() );
MetadataTools.addOrModifyColumn( endRevMapping, auditEntitiesConfiguration.getRevisionEndFieldName() );
anyMapping.add( endRevMapping );
if ( auditEntitiesConfiguration.isRevisionEndTimestampEnabled() ) {
// add a column for the timestamp of the end revision
final String revisionInfoTimestampSqlType = TimestampType.INSTANCE.getName();
final Element timestampProperty = MetadataTools.addProperty(
anyMapping,
auditEntitiesConfiguration.getRevisionEndTimestampFieldName(),
revisionInfoTimestampSqlType,
true,
true,
false
);
MetadataTools.addColumn(
timestampProperty,
auditEntitiesConfiguration.getRevisionEndTimestampFieldName(),
null,
null,
null,
null,
null,
null
);
}
}
@Override
public void initialize(Class<?> revisionInfoClass, PropertyData revisionInfoTimestampData, ServiceRegistry serviceRegistry) {
// further initialization required
final Getter revisionTimestampGetter = ReflectionTools.getGetter(
revisionInfoClass,
revisionInfoTimestampData,
serviceRegistry
);
setRevisionTimestampGetter( revisionTimestampGetter );
}
private Date convertRevEndTimestampToDate(Object revEndTimestampObj) {
// convert to a java.util.Date
if ( revEndTimestampObj instanceof Date ) {