HHH-5372:
applying patch by Matthew B. Jones and Erik-Berndt Scheper Using the revend column in queries that retrieve historical data, which is much faster then doing the subselect. git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@20315 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
28dae5c9f3
commit
9c919ee9dc
|
@ -83,7 +83,7 @@ public class AuditConfiguration {
|
||||||
public AuditConfiguration(Configuration cfg) {
|
public AuditConfiguration(Configuration cfg) {
|
||||||
Properties properties = cfg.getProperties();
|
Properties properties = cfg.getProperties();
|
||||||
|
|
||||||
ReflectionManager reflectionManager = ((AnnotationConfiguration) cfg).getReflectionManager();
|
ReflectionManager reflectionManager = cfg.getReflectionManager();
|
||||||
RevisionInfoConfiguration revInfoCfg = new RevisionInfoConfiguration();
|
RevisionInfoConfiguration revInfoCfg = new RevisionInfoConfiguration();
|
||||||
RevisionInfoConfigurationResult revInfoCfgResult = revInfoCfg.configure(cfg, reflectionManager);
|
RevisionInfoConfigurationResult revInfoCfgResult = revInfoCfg.configure(cfg, reflectionManager);
|
||||||
auditEntCfg = new AuditEntitiesConfiguration(properties, revInfoCfgResult.getRevisionInfoEntityName());
|
auditEntCfg = new AuditEntitiesConfiguration(properties, revInfoCfgResult.getRevisionInfoEntityName());
|
||||||
|
@ -99,7 +99,7 @@ public class AuditConfiguration {
|
||||||
|
|
||||||
revisionInfoQueryCreator = revInfoCfgResult.getRevisionInfoQueryCreator();
|
revisionInfoQueryCreator = revInfoCfgResult.getRevisionInfoQueryCreator();
|
||||||
revisionInfoNumberReader = revInfoCfgResult.getRevisionInfoNumberReader();
|
revisionInfoNumberReader = revInfoCfgResult.getRevisionInfoNumberReader();
|
||||||
entCfg = new EntitiesConfigurator().configure(cfg, reflectionManager, globalCfg, auditEntCfg,
|
entCfg = new EntitiesConfigurator().configure(cfg, reflectionManager, globalCfg, auditEntCfg, auditStrategy,
|
||||||
revInfoCfgResult.getRevisionInfoXmlMapping(), revInfoCfgResult.getRevisionInfoRelationMapping());
|
revInfoCfgResult.getRevisionInfoXmlMapping(), revInfoCfgResult.getRevisionInfoRelationMapping());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ import org.hibernate.envers.configuration.metadata.reader.ClassAuditingData;
|
||||||
import org.hibernate.envers.configuration.metadata.AuditMetadataGenerator;
|
import org.hibernate.envers.configuration.metadata.AuditMetadataGenerator;
|
||||||
import org.hibernate.envers.configuration.metadata.AuditEntityNameRegister;
|
import org.hibernate.envers.configuration.metadata.AuditEntityNameRegister;
|
||||||
import org.hibernate.envers.entities.EntitiesConfigurations;
|
import org.hibernate.envers.entities.EntitiesConfigurations;
|
||||||
|
import org.hibernate.envers.strategy.AuditStrategy;
|
||||||
import org.hibernate.envers.tools.StringTools;
|
import org.hibernate.envers.tools.StringTools;
|
||||||
import org.hibernate.envers.tools.graph.GraphTopologicalSort;
|
import org.hibernate.envers.tools.graph.GraphTopologicalSort;
|
||||||
|
|
||||||
|
@ -57,6 +58,7 @@ import org.hibernate.mapping.PersistentClass;
|
||||||
public class EntitiesConfigurator {
|
public class EntitiesConfigurator {
|
||||||
public EntitiesConfigurations configure(Configuration cfg, ReflectionManager reflectionManager,
|
public EntitiesConfigurations configure(Configuration cfg, ReflectionManager reflectionManager,
|
||||||
GlobalConfiguration globalCfg, AuditEntitiesConfiguration verEntCfg,
|
GlobalConfiguration globalCfg, AuditEntitiesConfiguration verEntCfg,
|
||||||
|
AuditStrategy auditStrategy,
|
||||||
Document revisionInfoXmlMapping, Element revisionInfoRelationMapping) {
|
Document revisionInfoXmlMapping, Element revisionInfoRelationMapping) {
|
||||||
// Creating a name register to capture all audit entity names created.
|
// Creating a name register to capture all audit entity names created.
|
||||||
AuditEntityNameRegister auditEntityNameRegister = new AuditEntityNameRegister();
|
AuditEntityNameRegister auditEntityNameRegister = new AuditEntityNameRegister();
|
||||||
|
@ -83,7 +85,7 @@ public class EntitiesConfigurator {
|
||||||
// Now that all information is read we can update the calculated fields.
|
// Now that all information is read we can update the calculated fields.
|
||||||
classesAuditingData.updateCalculatedFields();
|
classesAuditingData.updateCalculatedFields();
|
||||||
|
|
||||||
AuditMetadataGenerator auditMetaGen = new AuditMetadataGenerator(cfg, globalCfg, verEntCfg,
|
AuditMetadataGenerator auditMetaGen = new AuditMetadataGenerator(cfg, globalCfg, verEntCfg, auditStrategy,
|
||||||
revisionInfoRelationMapping, auditEntityNameRegister);
|
revisionInfoRelationMapping, auditEntityNameRegister);
|
||||||
|
|
||||||
// First pass
|
// First pass
|
||||||
|
|
|
@ -28,6 +28,7 @@ import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.dom4j.Element;
|
import org.dom4j.Element;
|
||||||
|
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||||
import org.hibernate.envers.configuration.GlobalConfiguration;
|
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||||
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
||||||
import org.hibernate.envers.configuration.metadata.reader.ClassAuditingData;
|
import org.hibernate.envers.configuration.metadata.reader.ClassAuditingData;
|
||||||
|
@ -38,6 +39,7 @@ import org.hibernate.envers.entities.mapper.CompositeMapperBuilder;
|
||||||
import org.hibernate.envers.entities.mapper.ExtendedPropertyMapper;
|
import org.hibernate.envers.entities.mapper.ExtendedPropertyMapper;
|
||||||
import org.hibernate.envers.entities.mapper.MultiPropertyMapper;
|
import org.hibernate.envers.entities.mapper.MultiPropertyMapper;
|
||||||
import org.hibernate.envers.entities.mapper.SubclassPropertyMapper;
|
import org.hibernate.envers.entities.mapper.SubclassPropertyMapper;
|
||||||
|
import org.hibernate.envers.strategy.AuditStrategy;
|
||||||
import org.hibernate.envers.strategy.ValidTimeAuditStrategy;
|
import org.hibernate.envers.strategy.ValidTimeAuditStrategy;
|
||||||
import org.hibernate.envers.tools.StringTools;
|
import org.hibernate.envers.tools.StringTools;
|
||||||
import org.hibernate.envers.tools.Triple;
|
import org.hibernate.envers.tools.Triple;
|
||||||
|
@ -63,6 +65,7 @@ public final class AuditMetadataGenerator {
|
||||||
private final Configuration cfg;
|
private final Configuration cfg;
|
||||||
private final GlobalConfiguration globalCfg;
|
private final GlobalConfiguration globalCfg;
|
||||||
private final AuditEntitiesConfiguration verEntCfg;
|
private final AuditEntitiesConfiguration verEntCfg;
|
||||||
|
private final AuditStrategy auditStrategy;
|
||||||
private final Element revisionInfoRelationMapping;
|
private final Element revisionInfoRelationMapping;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -86,11 +89,13 @@ public final class AuditMetadataGenerator {
|
||||||
|
|
||||||
public AuditMetadataGenerator(Configuration cfg, GlobalConfiguration globalCfg,
|
public AuditMetadataGenerator(Configuration cfg, GlobalConfiguration globalCfg,
|
||||||
AuditEntitiesConfiguration verEntCfg,
|
AuditEntitiesConfiguration verEntCfg,
|
||||||
|
AuditStrategy auditStrategy,
|
||||||
Element revisionInfoRelationMapping,
|
Element revisionInfoRelationMapping,
|
||||||
AuditEntityNameRegister auditEntityNameRegister) {
|
AuditEntityNameRegister auditEntityNameRegister) {
|
||||||
this.cfg = cfg;
|
this.cfg = cfg;
|
||||||
this.globalCfg = globalCfg;
|
this.globalCfg = globalCfg;
|
||||||
this.verEntCfg = verEntCfg;
|
this.verEntCfg = verEntCfg;
|
||||||
|
this.auditStrategy = auditStrategy;
|
||||||
this.revisionInfoRelationMapping = revisionInfoRelationMapping;
|
this.revisionInfoRelationMapping = revisionInfoRelationMapping;
|
||||||
|
|
||||||
this.basicMetadataGenerator = new BasicMetadataGenerator();
|
this.basicMetadataGenerator = new BasicMetadataGenerator();
|
||||||
|
@ -490,6 +495,10 @@ public final class AuditMetadataGenerator {
|
||||||
return verEntCfg;
|
return verEntCfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AuditStrategy getAuditStrategy() {
|
||||||
|
return auditStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
AuditEntityNameRegister getAuditEntityNameRegister() {
|
AuditEntityNameRegister getAuditEntityNameRegister() {
|
||||||
return auditEntityNameRegister;
|
return auditEntityNameRegister;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,11 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import javax.persistence.JoinColumn;
|
import javax.persistence.JoinColumn;
|
||||||
|
|
||||||
import org.dom4j.Element;
|
import org.dom4j.Element;
|
||||||
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.envers.ModificationStore;
|
import org.hibernate.envers.ModificationStore;
|
||||||
import org.hibernate.envers.RelationTargetAuditMode;
|
import org.hibernate.envers.RelationTargetAuditMode;
|
||||||
import org.hibernate.envers.configuration.metadata.reader.PropertyAuditingData;
|
import org.hibernate.envers.configuration.metadata.reader.PropertyAuditingData;
|
||||||
|
@ -45,8 +47,19 @@ import org.hibernate.envers.entities.mapper.CompositeMapperBuilder;
|
||||||
import org.hibernate.envers.entities.mapper.PropertyMapper;
|
import org.hibernate.envers.entities.mapper.PropertyMapper;
|
||||||
import org.hibernate.envers.entities.mapper.SinglePropertyMapper;
|
import org.hibernate.envers.entities.mapper.SinglePropertyMapper;
|
||||||
import org.hibernate.envers.entities.mapper.id.IdMapper;
|
import org.hibernate.envers.entities.mapper.id.IdMapper;
|
||||||
import org.hibernate.envers.entities.mapper.relation.*;
|
import org.hibernate.envers.entities.mapper.relation.BasicCollectionMapper;
|
||||||
import org.hibernate.envers.entities.mapper.relation.component.*;
|
import org.hibernate.envers.entities.mapper.relation.CommonCollectionMapperData;
|
||||||
|
import org.hibernate.envers.entities.mapper.relation.ListCollectionMapper;
|
||||||
|
import org.hibernate.envers.entities.mapper.relation.MapCollectionMapper;
|
||||||
|
import org.hibernate.envers.entities.mapper.relation.MiddleComponentData;
|
||||||
|
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
|
||||||
|
import org.hibernate.envers.entities.mapper.relation.ToOneIdMapper;
|
||||||
|
import org.hibernate.envers.entities.mapper.relation.component.MiddleDummyComponentMapper;
|
||||||
|
import org.hibernate.envers.entities.mapper.relation.component.MiddleMapKeyIdComponentMapper;
|
||||||
|
import org.hibernate.envers.entities.mapper.relation.component.MiddleMapKeyPropertyComponentMapper;
|
||||||
|
import org.hibernate.envers.entities.mapper.relation.component.MiddleRelatedComponentMapper;
|
||||||
|
import org.hibernate.envers.entities.mapper.relation.component.MiddleSimpleComponentMapper;
|
||||||
|
import org.hibernate.envers.entities.mapper.relation.component.MiddleStraightComponentMapper;
|
||||||
import org.hibernate.envers.entities.mapper.relation.lazy.proxy.ListProxy;
|
import org.hibernate.envers.entities.mapper.relation.lazy.proxy.ListProxy;
|
||||||
import org.hibernate.envers.entities.mapper.relation.lazy.proxy.MapProxy;
|
import org.hibernate.envers.entities.mapper.relation.lazy.proxy.MapProxy;
|
||||||
import org.hibernate.envers.entities.mapper.relation.lazy.proxy.SetProxy;
|
import org.hibernate.envers.entities.mapper.relation.lazy.proxy.SetProxy;
|
||||||
|
@ -54,11 +67,9 @@ import org.hibernate.envers.entities.mapper.relation.lazy.proxy.SortedMapProxy;
|
||||||
import org.hibernate.envers.entities.mapper.relation.lazy.proxy.SortedSetProxy;
|
import org.hibernate.envers.entities.mapper.relation.lazy.proxy.SortedSetProxy;
|
||||||
import org.hibernate.envers.entities.mapper.relation.query.OneAuditEntityQueryGenerator;
|
import org.hibernate.envers.entities.mapper.relation.query.OneAuditEntityQueryGenerator;
|
||||||
import org.hibernate.envers.entities.mapper.relation.query.RelationQueryGenerator;
|
import org.hibernate.envers.entities.mapper.relation.query.RelationQueryGenerator;
|
||||||
|
import org.hibernate.envers.tools.MappingTools;
|
||||||
import org.hibernate.envers.tools.StringTools;
|
import org.hibernate.envers.tools.StringTools;
|
||||||
import org.hibernate.envers.tools.Tools;
|
import org.hibernate.envers.tools.Tools;
|
||||||
import org.hibernate.envers.tools.MappingTools;
|
|
||||||
|
|
||||||
import org.hibernate.MappingException;
|
|
||||||
import org.hibernate.mapping.Collection;
|
import org.hibernate.mapping.Collection;
|
||||||
import org.hibernate.mapping.IndexedCollection;
|
import org.hibernate.mapping.IndexedCollection;
|
||||||
import org.hibernate.mapping.OneToMany;
|
import org.hibernate.mapping.OneToMany;
|
||||||
|
@ -184,8 +195,8 @@ public final class CollectionMetadataGenerator {
|
||||||
|
|
||||||
// Generating the query generator - it should read directly from the related entity.
|
// Generating the query generator - it should read directly from the related entity.
|
||||||
RelationQueryGenerator queryGenerator = new OneAuditEntityQueryGenerator(mainGenerator.getGlobalCfg(),
|
RelationQueryGenerator queryGenerator = new OneAuditEntityQueryGenerator(mainGenerator.getGlobalCfg(),
|
||||||
mainGenerator.getVerEntCfg(), referencingIdData, referencedEntityName,
|
mainGenerator.getVerEntCfg(), mainGenerator.getAuditStrategy(),
|
||||||
referencedIdMapping.getIdMapper());
|
referencingIdData, referencedEntityName, referencedIdData);
|
||||||
|
|
||||||
// Creating common mapper data.
|
// Creating common mapper data.
|
||||||
CommonCollectionMapperData commonCollectionMapperData = new CommonCollectionMapperData(
|
CommonCollectionMapperData commonCollectionMapperData = new CommonCollectionMapperData(
|
||||||
|
@ -332,8 +343,9 @@ public final class CollectionMetadataGenerator {
|
||||||
// Creating a query generator builder, to which additional id data will be added, in case this collection
|
// Creating a query generator builder, to which additional id data will be added, in case this collection
|
||||||
// references some entities (either from the element or index). At the end, this will be used to build
|
// references some entities (either from the element or index). At the end, this will be used to build
|
||||||
// a query generator to read the raw data collection from the middle table.
|
// a query generator to read the raw data collection from the middle table.
|
||||||
QueryGeneratorBuilder queryGeneratorBuilder = new QueryGeneratorBuilder(mainGenerator.getGlobalCfg(),
|
QueryGeneratorBuilder queryGeneratorBuilder = new QueryGeneratorBuilder(mainGenerator.getGlobalCfg(),
|
||||||
mainGenerator.getVerEntCfg(), referencingIdData, auditMiddleEntityName);
|
mainGenerator.getVerEntCfg(), mainGenerator.getAuditStrategy(), referencingIdData,
|
||||||
|
auditMiddleEntityName);
|
||||||
|
|
||||||
// Adding the XML mapping for the referencing entity, if the relation isn't inverse.
|
// Adding the XML mapping for the referencing entity, if the relation isn't inverse.
|
||||||
if (middleEntityXml != null) {
|
if (middleEntityXml != null) {
|
||||||
|
|
|
@ -26,12 +26,17 @@ package org.hibernate.envers.configuration.metadata;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.envers.configuration.GlobalConfiguration;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
||||||
|
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||||
import org.hibernate.envers.entities.mapper.relation.MiddleComponentData;
|
import org.hibernate.envers.entities.mapper.relation.MiddleComponentData;
|
||||||
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
|
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
|
||||||
import org.hibernate.envers.entities.mapper.relation.query.*;
|
import org.hibernate.envers.entities.mapper.relation.query.OneEntityQueryGenerator;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.envers.entities.mapper.relation.query.RelationQueryGenerator;
|
||||||
|
import org.hibernate.envers.entities.mapper.relation.query.ThreeEntityQueryGenerator;
|
||||||
|
import org.hibernate.envers.entities.mapper.relation.query.TwoEntityOneAuditedQueryGenerator;
|
||||||
|
import org.hibernate.envers.entities.mapper.relation.query.TwoEntityQueryGenerator;
|
||||||
|
import org.hibernate.envers.strategy.AuditStrategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds query generators, for reading collection middle tables, along with any related entities.
|
* Builds query generators, for reading collection middle tables, along with any related entities.
|
||||||
|
@ -41,14 +46,17 @@ import org.hibernate.MappingException;
|
||||||
public final class QueryGeneratorBuilder {
|
public final class QueryGeneratorBuilder {
|
||||||
private final GlobalConfiguration globalCfg;
|
private final GlobalConfiguration globalCfg;
|
||||||
private final AuditEntitiesConfiguration verEntCfg;
|
private final AuditEntitiesConfiguration verEntCfg;
|
||||||
|
private final AuditStrategy auditStrategy;
|
||||||
private final MiddleIdData referencingIdData;
|
private final MiddleIdData referencingIdData;
|
||||||
private final String auditMiddleEntityName;
|
private final String auditMiddleEntityName;
|
||||||
private final List<MiddleIdData> idDatas;
|
private final List<MiddleIdData> idDatas;
|
||||||
|
|
||||||
QueryGeneratorBuilder(GlobalConfiguration globalCfg, AuditEntitiesConfiguration verEntCfg,
|
QueryGeneratorBuilder(GlobalConfiguration globalCfg, AuditEntitiesConfiguration verEntCfg,
|
||||||
|
AuditStrategy auditStrategy,
|
||||||
MiddleIdData referencingIdData, String auditMiddleEntityName) {
|
MiddleIdData referencingIdData, String auditMiddleEntityName) {
|
||||||
this.globalCfg = globalCfg;
|
this.globalCfg = globalCfg;
|
||||||
this.verEntCfg = verEntCfg;
|
this.verEntCfg = verEntCfg;
|
||||||
|
this.auditStrategy = auditStrategy;
|
||||||
this.referencingIdData = referencingIdData;
|
this.referencingIdData = referencingIdData;
|
||||||
this.auditMiddleEntityName = auditMiddleEntityName;
|
this.auditMiddleEntityName = auditMiddleEntityName;
|
||||||
|
|
||||||
|
@ -61,14 +69,14 @@ public final class QueryGeneratorBuilder {
|
||||||
|
|
||||||
RelationQueryGenerator build(MiddleComponentData... componentDatas) {
|
RelationQueryGenerator build(MiddleComponentData... componentDatas) {
|
||||||
if (idDatas.size() == 0) {
|
if (idDatas.size() == 0) {
|
||||||
return new OneEntityQueryGenerator(verEntCfg, auditMiddleEntityName, referencingIdData,
|
return new OneEntityQueryGenerator(verEntCfg, auditStrategy, auditMiddleEntityName, referencingIdData,
|
||||||
componentDatas);
|
componentDatas);
|
||||||
} else if (idDatas.size() == 1) {
|
} else if (idDatas.size() == 1) {
|
||||||
if (idDatas.get(0).isAudited()) {
|
if (idDatas.get(0).isAudited()) {
|
||||||
return new TwoEntityQueryGenerator(globalCfg, verEntCfg, auditMiddleEntityName, referencingIdData,
|
return new TwoEntityQueryGenerator(globalCfg, verEntCfg, auditStrategy, auditMiddleEntityName, referencingIdData,
|
||||||
idDatas.get(0), componentDatas);
|
idDatas.get(0), componentDatas);
|
||||||
} else {
|
} else {
|
||||||
return new TwoEntityOneAuditedQueryGenerator(verEntCfg, auditMiddleEntityName, referencingIdData,
|
return new TwoEntityOneAuditedQueryGenerator(verEntCfg, auditStrategy, auditMiddleEntityName, referencingIdData,
|
||||||
idDatas.get(0), componentDatas);
|
idDatas.get(0), componentDatas);
|
||||||
}
|
}
|
||||||
} else if (idDatas.size() == 2) {
|
} else if (idDatas.size() == 2) {
|
||||||
|
@ -77,7 +85,7 @@ public final class QueryGeneratorBuilder {
|
||||||
throw new MappingException("Ternary relations using @Audited(targetAuditMode = NOT_AUDITED) are not supported.");
|
throw new MappingException("Ternary relations using @Audited(targetAuditMode = NOT_AUDITED) are not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ThreeEntityQueryGenerator(globalCfg, verEntCfg, auditMiddleEntityName, referencingIdData,
|
return new ThreeEntityQueryGenerator(globalCfg, verEntCfg, auditStrategy, auditMiddleEntityName, referencingIdData,
|
||||||
idDatas.get(0), idDatas.get(1), componentDatas);
|
idDatas.get(0), idDatas.get(1), componentDatas);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("Illegal number of related entities.");
|
throw new IllegalStateException("Illegal number of related entities.");
|
||||||
|
|
|
@ -25,18 +25,17 @@ package org.hibernate.envers.entities.mapper.relation.query;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import org.hibernate.Query;
|
||||||
import org.hibernate.envers.RevisionType;
|
import org.hibernate.envers.RevisionType;
|
||||||
import org.hibernate.envers.configuration.GlobalConfiguration;
|
|
||||||
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
||||||
import org.hibernate.envers.entities.mapper.id.IdMapper;
|
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||||
import org.hibernate.envers.entities.mapper.id.QueryParameterData;
|
import org.hibernate.envers.entities.mapper.id.QueryParameterData;
|
||||||
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
|
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
|
||||||
import org.hibernate.envers.reader.AuditReaderImplementor;
|
import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||||
|
import org.hibernate.envers.strategy.AuditStrategy;
|
||||||
import org.hibernate.envers.tools.query.Parameters;
|
import org.hibernate.envers.tools.query.Parameters;
|
||||||
import org.hibernate.envers.tools.query.QueryBuilder;
|
import org.hibernate.envers.tools.query.QueryBuilder;
|
||||||
|
|
||||||
import org.hibernate.Query;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects data from an audit entity.
|
* Selects data from an audit entity.
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
@ -45,9 +44,10 @@ public final class OneAuditEntityQueryGenerator implements RelationQueryGenerato
|
||||||
private final String queryString;
|
private final String queryString;
|
||||||
private final MiddleIdData referencingIdData;
|
private final MiddleIdData referencingIdData;
|
||||||
|
|
||||||
public OneAuditEntityQueryGenerator(GlobalConfiguration globalCfg, AuditEntitiesConfiguration verEntCfg,
|
public OneAuditEntityQueryGenerator(GlobalConfiguration globalCfg, AuditEntitiesConfiguration verEntCfg,
|
||||||
MiddleIdData referencingIdData, String referencedEntityName,
|
AuditStrategy auditStrategy,
|
||||||
IdMapper referencedIdMapper) {
|
MiddleIdData referencingIdData,
|
||||||
|
String referencedEntityName, MiddleIdData referencedIdData) {
|
||||||
this.referencingIdData = referencingIdData;
|
this.referencingIdData = referencingIdData;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -57,8 +57,14 @@ public final class OneAuditEntityQueryGenerator implements RelationQueryGenerato
|
||||||
* (only entities referenced by the association; id_ref_ing = id of the referencing entity)
|
* (only entities referenced by the association; id_ref_ing = id of the referencing entity)
|
||||||
* e.id_ref_ing = :id_ref_ing AND
|
* e.id_ref_ing = :id_ref_ing AND
|
||||||
* (selecting e entities at revision :revision)
|
* (selecting e entities at revision :revision)
|
||||||
|
* --> for DefaultAuditStrategy:
|
||||||
* e.revision = (SELECT max(e2.revision) FROM versionsReferencedEntity e2
|
* e.revision = (SELECT max(e2.revision) FROM versionsReferencedEntity e2
|
||||||
* WHERE e2.revision <= :revision AND e2.id = e.id) AND
|
* WHERE e2.revision <= :revision AND e2.id = e.id)
|
||||||
|
*
|
||||||
|
* --> for ValidTimeAuditStrategy:
|
||||||
|
* e.revision <= :revision and (e.endRevision > :revision or e.endRevision is null)
|
||||||
|
*
|
||||||
|
* AND
|
||||||
* (only non-deleted entities)
|
* (only non-deleted entities)
|
||||||
* e.revision_type != DEL
|
* e.revision_type != DEL
|
||||||
*/
|
*/
|
||||||
|
@ -75,19 +81,11 @@ public final class OneAuditEntityQueryGenerator implements RelationQueryGenerato
|
||||||
// e.id_ref_ed = :id_ref_ed
|
// e.id_ref_ed = :id_ref_ed
|
||||||
referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, null, true);
|
referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, null, true);
|
||||||
|
|
||||||
// SELECT max(e.revision) FROM versionsReferencedEntity e2
|
// (selecting e entities at revision :revision)
|
||||||
QueryBuilder maxERevQb = qb.newSubQueryBuilder(versionsReferencedEntityName, "e2");
|
// --> based on auditStrategy (see above)
|
||||||
maxERevQb.addProjection("max", revisionPropertyPath, false);
|
auditStrategy.addEntityAtRevisionRestriction(globalCfg, qb, revisionPropertyPath,
|
||||||
// WHERE
|
verEntCfg.getRevisionEndFieldName(), true, referencedIdData,
|
||||||
Parameters maxERevQbParameters = maxERevQb.getRootParameters();
|
revisionPropertyPath, originalIdPropertyName, "e", "e2");
|
||||||
// e2.revision <= :revision
|
|
||||||
maxERevQbParameters.addWhereWithNamedParam(revisionPropertyPath, "<=", "revision");
|
|
||||||
// e2.id = e.id
|
|
||||||
referencedIdMapper.addIdsEqualToQuery(maxERevQbParameters,
|
|
||||||
"e." + originalIdPropertyName, "e2." + originalIdPropertyName);
|
|
||||||
|
|
||||||
// e.revision = (SELECT max(...) ...)
|
|
||||||
rootParameters.addWhere(revisionPropertyPath, false, globalCfg.getCorrelatedSubqueryOperator(), maxERevQb);
|
|
||||||
|
|
||||||
// e.revision_type != DEL
|
// e.revision_type != DEL
|
||||||
rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), false, "!=", "delrevisiontype");
|
rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), false, "!=", "delrevisiontype");
|
||||||
|
@ -107,4 +105,4 @@ public final class OneAuditEntityQueryGenerator implements RelationQueryGenerato
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,17 +25,17 @@ package org.hibernate.envers.entities.mapper.relation.query;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import org.hibernate.Query;
|
||||||
import org.hibernate.envers.RevisionType;
|
import org.hibernate.envers.RevisionType;
|
||||||
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
||||||
import org.hibernate.envers.entities.mapper.id.QueryParameterData;
|
import org.hibernate.envers.entities.mapper.id.QueryParameterData;
|
||||||
import org.hibernate.envers.entities.mapper.relation.MiddleComponentData;
|
import org.hibernate.envers.entities.mapper.relation.MiddleComponentData;
|
||||||
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
|
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
|
||||||
import org.hibernate.envers.reader.AuditReaderImplementor;
|
import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||||
|
import org.hibernate.envers.strategy.AuditStrategy;
|
||||||
import org.hibernate.envers.tools.query.Parameters;
|
import org.hibernate.envers.tools.query.Parameters;
|
||||||
import org.hibernate.envers.tools.query.QueryBuilder;
|
import org.hibernate.envers.tools.query.QueryBuilder;
|
||||||
|
|
||||||
import org.hibernate.Query;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects data from a relation middle-table only.
|
* Selects data from a relation middle-table only.
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
@ -45,6 +45,7 @@ public final class OneEntityQueryGenerator implements RelationQueryGenerator {
|
||||||
private final MiddleIdData referencingIdData;
|
private final MiddleIdData referencingIdData;
|
||||||
|
|
||||||
public OneEntityQueryGenerator(AuditEntitiesConfiguration verEntCfg,
|
public OneEntityQueryGenerator(AuditEntitiesConfiguration verEntCfg,
|
||||||
|
AuditStrategy auditStrategy,
|
||||||
String versionsMiddleEntityName,
|
String versionsMiddleEntityName,
|
||||||
MiddleIdData referencingIdData,
|
MiddleIdData referencingIdData,
|
||||||
MiddleComponentData... componentDatas) {
|
MiddleComponentData... componentDatas) {
|
||||||
|
@ -55,9 +56,17 @@ public final class OneEntityQueryGenerator implements RelationQueryGenerator {
|
||||||
* SELECT new list(ee) FROM middleEntity ee WHERE
|
* SELECT new list(ee) FROM middleEntity ee WHERE
|
||||||
* (only entities referenced by the association; id_ref_ing = id of the referencing entity)
|
* (only entities referenced by the association; id_ref_ing = id of the referencing entity)
|
||||||
* ee.originalId.id_ref_ing = :id_ref_ing AND
|
* ee.originalId.id_ref_ing = :id_ref_ing AND
|
||||||
|
*
|
||||||
* (the association at revision :revision)
|
* (the association at revision :revision)
|
||||||
|
* --> for DefaultAuditStrategy:
|
||||||
* ee.revision = (SELECT max(ee2.revision) FROM middleEntity ee2
|
* ee.revision = (SELECT max(ee2.revision) FROM middleEntity ee2
|
||||||
* WHERE ee2.revision <= :revision AND ee2.originalId.* = ee.originalId.*) AND
|
* WHERE ee2.revision <= :revision AND ee2.originalId.* = ee.originalId.*)
|
||||||
|
*
|
||||||
|
* --> for ValidTimeAuditStrategy:
|
||||||
|
* ee.revision <= :revision and (ee.endRevision > :revision or ee.endRevision is null)
|
||||||
|
*
|
||||||
|
* AND
|
||||||
|
*
|
||||||
* (only non-deleted entities and associations)
|
* (only non-deleted entities and associations)
|
||||||
* ee.revision_type != DEL
|
* ee.revision_type != DEL
|
||||||
*/
|
*/
|
||||||
|
@ -71,22 +80,15 @@ public final class OneEntityQueryGenerator implements RelationQueryGenerator {
|
||||||
Parameters rootParameters = qb.getRootParameters();
|
Parameters rootParameters = qb.getRootParameters();
|
||||||
// ee.originalId.id_ref_ing = :id_ref_ing
|
// ee.originalId.id_ref_ing = :id_ref_ing
|
||||||
referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, originalIdPropertyName, true);
|
referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, originalIdPropertyName, true);
|
||||||
// SELECT max(ee2.revision) FROM middleEntity ee2
|
|
||||||
QueryBuilder maxRevQb = qb.newSubQueryBuilder(versionsMiddleEntityName, "ee2");
|
|
||||||
maxRevQb.addProjection("max", revisionPropertyPath, false);
|
|
||||||
// WHERE
|
|
||||||
Parameters maxRevQbParameters = maxRevQb.getRootParameters();
|
|
||||||
// ee2.revision <= :revision
|
|
||||||
maxRevQbParameters.addWhereWithNamedParam(revisionPropertyPath, "<=", "revision");
|
|
||||||
// ee2.originalId.* = ee.originalId.*
|
|
||||||
String eeOriginalIdPropertyPath = "ee." + originalIdPropertyName;
|
String eeOriginalIdPropertyPath = "ee." + originalIdPropertyName;
|
||||||
String ee2OriginalIdPropertyPath = "ee2." + originalIdPropertyName;
|
|
||||||
referencingIdData.getPrefixedMapper().addIdsEqualToQuery(maxRevQbParameters, eeOriginalIdPropertyPath, ee2OriginalIdPropertyPath);
|
// (with ee association at revision :revision)
|
||||||
for (MiddleComponentData componentData : componentDatas) {
|
// --> based on auditStrategy (see above)
|
||||||
componentData.getComponentMapper().addMiddleEqualToQuery(maxRevQbParameters, eeOriginalIdPropertyPath, ee2OriginalIdPropertyPath);
|
auditStrategy.addAssociationAtRevisionRestriction(qb, revisionPropertyPath,
|
||||||
}
|
verEntCfg.getRevisionEndFieldName(), true,referencingIdData, versionsMiddleEntityName,
|
||||||
// ee.revision = (SELECT max(...) ...)
|
eeOriginalIdPropertyPath, revisionPropertyPath, originalIdPropertyName, componentDatas);
|
||||||
rootParameters.addWhere(revisionPropertyPath, "=", maxRevQb);
|
|
||||||
// ee.revision_type != DEL
|
// ee.revision_type != DEL
|
||||||
rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), "!=", "delrevisiontype");
|
rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), "!=", "delrevisiontype");
|
||||||
|
|
||||||
|
|
|
@ -1,75 +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.entities.mapper.relation.query;
|
|
||||||
|
|
||||||
import org.hibernate.envers.configuration.GlobalConfiguration;
|
|
||||||
import org.hibernate.envers.entities.mapper.relation.MiddleComponentData;
|
|
||||||
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
|
|
||||||
import org.hibernate.envers.tools.query.Parameters;
|
|
||||||
import org.hibernate.envers.tools.query.QueryBuilder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Adam Warski (adam at warski dot org)
|
|
||||||
*/
|
|
||||||
public class QueryGeneratorTools {
|
|
||||||
public static void addEntityAtRevision(GlobalConfiguration globalCfg, QueryBuilder qb, Parameters rootParameters,
|
|
||||||
MiddleIdData idData, String revisionPropertyPath, String originalIdPropertyName,
|
|
||||||
String alias1, String alias2) {
|
|
||||||
// SELECT max(e.revision) FROM versionsReferencedEntity e2
|
|
||||||
QueryBuilder maxERevQb = qb.newSubQueryBuilder(idData.getAuditEntityName(), alias2);
|
|
||||||
maxERevQb.addProjection("max", revisionPropertyPath, false);
|
|
||||||
// WHERE
|
|
||||||
Parameters maxERevQbParameters = maxERevQb.getRootParameters();
|
|
||||||
// e2.revision <= :revision
|
|
||||||
maxERevQbParameters.addWhereWithNamedParam(revisionPropertyPath, "<=", "revision");
|
|
||||||
// e2.id_ref_ed = e.id_ref_ed
|
|
||||||
idData.getOriginalMapper().addIdsEqualToQuery(maxERevQbParameters,
|
|
||||||
alias1 + "." + originalIdPropertyName, alias2 +"." + originalIdPropertyName);
|
|
||||||
|
|
||||||
// e.revision = (SELECT max(...) ...)
|
|
||||||
rootParameters.addWhere("e." + revisionPropertyPath, false, globalCfg.getCorrelatedSubqueryOperator(), maxERevQb);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void addAssociationAtRevision(QueryBuilder qb, Parameters rootParameters,
|
|
||||||
MiddleIdData referencingIdData, String versionsMiddleEntityName,
|
|
||||||
String eeOriginalIdPropertyPath, String revisionPropertyPath,
|
|
||||||
String originalIdPropertyName, MiddleComponentData... componentDatas) {
|
|
||||||
// SELECT max(ee2.revision) FROM middleEntity ee2
|
|
||||||
QueryBuilder maxEeRevQb = qb.newSubQueryBuilder(versionsMiddleEntityName, "ee2");
|
|
||||||
maxEeRevQb.addProjection("max", revisionPropertyPath, false);
|
|
||||||
// WHERE
|
|
||||||
Parameters maxEeRevQbParameters = maxEeRevQb.getRootParameters();
|
|
||||||
// ee2.revision <= :revision
|
|
||||||
maxEeRevQbParameters.addWhereWithNamedParam(revisionPropertyPath, "<=", "revision");
|
|
||||||
// ee2.originalId.* = ee.originalId.*
|
|
||||||
String ee2OriginalIdPropertyPath = "ee2." + originalIdPropertyName;
|
|
||||||
referencingIdData.getPrefixedMapper().addIdsEqualToQuery(maxEeRevQbParameters, eeOriginalIdPropertyPath, ee2OriginalIdPropertyPath);
|
|
||||||
for (MiddleComponentData componentData : componentDatas) {
|
|
||||||
componentData.getComponentMapper().addMiddleEqualToQuery(maxEeRevQbParameters, eeOriginalIdPropertyPath, ee2OriginalIdPropertyPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ee.revision = (SELECT max(...) ...)
|
|
||||||
rootParameters.addWhere(revisionPropertyPath, "=", maxEeRevQb);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -25,18 +25,18 @@ package org.hibernate.envers.entities.mapper.relation.query;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import org.hibernate.Query;
|
||||||
import org.hibernate.envers.RevisionType;
|
import org.hibernate.envers.RevisionType;
|
||||||
import org.hibernate.envers.configuration.GlobalConfiguration;
|
|
||||||
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
||||||
|
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||||
import org.hibernate.envers.entities.mapper.id.QueryParameterData;
|
import org.hibernate.envers.entities.mapper.id.QueryParameterData;
|
||||||
import org.hibernate.envers.entities.mapper.relation.MiddleComponentData;
|
import org.hibernate.envers.entities.mapper.relation.MiddleComponentData;
|
||||||
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
|
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
|
||||||
import org.hibernate.envers.reader.AuditReaderImplementor;
|
import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||||
|
import org.hibernate.envers.strategy.AuditStrategy;
|
||||||
import org.hibernate.envers.tools.query.Parameters;
|
import org.hibernate.envers.tools.query.Parameters;
|
||||||
import org.hibernate.envers.tools.query.QueryBuilder;
|
import org.hibernate.envers.tools.query.QueryBuilder;
|
||||||
|
|
||||||
import org.hibernate.Query;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects data from a relation middle-table and a two related versions entity.
|
* Selects data from a relation middle-table and a two related versions entity.
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
@ -47,6 +47,7 @@ public final class ThreeEntityQueryGenerator implements RelationQueryGenerator {
|
||||||
|
|
||||||
public ThreeEntityQueryGenerator(GlobalConfiguration globalCfg,
|
public ThreeEntityQueryGenerator(GlobalConfiguration globalCfg,
|
||||||
AuditEntitiesConfiguration verEntCfg,
|
AuditEntitiesConfiguration verEntCfg,
|
||||||
|
AuditStrategy auditStrategy,
|
||||||
String versionsMiddleEntityName,
|
String versionsMiddleEntityName,
|
||||||
MiddleIdData referencingIdData,
|
MiddleIdData referencingIdData,
|
||||||
MiddleIdData referencedIdData,
|
MiddleIdData referencedIdData,
|
||||||
|
@ -65,14 +66,48 @@ public final class ThreeEntityQueryGenerator implements RelationQueryGenerator {
|
||||||
* (only entities referenced by the association; id_ref_ing = id of the referencing entity)
|
* (only entities referenced by the association; id_ref_ing = id of the referencing entity)
|
||||||
* ee.id_ref_ing = :id_ref_ing AND
|
* ee.id_ref_ing = :id_ref_ing AND
|
||||||
* (selecting e entities at revision :revision)
|
* (selecting e entities at revision :revision)
|
||||||
|
* --> for DefaultAuditStrategy:
|
||||||
* e.revision = (SELECT max(e2.revision) FROM versionsReferencedEntity e2
|
* e.revision = (SELECT max(e2.revision) FROM versionsReferencedEntity e2
|
||||||
* WHERE e2.revision <= :revision AND e2.id_ref_ed = e.id_ref_ed) AND
|
* WHERE e2.revision <= :revision AND e2.id = e.id)
|
||||||
|
*
|
||||||
|
* --> for ValidTimeAuditStrategy:
|
||||||
|
* e.revision <= :revision and (e.endRevision > :revision or e.endRevision is null)
|
||||||
|
*
|
||||||
|
* AND
|
||||||
|
*
|
||||||
* (selecting f entities at revision :revision)
|
* (selecting f entities at revision :revision)
|
||||||
|
* --> for DefaultAuditStrategy:
|
||||||
* f.revision = (SELECT max(f2.revision) FROM versionsIndexEntity f2
|
* f.revision = (SELECT max(f2.revision) FROM versionsIndexEntity f2
|
||||||
* WHERE f2.revision <= :revision AND f2.id_ref_ed = f.id_ref_ed) AND
|
* WHERE f2.revision <= :revision AND f2.id_ref_ed = f.id_ref_ed)
|
||||||
|
*
|
||||||
|
* --> for ValidTimeAuditStrategy:
|
||||||
|
* f.revision <= :revision and (f.endRevision > :revision or f.endRevision is null)
|
||||||
|
*
|
||||||
|
* AND
|
||||||
|
*
|
||||||
* (the association at revision :revision)
|
* (the association at revision :revision)
|
||||||
|
* --> for DefaultAuditStrategy:
|
||||||
* ee.revision = (SELECT max(ee2.revision) FROM middleEntity ee2
|
* ee.revision = (SELECT max(ee2.revision) FROM middleEntity ee2
|
||||||
* WHERE ee2.revision <= :revision AND ee2.originalId.* = ee.originalId.*) AND
|
* WHERE ee2.revision <= :revision AND ee2.originalId.* = ee.originalId.*)
|
||||||
|
*
|
||||||
|
* --> for ValidTimeAuditStrategy:
|
||||||
|
* ee.revision <= :revision and (ee.endRevision > :revision or ee.endRevision is null)
|
||||||
|
*
|
||||||
|
and (
|
||||||
|
strtestent1_.REVEND>?
|
||||||
|
or strtestent1_.REVEND is null
|
||||||
|
)
|
||||||
|
and (
|
||||||
|
strtestent1_.REVEND>?
|
||||||
|
or strtestent1_.REVEND is null
|
||||||
|
)
|
||||||
|
and (
|
||||||
|
ternarymap0_.REVEND>?
|
||||||
|
or ternarymap0_.REVEND is null
|
||||||
|
)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
* (only non-deleted entities and associations)
|
* (only non-deleted entities and associations)
|
||||||
* ee.revision_type != DEL AND
|
* ee.revision_type != DEL AND
|
||||||
* e.revision_type != DEL AND
|
* e.revision_type != DEL AND
|
||||||
|
@ -80,7 +115,6 @@ public final class ThreeEntityQueryGenerator implements RelationQueryGenerator {
|
||||||
*/
|
*/
|
||||||
String revisionPropertyPath = verEntCfg.getRevisionNumberPath();
|
String revisionPropertyPath = verEntCfg.getRevisionNumberPath();
|
||||||
String originalIdPropertyName = verEntCfg.getOriginalIdPropName();
|
String originalIdPropertyName = verEntCfg.getOriginalIdPropName();
|
||||||
|
|
||||||
String eeOriginalIdPropertyPath = "ee." + originalIdPropertyName;
|
String eeOriginalIdPropertyPath = "ee." + originalIdPropertyName;
|
||||||
|
|
||||||
// SELECT new list(ee) FROM middleEntity ee
|
// SELECT new list(ee) FROM middleEntity ee
|
||||||
|
@ -99,17 +133,23 @@ public final class ThreeEntityQueryGenerator implements RelationQueryGenerator {
|
||||||
// ee.originalId.id_ref_ing = :id_ref_ing
|
// ee.originalId.id_ref_ing = :id_ref_ing
|
||||||
referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, originalIdPropertyName, true);
|
referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, originalIdPropertyName, true);
|
||||||
|
|
||||||
// e.revision = (SELECT max(...) ...)
|
// (selecting e entities at revision :revision)
|
||||||
QueryGeneratorTools.addEntityAtRevision(globalCfg, qb, rootParameters, referencedIdData, revisionPropertyPath,
|
// --> based on auditStrategy (see above)
|
||||||
originalIdPropertyName, "e", "e2");
|
auditStrategy.addEntityAtRevisionRestriction(globalCfg, qb, "e." + revisionPropertyPath,
|
||||||
|
"e." + verEntCfg.getRevisionEndFieldName(), false,
|
||||||
|
referencedIdData, revisionPropertyPath, originalIdPropertyName, "e", "e2");
|
||||||
|
|
||||||
|
// (selecting f entities at revision :revision)
|
||||||
|
// --> based on auditStrategy (see above)
|
||||||
|
auditStrategy.addEntityAtRevisionRestriction(globalCfg, qb, "e." + revisionPropertyPath,
|
||||||
|
"e." + verEntCfg.getRevisionEndFieldName(), false,
|
||||||
|
referencedIdData, revisionPropertyPath, originalIdPropertyName, "f", "f2");
|
||||||
|
|
||||||
// f.revision = (SELECT max(...) ...)
|
// (with ee association at revision :revision)
|
||||||
QueryGeneratorTools.addEntityAtRevision(globalCfg, qb, rootParameters, indexIdData, revisionPropertyPath,
|
// --> based on auditStrategy (see above)
|
||||||
originalIdPropertyName, "f", "f2");
|
auditStrategy.addAssociationAtRevisionRestriction(qb, revisionPropertyPath,
|
||||||
|
verEntCfg.getRevisionEndFieldName(), true, referencingIdData, versionsMiddleEntityName,
|
||||||
// ee.revision = (SELECT max(...) ...)
|
eeOriginalIdPropertyPath, revisionPropertyPath, originalIdPropertyName, componentDatas);
|
||||||
QueryGeneratorTools.addAssociationAtRevision(qb, rootParameters, referencingIdData, versionsMiddleEntityName,
|
|
||||||
eeOriginalIdPropertyPath, revisionPropertyPath, originalIdPropertyName, componentDatas);
|
|
||||||
|
|
||||||
// ee.revision_type != DEL
|
// ee.revision_type != DEL
|
||||||
rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), "!=", "delrevisiontype");
|
rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), "!=", "delrevisiontype");
|
||||||
|
|
|
@ -26,11 +26,14 @@ package org.hibernate.envers.entities.mapper.relation.query;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import org.hibernate.envers.RevisionType;
|
import org.hibernate.envers.RevisionType;
|
||||||
|
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||||
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
||||||
|
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||||
import org.hibernate.envers.entities.mapper.id.QueryParameterData;
|
import org.hibernate.envers.entities.mapper.id.QueryParameterData;
|
||||||
import org.hibernate.envers.entities.mapper.relation.MiddleComponentData;
|
import org.hibernate.envers.entities.mapper.relation.MiddleComponentData;
|
||||||
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
|
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
|
||||||
import org.hibernate.envers.reader.AuditReaderImplementor;
|
import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||||
|
import org.hibernate.envers.strategy.AuditStrategy;
|
||||||
import org.hibernate.envers.tools.query.Parameters;
|
import org.hibernate.envers.tools.query.Parameters;
|
||||||
import org.hibernate.envers.tools.query.QueryBuilder;
|
import org.hibernate.envers.tools.query.QueryBuilder;
|
||||||
|
|
||||||
|
@ -44,8 +47,7 @@ public final class TwoEntityOneAuditedQueryGenerator implements RelationQueryGen
|
||||||
private final String queryString;
|
private final String queryString;
|
||||||
private final MiddleIdData referencingIdData;
|
private final MiddleIdData referencingIdData;
|
||||||
|
|
||||||
public TwoEntityOneAuditedQueryGenerator(
|
public TwoEntityOneAuditedQueryGenerator(AuditEntitiesConfiguration verEntCfg, AuditStrategy auditStrategy,
|
||||||
AuditEntitiesConfiguration verEntCfg,
|
|
||||||
String versionsMiddleEntityName,
|
String versionsMiddleEntityName,
|
||||||
MiddleIdData referencingIdData,
|
MiddleIdData referencingIdData,
|
||||||
MiddleIdData referencedIdData,
|
MiddleIdData referencedIdData,
|
||||||
|
@ -60,9 +62,17 @@ public final class TwoEntityOneAuditedQueryGenerator implements RelationQueryGen
|
||||||
* ee.id_ref_ed = e.id_ref_ed AND
|
* ee.id_ref_ed = e.id_ref_ed AND
|
||||||
* (only entities referenced by the association; id_ref_ing = id of the referencing entity)
|
* (only entities referenced by the association; id_ref_ing = id of the referencing entity)
|
||||||
* ee.id_ref_ing = :id_ref_ing AND
|
* ee.id_ref_ing = :id_ref_ing AND
|
||||||
|
*
|
||||||
* (the association at revision :revision)
|
* (the association at revision :revision)
|
||||||
|
* --> for DefaultAuditStrategy:
|
||||||
* ee.revision = (SELECT max(ee2.revision) FROM middleEntity ee2
|
* ee.revision = (SELECT max(ee2.revision) FROM middleEntity ee2
|
||||||
* WHERE ee2.revision <= :revision AND ee2.originalId.* = ee.originalId.*) AND
|
* WHERE ee2.revision <= :revision AND ee2.originalId.* = ee.originalId.*)
|
||||||
|
*
|
||||||
|
* --> for ValidTimeAuditStrategy:
|
||||||
|
* ee.revision <= :revision and (ee.endRevision > :revision or ee.endRevision is null)
|
||||||
|
*
|
||||||
|
* AND
|
||||||
|
*
|
||||||
* (only non-deleted entities and associations)
|
* (only non-deleted entities and associations)
|
||||||
* ee.revision_type != DEL
|
* ee.revision_type != DEL
|
||||||
*/
|
*/
|
||||||
|
@ -83,9 +93,11 @@ public final class TwoEntityOneAuditedQueryGenerator implements RelationQueryGen
|
||||||
// ee.originalId.id_ref_ing = :id_ref_ing
|
// ee.originalId.id_ref_ing = :id_ref_ing
|
||||||
referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, originalIdPropertyName, true);
|
referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, originalIdPropertyName, true);
|
||||||
|
|
||||||
// ee.revision = (SELECT max(...) ...)
|
// (with ee association at revision :revision)
|
||||||
QueryGeneratorTools.addAssociationAtRevision(qb, rootParameters, referencingIdData, versionsMiddleEntityName,
|
// --> based on auditStrategy (see above)
|
||||||
eeOriginalIdPropertyPath, revisionPropertyPath, originalIdPropertyName, componentDatas);
|
auditStrategy.addAssociationAtRevisionRestriction(qb, revisionPropertyPath,
|
||||||
|
verEntCfg.getRevisionEndFieldName(), true,referencingIdData, versionsMiddleEntityName,
|
||||||
|
eeOriginalIdPropertyPath, revisionPropertyPath, originalIdPropertyName, componentDatas);
|
||||||
|
|
||||||
// ee.revision_type != DEL
|
// ee.revision_type != DEL
|
||||||
rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), "!=", "delrevisiontype");
|
rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), "!=", "delrevisiontype");
|
||||||
|
@ -105,4 +117,4 @@ public final class TwoEntityOneAuditedQueryGenerator implements RelationQueryGen
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,18 +25,18 @@ package org.hibernate.envers.entities.mapper.relation.query;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import org.hibernate.Query;
|
||||||
import org.hibernate.envers.RevisionType;
|
import org.hibernate.envers.RevisionType;
|
||||||
import org.hibernate.envers.configuration.GlobalConfiguration;
|
|
||||||
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
||||||
|
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||||
import org.hibernate.envers.entities.mapper.id.QueryParameterData;
|
import org.hibernate.envers.entities.mapper.id.QueryParameterData;
|
||||||
import org.hibernate.envers.entities.mapper.relation.MiddleComponentData;
|
import org.hibernate.envers.entities.mapper.relation.MiddleComponentData;
|
||||||
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
|
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
|
||||||
import org.hibernate.envers.reader.AuditReaderImplementor;
|
import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||||
|
import org.hibernate.envers.strategy.AuditStrategy;
|
||||||
import org.hibernate.envers.tools.query.Parameters;
|
import org.hibernate.envers.tools.query.Parameters;
|
||||||
import org.hibernate.envers.tools.query.QueryBuilder;
|
import org.hibernate.envers.tools.query.QueryBuilder;
|
||||||
|
|
||||||
import org.hibernate.Query;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects data from a relation middle-table and a related versions entity.
|
* Selects data from a relation middle-table and a related versions entity.
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
@ -47,6 +47,7 @@ public final class TwoEntityQueryGenerator implements RelationQueryGenerator {
|
||||||
|
|
||||||
public TwoEntityQueryGenerator(GlobalConfiguration globalCfg,
|
public TwoEntityQueryGenerator(GlobalConfiguration globalCfg,
|
||||||
AuditEntitiesConfiguration verEntCfg,
|
AuditEntitiesConfiguration verEntCfg,
|
||||||
|
AuditStrategy auditStrategy,
|
||||||
String versionsMiddleEntityName,
|
String versionsMiddleEntityName,
|
||||||
MiddleIdData referencingIdData,
|
MiddleIdData referencingIdData,
|
||||||
MiddleIdData referencedIdData,
|
MiddleIdData referencedIdData,
|
||||||
|
@ -61,12 +62,25 @@ public final class TwoEntityQueryGenerator implements RelationQueryGenerator {
|
||||||
* ee.id_ref_ed = e.id_ref_ed AND
|
* ee.id_ref_ed = e.id_ref_ed AND
|
||||||
* (only entities referenced by the association; id_ref_ing = id of the referencing entity)
|
* (only entities referenced by the association; id_ref_ing = id of the referencing entity)
|
||||||
* ee.id_ref_ing = :id_ref_ing AND
|
* ee.id_ref_ing = :id_ref_ing AND
|
||||||
|
*
|
||||||
* (selecting e entities at revision :revision)
|
* (selecting e entities at revision :revision)
|
||||||
|
* --> for DefaultAuditStrategy:
|
||||||
* e.revision = (SELECT max(e2.revision) FROM versionsReferencedEntity e2
|
* e.revision = (SELECT max(e2.revision) FROM versionsReferencedEntity e2
|
||||||
* WHERE e2.revision <= :revision AND e2.id_ref_ed = e.id_ref_ed) AND
|
* WHERE e2.revision <= :revision AND e2.id = e.id)
|
||||||
* (the association at revision :revision)
|
*
|
||||||
|
* --> for ValidTimeAuditStrategy:
|
||||||
|
* e.revision <= :revision and (e.endRevision > :revision or e.endRevision is null)
|
||||||
|
*
|
||||||
|
* AND
|
||||||
|
*
|
||||||
|
* (the association at revision :revision)
|
||||||
|
* --> for DefaultAuditStrategy:
|
||||||
* ee.revision = (SELECT max(ee2.revision) FROM middleEntity ee2
|
* ee.revision = (SELECT max(ee2.revision) FROM middleEntity ee2
|
||||||
* WHERE ee2.revision <= :revision AND ee2.originalId.* = ee.originalId.*) AND
|
* WHERE ee2.revision <= :revision AND ee2.originalId.* = ee.originalId.*)
|
||||||
|
*
|
||||||
|
* --> for ValidTimeAuditStrategy:
|
||||||
|
* ee.revision <= :revision and (ee.endRevision > :revision or ee.endRevision is null)
|
||||||
|
*
|
||||||
* (only non-deleted entities and associations)
|
* (only non-deleted entities and associations)
|
||||||
* ee.revision_type != DEL AND
|
* ee.revision_type != DEL AND
|
||||||
* e.revision_type != DEL
|
* e.revision_type != DEL
|
||||||
|
@ -88,13 +102,17 @@ public final class TwoEntityQueryGenerator implements RelationQueryGenerator {
|
||||||
// ee.originalId.id_ref_ing = :id_ref_ing
|
// ee.originalId.id_ref_ing = :id_ref_ing
|
||||||
referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, originalIdPropertyName, true);
|
referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, originalIdPropertyName, true);
|
||||||
|
|
||||||
// e.revision = (SELECT max(...) ...)
|
// (selecting e entities at revision :revision)
|
||||||
QueryGeneratorTools.addEntityAtRevision(globalCfg, qb, rootParameters, referencedIdData, revisionPropertyPath,
|
// --> based on auditStrategy (see above)
|
||||||
originalIdPropertyName, "e", "e2");
|
auditStrategy.addEntityAtRevisionRestriction(globalCfg, qb, "e." + revisionPropertyPath,
|
||||||
|
"e." + verEntCfg.getRevisionEndFieldName(), false,
|
||||||
|
referencedIdData, revisionPropertyPath, originalIdPropertyName, "e", "e2");
|
||||||
|
|
||||||
// ee.revision = (SELECT max(...) ...)
|
// (with ee association at revision :revision)
|
||||||
QueryGeneratorTools.addAssociationAtRevision(qb, rootParameters, referencingIdData, versionsMiddleEntityName,
|
// --> based on auditStrategy (see above)
|
||||||
eeOriginalIdPropertyPath, revisionPropertyPath, originalIdPropertyName, componentDatas);
|
auditStrategy.addAssociationAtRevisionRestriction(qb, revisionPropertyPath,
|
||||||
|
verEntCfg.getRevisionEndFieldName(), true, referencingIdData, versionsMiddleEntityName,
|
||||||
|
eeOriginalIdPropertyPath, revisionPropertyPath, originalIdPropertyName, componentDatas);
|
||||||
|
|
||||||
// ee.revision_type != DEL
|
// ee.revision_type != DEL
|
||||||
rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), "!=", "delrevisiontype");
|
rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), "!=", "delrevisiontype");
|
||||||
|
|
|
@ -86,10 +86,14 @@ public abstract class AbstractAuditQuery implements AuditQuery {
|
||||||
qb = new QueryBuilder(versionsEntityName, "e");
|
qb = new QueryBuilder(versionsEntityName, "e");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List buildAndExecuteQuery() {
|
protected Query buildQuery() {
|
||||||
Query query = qb.toQuery(versionsReader.getSession());
|
Query query = qb.toQuery(versionsReader.getSession());
|
||||||
|
|
||||||
setQueryProperties(query);
|
setQueryProperties(query);
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List buildAndExecuteQuery() {
|
||||||
|
Query query = buildQuery();
|
||||||
|
|
||||||
return query.list();
|
return query.list();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,14 +24,16 @@
|
||||||
package org.hibernate.envers.query.impl;
|
package org.hibernate.envers.query.impl;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.Query;
|
||||||
import org.hibernate.envers.RevisionType;
|
import org.hibernate.envers.RevisionType;
|
||||||
import org.hibernate.envers.configuration.AuditConfiguration;
|
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||||
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
||||||
|
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
|
||||||
import org.hibernate.envers.query.criteria.AuditCriterion;
|
import org.hibernate.envers.query.criteria.AuditCriterion;
|
||||||
import org.hibernate.envers.reader.AuditReaderImplementor;
|
import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||||
import org.hibernate.envers.tools.query.QueryBuilder;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
@ -56,39 +58,50 @@ public class EntitiesAtRevisionQuery extends AbstractAuditQuery {
|
||||||
@SuppressWarnings({"unchecked"})
|
@SuppressWarnings({"unchecked"})
|
||||||
public List list() {
|
public List list() {
|
||||||
/*
|
/*
|
||||||
The query that should be executed in the versions table:
|
* The query that we need to create:
|
||||||
SELECT e FROM ent_ver e WHERE
|
* SELECT new list(e) FROM versionsReferencedEntity e
|
||||||
(all specified conditions, transformed, on the "e" entity) AND
|
* WHERE
|
||||||
e.revision_type != DEL AND
|
* (all specified conditions, transformed, on the "e" entity) AND
|
||||||
e.revision = (SELECT max(e2.revision) FROM ent_ver e2 WHERE
|
* (selecting e entities at revision :revision)
|
||||||
e2.revision <= :revision AND e2.originalId.id = e.originalId.id)
|
* --> for DefaultAuditStrategy:
|
||||||
|
* e.revision = (SELECT max(e2.revision) FROM versionsReferencedEntity e2
|
||||||
|
* WHERE e2.revision <= :revision AND e2.id = e.id)
|
||||||
|
*
|
||||||
|
* --> for ValidTimeAuditStrategy:
|
||||||
|
* e.revision <= :revision and (e.endRevision > :revision or e.endRevision is null)
|
||||||
|
*
|
||||||
|
* AND
|
||||||
|
* (only non-deleted entities)
|
||||||
|
* e.revision_type != DEL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
QueryBuilder maxRevQb = qb.newSubQueryBuilder(versionsEntityName, "e2");
|
|
||||||
|
|
||||||
AuditEntitiesConfiguration verEntCfg = verCfg.getAuditEntCfg();
|
AuditEntitiesConfiguration verEntCfg = verCfg.getAuditEntCfg();
|
||||||
|
|
||||||
String revisionPropertyPath = verEntCfg.getRevisionNumberPath();
|
String revisionPropertyPath = verEntCfg.getRevisionNumberPath();
|
||||||
String originalIdPropertyName = verEntCfg.getOriginalIdPropName();
|
String originalIdPropertyName = verEntCfg.getOriginalIdPropName();
|
||||||
|
|
||||||
// SELECT max(e2.revision)
|
MiddleIdData referencedIdData = new MiddleIdData(verEntCfg, verCfg.getEntCfg().get(entityName).getIdMappingData(),
|
||||||
maxRevQb.addProjection("max", revisionPropertyPath, false);
|
null, entityName, verCfg.getEntCfg().isVersioned(entityName));
|
||||||
// e2.revision <= :revision
|
|
||||||
maxRevQb.getRootParameters().addWhereWithParam(revisionPropertyPath, "<=", revision);
|
// (selecting e entities at revision :revision)
|
||||||
// e2.id = e.id
|
// --> based on auditStrategy (see above)
|
||||||
verCfg.getEntCfg().get(entityName).getIdMapper().addIdsEqualToQuery(maxRevQb.getRootParameters(),
|
verCfg.getAuditStrategy().addEntityAtRevisionRestriction(verCfg.getGlobalCfg(), qb, revisionPropertyPath,
|
||||||
"e." + originalIdPropertyName, "e2." + originalIdPropertyName);
|
verEntCfg.getRevisionEndFieldName(), true, referencedIdData,
|
||||||
|
revisionPropertyPath, originalIdPropertyName, "e", "e2");
|
||||||
|
|
||||||
|
// e.revision_type != DEL
|
||||||
|
qb.getRootParameters().addWhereWithParam(verEntCfg.getRevisionTypePropName(), "<>", RevisionType.DEL);
|
||||||
|
|
||||||
// e.revision_type != DEL AND
|
|
||||||
qb.getRootParameters().addWhereWithParam(verEntCfg.getRevisionTypePropName(), "<>", RevisionType.DEL);
|
|
||||||
// e.revision = (SELECT max(...) ...)
|
|
||||||
qb.getRootParameters().addWhere(revisionPropertyPath, verCfg.getGlobalCfg().getCorrelatedSubqueryOperator(), maxRevQb);
|
|
||||||
// all specified conditions
|
// all specified conditions
|
||||||
for (AuditCriterion criterion : criterions) {
|
for (AuditCriterion criterion : criterions) {
|
||||||
criterion.addToQuery(verCfg, entityName, qb, qb.getRootParameters());
|
criterion.addToQuery(verCfg, entityName, qb, qb.getRootParameters());
|
||||||
}
|
}
|
||||||
|
|
||||||
List queryResult = buildAndExecuteQuery();
|
Query query = buildQuery();
|
||||||
|
// add named parameter (only used for ValidAuditTimeStrategy)
|
||||||
|
List<String> params = Arrays.asList(query.getNamedParameters());
|
||||||
|
if (params.contains("revision")) {
|
||||||
|
query.setParameter("revision", revision);
|
||||||
|
}
|
||||||
|
List queryResult = query.list();
|
||||||
|
|
||||||
if (hasProjection) {
|
if (hasProjection) {
|
||||||
return queryResult;
|
return queryResult;
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
package org.hibernate.envers.strategy;
|
package org.hibernate.envers.strategy;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.envers.configuration.AuditConfiguration;
|
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||||
|
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||||
import org.hibernate.envers.entities.mapper.PersistentCollectionChangeData;
|
import org.hibernate.envers.entities.mapper.PersistentCollectionChangeData;
|
||||||
|
import org.hibernate.envers.entities.mapper.relation.MiddleComponentData;
|
||||||
import java.io.Serializable;
|
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
|
||||||
|
import org.hibernate.envers.tools.query.QueryBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Behaviours of different audit strategy for populating audit data.
|
* Behaviours of different audit strategy for populating audit data.
|
||||||
|
@ -36,4 +40,61 @@ public interface AuditStrategy {
|
||||||
*/
|
*/
|
||||||
void performCollectionChange(Session session, AuditConfiguration auditCfg,
|
void performCollectionChange(Session session, AuditConfiguration auditCfg,
|
||||||
PersistentCollectionChangeData persistentCollectionChangeData, Object revision);
|
PersistentCollectionChangeData persistentCollectionChangeData, Object revision);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the rootQueryBuilder with an extra WHERE clause to restrict the revision for a two-entity relation.
|
||||||
|
* This WHERE clause depends on the AuditStrategy, as follows:
|
||||||
|
* <ul>
|
||||||
|
* <li>For {@link DefaultAuditStrategy} a subquery is created:
|
||||||
|
* <p><code>e.revision = (SELECT max(...) ...)</code></p>
|
||||||
|
* </li>
|
||||||
|
* <li>for {@link ValidTimeAuditStrategy} the revision-end column is used:
|
||||||
|
* <p><code>e.revision <= :revision and (e.endRevision > :revision or e.endRevision is null)</code></p>
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param globalCfg the {@link GlobalConfiguration}
|
||||||
|
* @param rootQueryBuilder the {@link QueryBuilder} that will be updated
|
||||||
|
* @param revisionProperty property of the revision column
|
||||||
|
* @param revisionEndProperty property of the revisionEnd column (only used for {@link ValidTimeAuditStrategy})
|
||||||
|
* @param addAlias {@code boolean} indicator if a left alias is needed
|
||||||
|
* @param idData id-information for the two-entity relation (only used for {@link DefaultAuditStrategy})
|
||||||
|
* @param revisionPropertyPath path of the revision property (only used for {@link ValidTimeAuditStrategy})
|
||||||
|
* @param originalIdPropertyName name of the id property (only used for {@link ValidTimeAuditStrategy})
|
||||||
|
* @param alias1 an alias used for subquery (only used for {@link ValidTimeAuditStrategy})
|
||||||
|
* @param alias2 an alias used for subquery (only used for {@link ValidTimeAuditStrategy})
|
||||||
|
*/
|
||||||
|
void addEntityAtRevisionRestriction(GlobalConfiguration globalCfg, QueryBuilder rootQueryBuilder,
|
||||||
|
String revisionProperty, String revisionEndProperty, boolean addAlias, MiddleIdData idData,
|
||||||
|
String revisionPropertyPath, String originalIdPropertyName, String alias1, String alias2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the rootQueryBuilder with an extra WHERE clause to restrict the revision for a middle-entity
|
||||||
|
* association. This WHERE clause depends on the AuditStrategy, as follows:
|
||||||
|
* <ul>
|
||||||
|
* <li>For {@link DefaultAuditStrategy} a subquery is created:
|
||||||
|
* <p><code>e.revision = (SELECT max(...) ...)</code></p>
|
||||||
|
* </li>
|
||||||
|
* <li>for {@link ValidTimeAuditStrategy} the revision-end column is used:
|
||||||
|
* <p><code>e.revision <= :revision and (e.endRevision > :revision or e.endRevision is null)</code></p>
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param rootQueryBuilder the {@link QueryBuilder} that will be updated
|
||||||
|
* @param revisionProperty property of the revision column
|
||||||
|
* @param revisionEndProperty property of the revisionEnd column (only used for {@link ValidTimeAuditStrategy})
|
||||||
|
* @param addAlias {@code boolean} indicator if a left alias is needed
|
||||||
|
* @param referencingIdData id-information for the middle-entity association (only used for {@link DefaultAuditStrategy})
|
||||||
|
* @param versionsMiddleEntityName name of the middle-entity
|
||||||
|
* @param eeOriginalIdPropertyPath name of the id property (only used for {@link ValidTimeAuditStrategy})
|
||||||
|
* @param revisionPropertyPath path of the revision property (only used for {@link ValidTimeAuditStrategy})
|
||||||
|
* @param originalIdPropertyName name of the id property (only used for {@link ValidTimeAuditStrategy})
|
||||||
|
* @param componentDatas information about the middle-entity relation
|
||||||
|
*/
|
||||||
|
void addAssociationAtRevisionRestriction(QueryBuilder rootQueryBuilder, String revisionProperty,
|
||||||
|
String revisionEndProperty, boolean addAlias, MiddleIdData referencingIdData,
|
||||||
|
String versionsMiddleEntityName, String eeOriginalIdPropertyPath, String revisionPropertyPath,
|
||||||
|
String originalIdPropertyName, MiddleComponentData... componentDatas);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
package org.hibernate.envers.strategy;
|
package org.hibernate.envers.strategy;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.envers.configuration.AuditConfiguration;
|
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||||
|
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||||
import org.hibernate.envers.entities.mapper.PersistentCollectionChangeData;
|
import org.hibernate.envers.entities.mapper.PersistentCollectionChangeData;
|
||||||
|
import org.hibernate.envers.entities.mapper.relation.MiddleComponentData;
|
||||||
import java.io.Serializable;
|
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
|
||||||
|
import org.hibernate.envers.tools.query.Parameters;
|
||||||
|
import org.hibernate.envers.tools.query.QueryBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default strategy is to simply persist the audit data.
|
* Default strategy is to simply persist the audit data.
|
||||||
|
@ -22,4 +27,52 @@ public class DefaultAuditStrategy implements AuditStrategy {
|
||||||
PersistentCollectionChangeData persistentCollectionChangeData, Object revision) {
|
PersistentCollectionChangeData persistentCollectionChangeData, Object revision) {
|
||||||
session.save(persistentCollectionChangeData.getEntityName(), persistentCollectionChangeData.getData());
|
session.save(persistentCollectionChangeData.getEntityName(), persistentCollectionChangeData.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void addEntityAtRevisionRestriction(GlobalConfiguration globalCfg, QueryBuilder rootQueryBuilder, String revisionProperty,
|
||||||
|
String revisionEndProperty, boolean addAlias, MiddleIdData idData, String revisionPropertyPath,
|
||||||
|
String originalIdPropertyName, String alias1, String alias2) {
|
||||||
|
Parameters rootParameters = rootQueryBuilder.getRootParameters();
|
||||||
|
|
||||||
|
// create a subquery builder
|
||||||
|
// SELECT max(e.revision) FROM versionsReferencedEntity e2
|
||||||
|
QueryBuilder maxERevQb = rootQueryBuilder.newSubQueryBuilder(idData.getAuditEntityName(), alias2);
|
||||||
|
maxERevQb.addProjection("max", revisionPropertyPath, false);
|
||||||
|
// WHERE
|
||||||
|
Parameters maxERevQbParameters = maxERevQb.getRootParameters();
|
||||||
|
// e2.revision <= :revision
|
||||||
|
maxERevQbParameters.addWhereWithNamedParam(revisionPropertyPath, "<=", "revision");
|
||||||
|
// e2.id_ref_ed = e.id_ref_ed
|
||||||
|
idData.getOriginalMapper().addIdsEqualToQuery(maxERevQbParameters,
|
||||||
|
alias1 + "." + originalIdPropertyName, alias2 +"." + originalIdPropertyName);
|
||||||
|
|
||||||
|
// add subquery to rootParameters
|
||||||
|
String subqueryOperator = globalCfg.getCorrelatedSubqueryOperator();
|
||||||
|
rootParameters.addWhere(revisionProperty, addAlias, subqueryOperator, maxERevQb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAssociationAtRevisionRestriction(QueryBuilder rootQueryBuilder, String revisionProperty,
|
||||||
|
String revisionEndProperty, boolean addAlias, MiddleIdData referencingIdData, String versionsMiddleEntityName,
|
||||||
|
String eeOriginalIdPropertyPath, String revisionPropertyPath,
|
||||||
|
String originalIdPropertyName, MiddleComponentData... componentDatas) {
|
||||||
|
Parameters rootParameters = rootQueryBuilder.getRootParameters();
|
||||||
|
|
||||||
|
// SELECT max(ee2.revision) FROM middleEntity ee2
|
||||||
|
QueryBuilder maxEeRevQb = rootQueryBuilder.newSubQueryBuilder(versionsMiddleEntityName, "ee2");
|
||||||
|
maxEeRevQb.addProjection("max", revisionPropertyPath, false);
|
||||||
|
// WHERE
|
||||||
|
Parameters maxEeRevQbParameters = maxEeRevQb.getRootParameters();
|
||||||
|
// ee2.revision <= :revision
|
||||||
|
maxEeRevQbParameters.addWhereWithNamedParam(revisionPropertyPath, "<=", "revision");
|
||||||
|
// ee2.originalId.* = ee.originalId.*
|
||||||
|
String ee2OriginalIdPropertyPath = "ee2." + originalIdPropertyName;
|
||||||
|
referencingIdData.getPrefixedMapper().addIdsEqualToQuery(maxEeRevQbParameters, eeOriginalIdPropertyPath, ee2OriginalIdPropertyPath);
|
||||||
|
for (MiddleComponentData componentData : componentDatas) {
|
||||||
|
componentData.getComponentMapper().addMiddleEqualToQuery(maxEeRevQbParameters, eeOriginalIdPropertyPath, ee2OriginalIdPropertyPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add subquery to rootParameters
|
||||||
|
rootParameters.addWhere(revisionProperty, addAlias, "=", maxEeRevQb);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,12 @@ import org.hibernate.Session;
|
||||||
import org.hibernate.envers.RevisionType;
|
import org.hibernate.envers.RevisionType;
|
||||||
import org.hibernate.envers.configuration.AuditConfiguration;
|
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||||
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
||||||
|
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||||
import org.hibernate.envers.entities.mapper.PersistentCollectionChangeData;
|
import org.hibernate.envers.entities.mapper.PersistentCollectionChangeData;
|
||||||
import org.hibernate.envers.entities.mapper.id.IdMapper;
|
import org.hibernate.envers.entities.mapper.id.IdMapper;
|
||||||
|
import org.hibernate.envers.entities.mapper.relation.MiddleComponentData;
|
||||||
|
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.envers.tools.query.QueryBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -75,6 +79,32 @@ public class ValidTimeAuditStrategy implements AuditStrategy {
|
||||||
session.save(persistentCollectionChangeData.getEntityName(), persistentCollectionChangeData.getData());
|
session.save(persistentCollectionChangeData.getEntityName(), persistentCollectionChangeData.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addEntityAtRevisionRestriction(GlobalConfiguration globalCfg, QueryBuilder rootQueryBuilder,
|
||||||
|
String revisionProperty,String revisionEndProperty, boolean addAlias,
|
||||||
|
MiddleIdData idData, String revisionPropertyPath, String originalIdPropertyName,
|
||||||
|
String alias1, String alias2) {
|
||||||
|
Parameters rootParameters = rootQueryBuilder.getRootParameters();
|
||||||
|
addRevisionRestriction(rootParameters, revisionProperty, revisionEndProperty, addAlias);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAssociationAtRevisionRestriction(QueryBuilder rootQueryBuilder, String revisionProperty,
|
||||||
|
String revisionEndProperty, boolean addAlias, MiddleIdData referencingIdData,
|
||||||
|
String versionsMiddleEntityName, String eeOriginalIdPropertyPath, String revisionPropertyPath,
|
||||||
|
String originalIdPropertyName, MiddleComponentData... componentDatas) {
|
||||||
|
Parameters rootParameters = rootQueryBuilder.getRootParameters();
|
||||||
|
addRevisionRestriction(rootParameters, revisionProperty, revisionEndProperty, addAlias);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addRevisionRestriction(Parameters rootParameters,
|
||||||
|
String revisionProperty, String revisionEndProperty, boolean addAlias) {
|
||||||
|
|
||||||
|
// e.revision <= _revision and (e.endRevision > _revision or e.endRevision is null)
|
||||||
|
Parameters subParm = rootParameters.addSubParameters("or");
|
||||||
|
rootParameters.addWhereWithNamedParam(revisionProperty, addAlias, "<=", "revision");
|
||||||
|
subParm.addWhereWithNamedParam(revisionEndProperty + ".id", addAlias, ">", "revision");
|
||||||
|
subParm.addWhere(revisionEndProperty, addAlias, "is", "null", false);
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked"})
|
@SuppressWarnings({"unchecked"})
|
||||||
private RevisionType getRevisionType(AuditConfiguration auditCfg, Object data) {
|
private RevisionType getRevisionType(AuditConfiguration auditCfg, Object data) {
|
||||||
return (RevisionType) ((Map<String, Object>) data).get(auditCfg.getAuditEntCfg().getRevisionTypePropName());
|
return (RevisionType) ((Map<String, Object>) data).get(auditCfg.getAuditEntCfg().getRevisionTypePropName());
|
||||||
|
|
Loading…
Reference in New Issue