[hibernate-commits] Hibernate SVN: r20315 - in core/trunk/envers/src/main/java/org/hibernate/envers: configuration/metadata and 3 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Tue Sep 7 09:52:39 EDT 2010


Author: adamw
Date: 2010-09-07 09:52:38 -0400 (Tue, 07 Sep 2010)
New Revision: 20315

Removed:
   core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/QueryGeneratorTools.java
Modified:
   core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java
   core/trunk/envers/src/main/java/org/hibernate/envers/configuration/EntitiesConfigurator.java
   core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java
   core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/CollectionMetadataGenerator.java
   core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/QueryGeneratorBuilder.java
   core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/OneAuditEntityQueryGenerator.java
   core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/OneEntityQueryGenerator.java
   core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/ThreeEntityQueryGenerator.java
   core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/TwoEntityOneAuditedQueryGenerator.java
   core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/TwoEntityQueryGenerator.java
   core/trunk/envers/src/main/java/org/hibernate/envers/query/impl/AbstractAuditQuery.java
   core/trunk/envers/src/main/java/org/hibernate/envers/query/impl/EntitiesAtRevisionQuery.java
   core/trunk/envers/src/main/java/org/hibernate/envers/strategy/AuditStrategy.java
   core/trunk/envers/src/main/java/org/hibernate/envers/strategy/DefaultAuditStrategy.java
   core/trunk/envers/src/main/java/org/hibernate/envers/strategy/ValidTimeAuditStrategy.java
Log:
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.

Modified: core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java	2010-09-07 07:33:33 UTC (rev 20314)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java	2010-09-07 13:52:38 UTC (rev 20315)
@@ -83,7 +83,7 @@
     public AuditConfiguration(Configuration cfg) {
         Properties properties = cfg.getProperties();
 
-        ReflectionManager reflectionManager = ((AnnotationConfiguration) cfg).getReflectionManager();
+        ReflectionManager reflectionManager = cfg.getReflectionManager();
         RevisionInfoConfiguration revInfoCfg = new RevisionInfoConfiguration();
         RevisionInfoConfigurationResult revInfoCfgResult = revInfoCfg.configure(cfg, reflectionManager);
         auditEntCfg = new AuditEntitiesConfiguration(properties, revInfoCfgResult.getRevisionInfoEntityName());
@@ -99,7 +99,7 @@
         
         revisionInfoQueryCreator = revInfoCfgResult.getRevisionInfoQueryCreator();
         revisionInfoNumberReader = revInfoCfgResult.getRevisionInfoNumberReader();
-        entCfg = new EntitiesConfigurator().configure(cfg, reflectionManager, globalCfg, auditEntCfg,
+        entCfg = new EntitiesConfigurator().configure(cfg, reflectionManager, globalCfg, auditEntCfg, auditStrategy,
                 revInfoCfgResult.getRevisionInfoXmlMapping(), revInfoCfgResult.getRevisionInfoRelationMapping());
     }
 

Modified: core/trunk/envers/src/main/java/org/hibernate/envers/configuration/EntitiesConfigurator.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/configuration/EntitiesConfigurator.java	2010-09-07 07:33:33 UTC (rev 20314)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/configuration/EntitiesConfigurator.java	2010-09-07 13:52:38 UTC (rev 20315)
@@ -43,6 +43,7 @@
 import org.hibernate.envers.configuration.metadata.AuditMetadataGenerator;
 import org.hibernate.envers.configuration.metadata.AuditEntityNameRegister;
 import org.hibernate.envers.entities.EntitiesConfigurations;
+import org.hibernate.envers.strategy.AuditStrategy;
 import org.hibernate.envers.tools.StringTools;
 import org.hibernate.envers.tools.graph.GraphTopologicalSort;
 
@@ -57,6 +58,7 @@
 public class EntitiesConfigurator {
     public EntitiesConfigurations configure(Configuration cfg, ReflectionManager reflectionManager,
                                             GlobalConfiguration globalCfg, AuditEntitiesConfiguration verEntCfg,
+                                            AuditStrategy auditStrategy,
                                             Document revisionInfoXmlMapping, Element revisionInfoRelationMapping) {
         // Creating a name register to capture all audit entity names created.
         AuditEntityNameRegister auditEntityNameRegister = new AuditEntityNameRegister();
@@ -83,7 +85,7 @@
         // Now that all information is read we can update the calculated fields.
         classesAuditingData.updateCalculatedFields();
 
-        AuditMetadataGenerator auditMetaGen = new AuditMetadataGenerator(cfg, globalCfg, verEntCfg,
+        AuditMetadataGenerator auditMetaGen = new AuditMetadataGenerator(cfg, globalCfg, verEntCfg, auditStrategy,
                 revisionInfoRelationMapping, auditEntityNameRegister);
 
         // First pass

Modified: core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java	2010-09-07 07:33:33 UTC (rev 20314)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java	2010-09-07 13:52:38 UTC (rev 20315)
@@ -28,6 +28,7 @@
 import java.util.Map;
 
 import org.dom4j.Element;
+import org.hibernate.envers.configuration.AuditConfiguration;
 import org.hibernate.envers.configuration.GlobalConfiguration;
 import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
 import org.hibernate.envers.configuration.metadata.reader.ClassAuditingData;
@@ -38,6 +39,7 @@
 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.AuditStrategy;
 import org.hibernate.envers.strategy.ValidTimeAuditStrategy;
 import org.hibernate.envers.tools.StringTools;
 import org.hibernate.envers.tools.Triple;
@@ -63,6 +65,7 @@
     private final Configuration cfg;
     private final GlobalConfiguration globalCfg;
     private final AuditEntitiesConfiguration verEntCfg;
+    private final AuditStrategy auditStrategy;
     private final Element revisionInfoRelationMapping;
 
     /*
@@ -86,11 +89,13 @@
 
     public AuditMetadataGenerator(Configuration cfg, GlobalConfiguration globalCfg,
                                   AuditEntitiesConfiguration verEntCfg,
+                                  AuditStrategy auditStrategy,
                                   Element revisionInfoRelationMapping,
                                   AuditEntityNameRegister auditEntityNameRegister) {
         this.cfg = cfg;
         this.globalCfg = globalCfg;
         this.verEntCfg = verEntCfg;
+        this.auditStrategy = auditStrategy;
         this.revisionInfoRelationMapping = revisionInfoRelationMapping;
 
         this.basicMetadataGenerator = new BasicMetadataGenerator();
@@ -490,6 +495,10 @@
         return verEntCfg;
     }
 
+    AuditStrategy getAuditStrategy() {
+        return auditStrategy;
+    }
+
     AuditEntityNameRegister getAuditEntityNameRegister() {
         return auditEntityNameRegister;
     }

Modified: core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/CollectionMetadataGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/CollectionMetadataGenerator.java	2010-09-07 07:33:33 UTC (rev 20314)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/CollectionMetadataGenerator.java	2010-09-07 13:52:38 UTC (rev 20315)
@@ -32,9 +32,11 @@
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.TreeSet;
+
 import javax.persistence.JoinColumn;
 
 import org.dom4j.Element;
+import org.hibernate.MappingException;
 import org.hibernate.envers.ModificationStore;
 import org.hibernate.envers.RelationTargetAuditMode;
 import org.hibernate.envers.configuration.metadata.reader.PropertyAuditingData;
@@ -45,8 +47,19 @@
 import org.hibernate.envers.entities.mapper.PropertyMapper;
 import org.hibernate.envers.entities.mapper.SinglePropertyMapper;
 import org.hibernate.envers.entities.mapper.id.IdMapper;
-import org.hibernate.envers.entities.mapper.relation.*;
-import org.hibernate.envers.entities.mapper.relation.component.*;
+import org.hibernate.envers.entities.mapper.relation.BasicCollectionMapper;
+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.MapProxy;
 import org.hibernate.envers.entities.mapper.relation.lazy.proxy.SetProxy;
@@ -54,11 +67,9 @@
 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.RelationQueryGenerator;
+import org.hibernate.envers.tools.MappingTools;
 import org.hibernate.envers.tools.StringTools;
 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.IndexedCollection;
 import org.hibernate.mapping.OneToMany;
@@ -184,8 +195,8 @@
 
         // Generating the query generator - it should read directly from the related entity.
         RelationQueryGenerator queryGenerator = new OneAuditEntityQueryGenerator(mainGenerator.getGlobalCfg(),
-                mainGenerator.getVerEntCfg(), referencingIdData, referencedEntityName,
-                referencedIdMapping.getIdMapper());
+                mainGenerator.getVerEntCfg(), mainGenerator.getAuditStrategy(),
+                referencingIdData, referencedEntityName, referencedIdData);
 
         // Creating common mapper data.
         CommonCollectionMapperData commonCollectionMapperData = new CommonCollectionMapperData(
@@ -332,8 +343,9 @@
         // 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
         // a query generator to read the raw data collection from the middle table.
-        QueryGeneratorBuilder queryGeneratorBuilder = new QueryGeneratorBuilder(mainGenerator.getGlobalCfg(),
-                mainGenerator.getVerEntCfg(), referencingIdData, auditMiddleEntityName);
+		QueryGeneratorBuilder queryGeneratorBuilder = new QueryGeneratorBuilder(mainGenerator.getGlobalCfg(),
+                mainGenerator.getVerEntCfg(), mainGenerator.getAuditStrategy(), referencingIdData,
+				auditMiddleEntityName);
 
         // Adding the XML mapping for the referencing entity, if the relation isn't inverse.
         if (middleEntityXml != null) {

Modified: core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/QueryGeneratorBuilder.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/QueryGeneratorBuilder.java	2010-09-07 07:33:33 UTC (rev 20314)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/QueryGeneratorBuilder.java	2010-09-07 13:52:38 UTC (rev 20315)
@@ -26,12 +26,17 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.hibernate.MappingException;
+import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
 import org.hibernate.envers.configuration.GlobalConfiguration;
-import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
 import org.hibernate.envers.entities.mapper.relation.MiddleComponentData;
 import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
-import org.hibernate.envers.entities.mapper.relation.query.*;
-import org.hibernate.MappingException;
+import org.hibernate.envers.entities.mapper.relation.query.OneEntityQueryGenerator;
+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.
@@ -41,14 +46,17 @@
 public final class QueryGeneratorBuilder {
     private final GlobalConfiguration globalCfg;
     private final AuditEntitiesConfiguration verEntCfg;
+    private final AuditStrategy auditStrategy;
     private final MiddleIdData referencingIdData;
     private final String auditMiddleEntityName;
     private final List<MiddleIdData> idDatas;
 
     QueryGeneratorBuilder(GlobalConfiguration globalCfg, AuditEntitiesConfiguration verEntCfg,
+                          AuditStrategy auditStrategy,
                           MiddleIdData referencingIdData, String auditMiddleEntityName) {
         this.globalCfg = globalCfg;
         this.verEntCfg = verEntCfg;
+        this.auditStrategy = auditStrategy;
         this.referencingIdData = referencingIdData;
         this.auditMiddleEntityName = auditMiddleEntityName;
 
@@ -61,14 +69,14 @@
 
     RelationQueryGenerator build(MiddleComponentData... componentDatas) {
         if (idDatas.size() == 0) {
-            return new OneEntityQueryGenerator(verEntCfg, auditMiddleEntityName, referencingIdData,
+            return new OneEntityQueryGenerator(verEntCfg, auditStrategy, auditMiddleEntityName, referencingIdData,
                     componentDatas);
         } else if (idDatas.size() == 1) {
             if (idDatas.get(0).isAudited()) {
-                return new TwoEntityQueryGenerator(globalCfg, verEntCfg, auditMiddleEntityName, referencingIdData,
+                return new TwoEntityQueryGenerator(globalCfg, verEntCfg, auditStrategy, auditMiddleEntityName, referencingIdData,
                         idDatas.get(0), componentDatas);
             } else {
-                return new TwoEntityOneAuditedQueryGenerator(verEntCfg, auditMiddleEntityName, referencingIdData,
+                return new TwoEntityOneAuditedQueryGenerator(verEntCfg, auditStrategy, auditMiddleEntityName, referencingIdData,
                         idDatas.get(0), componentDatas);
             }
         } else if (idDatas.size() == 2) {
@@ -77,7 +85,7 @@
                 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);
         } else {
             throw new IllegalStateException("Illegal number of related entities.");

Modified: core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/OneAuditEntityQueryGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/OneAuditEntityQueryGenerator.java	2010-09-07 07:33:33 UTC (rev 20314)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/OneAuditEntityQueryGenerator.java	2010-09-07 13:52:38 UTC (rev 20315)
@@ -25,18 +25,17 @@
 
 import java.util.Collections;
 
+import org.hibernate.Query;
 import org.hibernate.envers.RevisionType;
-import org.hibernate.envers.configuration.GlobalConfiguration;
 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.relation.MiddleIdData;
 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.QueryBuilder;
 
-import org.hibernate.Query;
-
 /**
  * Selects data from an audit entity.
  * @author Adam Warski (adam at warski dot org)
@@ -45,9 +44,10 @@
     private final String queryString;
     private final MiddleIdData referencingIdData;
 
-    public OneAuditEntityQueryGenerator(GlobalConfiguration globalCfg, AuditEntitiesConfiguration verEntCfg,
-                                           MiddleIdData referencingIdData, String referencedEntityName,
-                                           IdMapper referencedIdMapper) {
+    public OneAuditEntityQueryGenerator(GlobalConfiguration globalCfg, AuditEntitiesConfiguration verEntCfg, 
+                                        AuditStrategy auditStrategy,
+                                        MiddleIdData referencingIdData,
+                                        String referencedEntityName, MiddleIdData referencedIdData) {
         this.referencingIdData = referencingIdData;
 
         /*
@@ -57,8 +57,14 @@
          * (only entities referenced by the association; id_ref_ing = id of the referencing entity)
          *     e.id_ref_ing = :id_ref_ing AND
          * (selecting e entities at revision :revision)
+         *   --> for DefaultAuditStrategy:
          *     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)
          *     e.revision_type != DEL
          */
@@ -75,20 +81,12 @@
         // e.id_ref_ed = :id_ref_ed
         referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, null, true);
 
-        // SELECT max(e.revision) FROM versionsReferencedEntity e2
-        QueryBuilder maxERevQb = qb.newSubQueryBuilder(versionsReferencedEntityName, "e2");
-        maxERevQb.addProjection("max", revisionPropertyPath, false);
-        // WHERE
-        Parameters maxERevQbParameters = maxERevQb.getRootParameters();
-        // e2.revision <= :revision
-        maxERevQbParameters.addWhereWithNamedParam(revisionPropertyPath, "<=", "revision");
-        // e2.id = e.id
-        referencedIdMapper.addIdsEqualToQuery(maxERevQbParameters,
-                "e." + originalIdPropertyName, "e2." + originalIdPropertyName);
+        // (selecting e entities at revision :revision)
+        // --> based on auditStrategy (see above)
+        auditStrategy.addEntityAtRevisionRestriction(globalCfg, qb, revisionPropertyPath,
+        		verEntCfg.getRevisionEndFieldName(), true, referencedIdData, 
+				revisionPropertyPath, originalIdPropertyName, "e", "e2");
 
-        // e.revision = (SELECT max(...) ...)
-        rootParameters.addWhere(revisionPropertyPath, false, globalCfg.getCorrelatedSubqueryOperator(), maxERevQb);
-
         // e.revision_type != DEL
         rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), false, "!=", "delrevisiontype");
 
@@ -107,4 +105,4 @@
 
         return query;
     }
-}
\ No newline at end of file
+}

Modified: core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/OneEntityQueryGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/OneEntityQueryGenerator.java	2010-09-07 07:33:33 UTC (rev 20314)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/OneEntityQueryGenerator.java	2010-09-07 13:52:38 UTC (rev 20315)
@@ -25,17 +25,17 @@
 
 import java.util.Collections;
 
+import org.hibernate.Query;
 import org.hibernate.envers.RevisionType;
 import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
 import org.hibernate.envers.entities.mapper.id.QueryParameterData;
 import org.hibernate.envers.entities.mapper.relation.MiddleComponentData;
 import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
 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.QueryBuilder;
 
-import org.hibernate.Query;
-
 /**
  * Selects data from a relation middle-table only.
  * @author Adam Warski (adam at warski dot org)
@@ -45,6 +45,7 @@
     private final MiddleIdData referencingIdData;
 
     public OneEntityQueryGenerator(AuditEntitiesConfiguration verEntCfg,
+                                   AuditStrategy auditStrategy,
                                    String versionsMiddleEntityName,
                                    MiddleIdData referencingIdData,
                                    MiddleComponentData... componentDatas) {
@@ -55,9 +56,17 @@
          *   SELECT new list(ee) FROM middleEntity ee WHERE
          * (only entities referenced by the association; id_ref_ing = id of the referencing entity)
          *     ee.originalId.id_ref_ing = :id_ref_ing AND
+         *     
          * (the association at revision :revision)
+         *   --> for DefaultAuditStrategy:
          *     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)
          *     ee.revision_type != DEL
          */
@@ -71,22 +80,15 @@
         Parameters rootParameters = qb.getRootParameters();
         // ee.originalId.id_ref_ing = :id_ref_ing
         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 ee2OriginalIdPropertyPath = "ee2." + originalIdPropertyName;
-        referencingIdData.getPrefixedMapper().addIdsEqualToQuery(maxRevQbParameters, eeOriginalIdPropertyPath, ee2OriginalIdPropertyPath);
-        for (MiddleComponentData componentData : componentDatas) {
-            componentData.getComponentMapper().addMiddleEqualToQuery(maxRevQbParameters, eeOriginalIdPropertyPath, ee2OriginalIdPropertyPath);
-        }
-        // ee.revision = (SELECT max(...) ...)
-        rootParameters.addWhere(revisionPropertyPath, "=", maxRevQb);       
+
+        // (with ee association at revision :revision)
+        // --> based on auditStrategy (see above)
+        auditStrategy.addAssociationAtRevisionRestriction(qb, revisionPropertyPath,
+         		verEntCfg.getRevisionEndFieldName(), true,referencingIdData, versionsMiddleEntityName, 
+         		eeOriginalIdPropertyPath, revisionPropertyPath, originalIdPropertyName, componentDatas);
+         
         // ee.revision_type != DEL
         rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), "!=", "delrevisiontype");
 

Deleted: core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/QueryGeneratorTools.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/QueryGeneratorTools.java	2010-09-07 07:33:33 UTC (rev 20314)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/QueryGeneratorTools.java	2010-09-07 13:52:38 UTC (rev 20315)
@@ -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);
-    }
-}

Modified: core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/ThreeEntityQueryGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/ThreeEntityQueryGenerator.java	2010-09-07 07:33:33 UTC (rev 20314)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/ThreeEntityQueryGenerator.java	2010-09-07 13:52:38 UTC (rev 20315)
@@ -25,18 +25,18 @@
 
 import java.util.Collections;
 
+import org.hibernate.Query;
 import org.hibernate.envers.RevisionType;
+import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
 import org.hibernate.envers.configuration.GlobalConfiguration;
-import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
 import org.hibernate.envers.entities.mapper.id.QueryParameterData;
 import org.hibernate.envers.entities.mapper.relation.MiddleComponentData;
 import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
 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.QueryBuilder;
 
-import org.hibernate.Query;
-
 /**
  * Selects data from a relation middle-table and a two related versions entity.
  * @author Adam Warski (adam at warski dot org)
@@ -47,6 +47,7 @@
 
     public ThreeEntityQueryGenerator(GlobalConfiguration globalCfg,
                                      AuditEntitiesConfiguration verEntCfg,
+                                     AuditStrategy auditStrategy,
                                      String versionsMiddleEntityName,
                                      MiddleIdData referencingIdData,
                                      MiddleIdData referencedIdData,
@@ -65,14 +66,48 @@
          * (only entities referenced by the association; id_ref_ing = id of the referencing entity)
          *     ee.id_ref_ing = :id_ref_ing AND
          * (selecting e entities at revision :revision)
+         *   --> for DefaultAuditStrategy:
          *     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)
+         *   --> for DefaultAuditStrategy:
          *     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)
+         *   --> for DefaultAuditStrategy:
          *     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)
          *     ee.revision_type != DEL AND
          *     e.revision_type != DEL AND
@@ -80,7 +115,6 @@
          */
         String revisionPropertyPath = verEntCfg.getRevisionNumberPath();
         String originalIdPropertyName = verEntCfg.getOriginalIdPropName();
-
         String eeOriginalIdPropertyPath = "ee." + originalIdPropertyName;
 
         // SELECT new list(ee) FROM middleEntity ee
@@ -99,18 +133,24 @@
         // ee.originalId.id_ref_ing = :id_ref_ing
         referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, originalIdPropertyName, true);
 
-        // e.revision = (SELECT max(...) ...)
-        QueryGeneratorTools.addEntityAtRevision(globalCfg, qb, rootParameters, referencedIdData, revisionPropertyPath,
-                originalIdPropertyName, "e", "e2");
+        // (selecting e entities at revision :revision)
+        // --> based on auditStrategy (see above)
+        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(...) ...)
-        QueryGeneratorTools.addEntityAtRevision(globalCfg, qb, rootParameters, indexIdData, revisionPropertyPath,
-                originalIdPropertyName, "f", "f2");
+        // (with ee association at revision :revision)
+        // --> based on auditStrategy (see above)
+        auditStrategy.addAssociationAtRevisionRestriction(qb, revisionPropertyPath,
+        		verEntCfg.getRevisionEndFieldName(), true, referencingIdData, versionsMiddleEntityName,
+        		eeOriginalIdPropertyPath, revisionPropertyPath, originalIdPropertyName, componentDatas);
 
-        // ee.revision = (SELECT max(...) ...)
-        QueryGeneratorTools.addAssociationAtRevision(qb, rootParameters, referencingIdData, versionsMiddleEntityName,
-                eeOriginalIdPropertyPath, revisionPropertyPath, originalIdPropertyName, componentDatas);
-
         // ee.revision_type != DEL
         rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), "!=", "delrevisiontype");
         // e.revision_type != DEL

Modified: core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/TwoEntityOneAuditedQueryGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/TwoEntityOneAuditedQueryGenerator.java	2010-09-07 07:33:33 UTC (rev 20314)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/TwoEntityOneAuditedQueryGenerator.java	2010-09-07 13:52:38 UTC (rev 20315)
@@ -26,11 +26,14 @@
 import java.util.Collections;
 
 import org.hibernate.envers.RevisionType;
+import org.hibernate.envers.configuration.AuditConfiguration;
 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.relation.MiddleComponentData;
 import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
 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.QueryBuilder;
 
@@ -44,8 +47,7 @@
     private final String queryString;
     private final MiddleIdData referencingIdData;
 
-    public TwoEntityOneAuditedQueryGenerator(
-                                   AuditEntitiesConfiguration verEntCfg,
+    public TwoEntityOneAuditedQueryGenerator(AuditEntitiesConfiguration verEntCfg, AuditStrategy auditStrategy,
                                    String versionsMiddleEntityName,
                                    MiddleIdData referencingIdData,
                                    MiddleIdData referencedIdData,
@@ -60,9 +62,17 @@
          *     ee.id_ref_ed = e.id_ref_ed AND
          * (only entities referenced by the association; id_ref_ing = id of the referencing entity)
          *     ee.id_ref_ing = :id_ref_ing AND
+         *     
          * (the association at revision :revision)
+         *   --> for DefaultAuditStrategy:
          *     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)
          *     ee.revision_type != DEL
          */
@@ -83,9 +93,11 @@
         // ee.originalId.id_ref_ing = :id_ref_ing
         referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, originalIdPropertyName, true);
 
-        // ee.revision = (SELECT max(...) ...)
-        QueryGeneratorTools.addAssociationAtRevision(qb, rootParameters, referencingIdData, versionsMiddleEntityName,
-                eeOriginalIdPropertyPath, revisionPropertyPath, originalIdPropertyName, componentDatas);
+        // (with ee association at revision :revision)
+        // --> based on auditStrategy (see above)
+        auditStrategy.addAssociationAtRevisionRestriction(qb, revisionPropertyPath,
+        		verEntCfg.getRevisionEndFieldName(), true,referencingIdData, versionsMiddleEntityName,
+        		eeOriginalIdPropertyPath, revisionPropertyPath, originalIdPropertyName, componentDatas);
 
         // ee.revision_type != DEL
         rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), "!=", "delrevisiontype");
@@ -105,4 +117,4 @@
 
         return query;
     }
-}
\ No newline at end of file
+}

Modified: core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/TwoEntityQueryGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/TwoEntityQueryGenerator.java	2010-09-07 07:33:33 UTC (rev 20314)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/query/TwoEntityQueryGenerator.java	2010-09-07 13:52:38 UTC (rev 20315)
@@ -25,18 +25,18 @@
 
 import java.util.Collections;
 
+import org.hibernate.Query;
 import org.hibernate.envers.RevisionType;
+import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
 import org.hibernate.envers.configuration.GlobalConfiguration;
-import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
 import org.hibernate.envers.entities.mapper.id.QueryParameterData;
 import org.hibernate.envers.entities.mapper.relation.MiddleComponentData;
 import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
 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.QueryBuilder;
 
-import org.hibernate.Query;
-
 /**
  * Selects data from a relation middle-table and a related versions entity.
  * @author Adam Warski (adam at warski dot org)
@@ -47,6 +47,7 @@
 
     public TwoEntityQueryGenerator(GlobalConfiguration globalCfg,
                                    AuditEntitiesConfiguration verEntCfg,
+                                   AuditStrategy auditStrategy,
                                    String versionsMiddleEntityName,
                                    MiddleIdData referencingIdData,
                                    MiddleIdData referencedIdData,
@@ -61,12 +62,25 @@
          *     ee.id_ref_ed = e.id_ref_ed AND
          * (only entities referenced by the association; id_ref_ing = id of the referencing entity)
          *     ee.id_ref_ing = :id_ref_ing AND
+         *     
          * (selecting e entities at revision :revision)
+         *   --> for DefaultAuditStrategy:
          *     e.revision = (SELECT max(e2.revision) FROM versionsReferencedEntity e2
-         *       WHERE e2.revision <= :revision AND e2.id_ref_ed = e.id_ref_ed) AND
-         * (the association at revision :revision)
+         *       WHERE e2.revision <= :revision AND e2.id = e.id) 
+         *     
+         *   --> 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
-         *       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)
          *     ee.revision_type != DEL AND
          *     e.revision_type != DEL
@@ -88,13 +102,17 @@
         // ee.originalId.id_ref_ing = :id_ref_ing
         referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, originalIdPropertyName, true);
 
-        // e.revision = (SELECT max(...) ...)
-        QueryGeneratorTools.addEntityAtRevision(globalCfg, qb, rootParameters, referencedIdData, revisionPropertyPath,
-                originalIdPropertyName, "e", "e2");
+        // (selecting e entities at revision :revision)
+        // --> based on auditStrategy (see above)
+        auditStrategy.addEntityAtRevisionRestriction(globalCfg, qb, "e." + revisionPropertyPath,
+        		"e." + verEntCfg.getRevisionEndFieldName(), false,
+        		referencedIdData, revisionPropertyPath, originalIdPropertyName, "e", "e2");
 
-        // ee.revision = (SELECT max(...) ...)
-        QueryGeneratorTools.addAssociationAtRevision(qb, rootParameters, referencingIdData, versionsMiddleEntityName,
-                eeOriginalIdPropertyPath, revisionPropertyPath, originalIdPropertyName, componentDatas);
+        // (with ee association at revision :revision)
+        // --> based on auditStrategy (see above)
+        auditStrategy.addAssociationAtRevisionRestriction(qb, revisionPropertyPath,
+        		verEntCfg.getRevisionEndFieldName(), true, referencingIdData, versionsMiddleEntityName,
+        		eeOriginalIdPropertyPath, revisionPropertyPath, originalIdPropertyName, componentDatas);
 
         // ee.revision_type != DEL
         rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), "!=", "delrevisiontype");

Modified: core/trunk/envers/src/main/java/org/hibernate/envers/query/impl/AbstractAuditQuery.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/query/impl/AbstractAuditQuery.java	2010-09-07 07:33:33 UTC (rev 20314)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/query/impl/AbstractAuditQuery.java	2010-09-07 13:52:38 UTC (rev 20315)
@@ -86,10 +86,14 @@
 		qb = new QueryBuilder(versionsEntityName, "e");
 	}
     
-    protected List buildAndExecuteQuery() {
+    protected Query buildQuery() {
         Query query = qb.toQuery(versionsReader.getSession());
-
         setQueryProperties(query);
+        return query;
+    }
+    
+	protected List buildAndExecuteQuery() {
+        Query query = buildQuery();
 
         return query.list();
     }

Modified: core/trunk/envers/src/main/java/org/hibernate/envers/query/impl/EntitiesAtRevisionQuery.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/query/impl/EntitiesAtRevisionQuery.java	2010-09-07 07:33:33 UTC (rev 20314)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/query/impl/EntitiesAtRevisionQuery.java	2010-09-07 13:52:38 UTC (rev 20315)
@@ -24,14 +24,16 @@
 package org.hibernate.envers.query.impl;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
+import org.hibernate.Query;
 import org.hibernate.envers.RevisionType;
 import org.hibernate.envers.configuration.AuditConfiguration;
 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.reader.AuditReaderImplementor;
-import org.hibernate.envers.tools.query.QueryBuilder;
 
 /**
  * @author Adam Warski (adam at warski dot org)
@@ -56,40 +58,51 @@
     @SuppressWarnings({"unchecked"})
     public List list() {
         /*
-        The query that should be executed in the versions table:
-        SELECT e FROM ent_ver e WHERE
-          (all specified conditions, transformed, on the "e" entity) AND
-          e.revision_type != DEL AND
-          e.revision = (SELECT max(e2.revision) FROM ent_ver e2 WHERE
-            e2.revision <= :revision AND e2.originalId.id = e.originalId.id)
+         * The query that we need to create:
+         *   SELECT new list(e) FROM versionsReferencedEntity e
+         *   WHERE
+         * (all specified conditions, transformed, on the "e" entity) AND
+         * (selecting e entities at revision :revision)
+         *   --> 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();
-
         String revisionPropertyPath = verEntCfg.getRevisionNumberPath();
         String originalIdPropertyName = verEntCfg.getOriginalIdPropName();
 
-        // SELECT max(e2.revision)
-        maxRevQb.addProjection("max", revisionPropertyPath, false);
-        // e2.revision <= :revision
-        maxRevQb.getRootParameters().addWhereWithParam(revisionPropertyPath, "<=", revision);
-        // e2.id = e.id
-        verCfg.getEntCfg().get(entityName).getIdMapper().addIdsEqualToQuery(maxRevQb.getRootParameters(),
-                "e." + originalIdPropertyName, "e2." + originalIdPropertyName);
+        MiddleIdData referencedIdData = new MiddleIdData(verEntCfg, verCfg.getEntCfg().get(entityName).getIdMappingData(), 
+        		null, entityName, verCfg.getEntCfg().isVersioned(entityName));
 
-        // e.revision_type != DEL AND
-        qb.getRootParameters().addWhereWithParam(verEntCfg.getRevisionTypePropName(), "<>", RevisionType.DEL);
-        // e.revision = (SELECT max(...) ...)
-        qb.getRootParameters().addWhere(revisionPropertyPath, verCfg.getGlobalCfg().getCorrelatedSubqueryOperator(), maxRevQb);
+        // (selecting e entities at revision :revision)
+        // --> based on auditStrategy (see above)
+        verCfg.getAuditStrategy().addEntityAtRevisionRestriction(verCfg.getGlobalCfg(), qb, revisionPropertyPath, 
+        		verEntCfg.getRevisionEndFieldName(), true, referencedIdData, 
+				revisionPropertyPath, originalIdPropertyName, "e", "e2");
+        
+         // e.revision_type != DEL
+         qb.getRootParameters().addWhereWithParam(verEntCfg.getRevisionTypePropName(), "<>", RevisionType.DEL);
+
         // all specified conditions
         for (AuditCriterion criterion : criterions) {
             criterion.addToQuery(verCfg, entityName, qb, qb.getRootParameters());
         }
+        
+        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();
 
-        List queryResult = buildAndExecuteQuery();
-
         if (hasProjection) {
             return queryResult;
         } else {

Modified: core/trunk/envers/src/main/java/org/hibernate/envers/strategy/AuditStrategy.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/strategy/AuditStrategy.java	2010-09-07 07:33:33 UTC (rev 20314)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/strategy/AuditStrategy.java	2010-09-07 13:52:38 UTC (rev 20315)
@@ -1,11 +1,15 @@
 package org.hibernate.envers.strategy;
 
+import java.io.Serializable;
+
 import org.hibernate.Session;
 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.relation.MiddleComponentData;
+import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
+import org.hibernate.envers.tools.query.QueryBuilder;
 
-import java.io.Serializable;
-
 /**
  * Behaviours of different audit strategy for populating audit data.
  * 
@@ -36,4 +40,61 @@
      */
     void performCollectionChange(Session session, AuditConfiguration auditCfg,
                                  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);
+
 }

Modified: core/trunk/envers/src/main/java/org/hibernate/envers/strategy/DefaultAuditStrategy.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/strategy/DefaultAuditStrategy.java	2010-09-07 07:33:33 UTC (rev 20314)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/strategy/DefaultAuditStrategy.java	2010-09-07 13:52:38 UTC (rev 20315)
@@ -1,11 +1,16 @@
 package org.hibernate.envers.strategy;
 
+import java.io.Serializable;
+
 import org.hibernate.Session;
 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.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 java.io.Serializable;
-
 /**
  * Default strategy is to simply persist the audit data.
  *
@@ -22,4 +27,52 @@
                                         PersistentCollectionChangeData persistentCollectionChangeData, Object revision) {
         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);
+	}
+
 }

Modified: core/trunk/envers/src/main/java/org/hibernate/envers/strategy/ValidTimeAuditStrategy.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/strategy/ValidTimeAuditStrategy.java	2010-09-07 07:33:33 UTC (rev 20314)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/strategy/ValidTimeAuditStrategy.java	2010-09-07 13:52:38 UTC (rev 20315)
@@ -8,8 +8,12 @@
 import org.hibernate.envers.RevisionType;
 import org.hibernate.envers.configuration.AuditConfiguration;
 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.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;
 
 /**
@@ -75,6 +79,32 @@
         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"})
     private RevisionType getRevisionType(AuditConfiguration auditCfg, Object data) {
         return (RevisionType) ((Map<String, Object>) data).get(auditCfg.getAuditEntCfg().getRevisionTypePropName());



More information about the hibernate-commits mailing list