diff --git a/documentation/src/main/docbook/devguide/en-US/Envers.xml b/documentation/src/main/docbook/devguide/en-US/Envers.xml index 14c666ec60..4755dba285 100644 --- a/documentation/src/main/docbook/devguide/en-US/Envers.xml +++ b/documentation/src/main/docbook/devguide/en-US/Envers.xml @@ -253,8 +253,8 @@ Should entity types, that have been modified during each revision, be tracked. The default - implementation creates REVENTITY table that stores fully qualified names - of Java classes changed in a specified revision. Single record encapsulates the revision + implementation creates REVCHANGES table that stores fully qualified names + of Java classes modified in a specified revision. Single record encapsulates the revision identifier (foreign key to REVINFO table) and a string value. This feature shall be used when entity name can be clearly identified by Java class type. Otherwise extend org.hibernate.envers.EntityTrackingRevisionListener @@ -470,8 +470,8 @@ public class ExampleListener implements RevisionListener { By default entity types that have been changed in each revision are not being tracked. This implies the necessity to query all tables storing audited data in order to retrieve changes made during - specified revision. Envers provides a simple mechanism that creates REVENTITY - table which stores fully qualified names of Java classes changed in each revision. + specified revision. Envers provides a simple mechanism that creates REVCHANGES + table which stores fully qualified names of Java classes modified in each revision. Single record encapsulates the revision identifier (foreign key to REVINFO table) and a string value. Note that this mechanism shall be used when entity name can be clearly identified by Java class type. Otherwise extend org.hibernate.envers.EntityTrackingRevisionListener @@ -508,7 +508,7 @@ public class AnnotatedTrackingRevisionEntity { ... @ElementCollection - @JoinTable(name = "REVENTITY", joinColumns = @JoinColumn(name = "REV")) + @JoinTable(name = "REVCHANGES", joinColumns = @JoinColumn(name = "REV")) @Column(name = "ENTITYTYPE") @ModifiedEntityTypes private Set modifiedEntityTypes; diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/DefaultTrackingModifiedTypesRevisionEntity.java b/hibernate-envers/src/main/java/org/hibernate/envers/DefaultTrackingModifiedTypesRevisionEntity.java index b9a03c7cc6..83b2706f14 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/DefaultTrackingModifiedTypesRevisionEntity.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/DefaultTrackingModifiedTypesRevisionEntity.java @@ -16,7 +16,7 @@ import java.util.Set; @MappedSuperclass public class DefaultTrackingModifiedTypesRevisionEntity extends DefaultRevisionEntity { @ElementCollection(fetch = FetchType.EAGER) - @JoinTable(name = "REVENTITY", joinColumns = @JoinColumn(name = "REV")) + @JoinTable(name = "REVCHANGES", joinColumns = @JoinColumn(name = "REV")) @Column(name = "ENTITYTYPE") @Fetch(FetchMode.JOIN) @ModifiedEntityTypes diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java index 0106fe2426..046c1dfe3e 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java @@ -99,7 +99,7 @@ public class RevisionInfoConfiguration { MetadataTools.addColumn(timestampProperty, "REVTSTMP", null, 0, 0, null, null, null, false); if (globalCfg.isTrackEntitiesChangedInRevisionEnabled()) { - generateEntityTypesTrackingTableMapping(class_mapping, "modifiedEntityTypes", "REVENTITY", "REV", "ENTITYTYPE", "string"); + generateEntityTypesTrackingTableMapping(class_mapping, "modifiedEntityTypes", "REVCHANGES", "REV", "ENTITYTYPE", "string"); } return document; diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/query/AuditQueryCreator.java b/hibernate-envers/src/main/java/org/hibernate/envers/query/AuditQueryCreator.java index 595d3bbb17..226eecf4e2 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/query/AuditQueryCreator.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/query/AuditQueryCreator.java @@ -79,11 +79,27 @@ public class AuditQueryCreator { * In comparison to {@link #forEntitiesAtRevision(Class, String, Number)} this query will return an empty * collection if an entity of a certain type has not been changed in a given revision. * @param c Class of the entities for which to query. + * @param entityName Name of the entity (if can't be guessed basing on the {@code c}). * @param revision Revision number at which to execute the query. * @return A query for entities changed at a given revision, to which conditions can be added and which * can then be executed. * @see #forEntitiesAtRevision(Class, String, Number) */ + public AuditQuery forEntitiesModifiedAtRevision(Class c, String entityName, Number revision) { + checkNotNull(revision, "Entity revision"); + checkPositive(revision, "Entity revision"); + return new EntitiesModifiedAtRevisionQuery(auditCfg, auditReaderImplementor, c, entityName, revision); + } + + /** + * In comparison to {@link #forEntitiesAtRevision(Class, Number)} this query will return an empty + * collection if an entity of a certain type has not been changed in a given revision. + * @param c Class of the entities for which to query. + * @param revision Revision number at which to execute the query. + * @return A query for entities changed at a given revision, to which conditions can be added and which + * can then be executed. + * @see #forEntitiesAtRevision(Class, Number) + */ public AuditQuery forEntitiesModifiedAtRevision(Class c, Number revision) { checkNotNull(revision, "Entity revision"); checkPositive(revision, "Entity revision"); diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/query/impl/EntitiesModifiedAtRevisionQuery.java b/hibernate-envers/src/main/java/org/hibernate/envers/query/impl/EntitiesModifiedAtRevisionQuery.java index 369fb85257..87fb6c87f5 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/query/impl/EntitiesModifiedAtRevisionQuery.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/query/impl/EntitiesModifiedAtRevisionQuery.java @@ -20,9 +20,15 @@ public class EntitiesModifiedAtRevisionQuery extends AbstractAuditQuery { public EntitiesModifiedAtRevisionQuery(AuditConfiguration verCfg, AuditReaderImplementor versionsReader, Class cls, Number revision) { - super(verCfg, versionsReader, cls); + super(verCfg, versionsReader, cls); this.revision = revision; - } + } + + public EntitiesModifiedAtRevisionQuery(AuditConfiguration verCfg, AuditReaderImplementor versionsReader, + Class cls, String entityName, Number revision) { + super(verCfg, versionsReader, cls, entityName); + this.revision = revision; + } @SuppressWarnings({"unchecked"}) public List list() { diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/reventity/trackmodifiedentities/AnnotatedTrackingRevisionEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/reventity/trackmodifiedentities/AnnotatedTrackingRevisionEntity.java index dde3e2730b..28086dd310 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/reventity/trackmodifiedentities/AnnotatedTrackingRevisionEntity.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/reventity/trackmodifiedentities/AnnotatedTrackingRevisionEntity.java @@ -24,7 +24,7 @@ public class AnnotatedTrackingRevisionEntity { private long customTimestamp; @ElementCollection - @JoinTable(name = "REVENTITY", joinColumns = @JoinColumn(name = "REV")) + @JoinTable(name = "REVCHANGES", joinColumns = @JoinColumn(name = "REV")) @Column(name = "ENTITYTYPE") @ModifiedEntityTypes private Set entityTypes; diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/SimpleQuery.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/SimpleQuery.java index 74b14731e9..5af474ffd2 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/SimpleQuery.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/query/SimpleQuery.java @@ -31,6 +31,7 @@ import org.hibernate.envers.test.AbstractEntityTest; import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.StrIntTestEntity; import org.hibernate.envers.test.tools.TestTools; +import org.junit.Assert; import org.junit.Test; import javax.persistence.EntityManager; @@ -40,6 +41,7 @@ import java.util.List; /** * @author Adam Warski (adam at warski dot org) + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ @SuppressWarnings({"unchecked"}) public class SimpleQuery extends AbstractEntityTest { @@ -267,4 +269,59 @@ public class SimpleQuery extends AbstractEntityTest { assert result.size() == 0; } + + @Test + public void testEntitiesAddedAtRevision() { + StrIntTestEntity site1 = new StrIntTestEntity("a", 10, id1); + StrIntTestEntity site2 = new StrIntTestEntity("a", 10, id2); + StrIntTestEntity site3 = new StrIntTestEntity("b", 5, id3); + + List result = getAuditReader().createQuery().forEntitiesModifiedAtRevision(StrIntTestEntity.class, StrIntTestEntity.class.getName(), 1).getResultList(); + RevisionType revisionType = (RevisionType) getAuditReader().createQuery().forEntitiesModifiedAtRevision(StrIntTestEntity.class, 1) + .addProjection(AuditEntity.revisionType()).add(AuditEntity.id().eq(id1)) + .getSingleResult(); + + Assert.assertTrue(TestTools.checkList(result, site1, site2, site3)); + Assert.assertEquals(revisionType, RevisionType.ADD); + } + + @Test + public void testEntitiesChangedAtRevision() { + StrIntTestEntity site1 = new StrIntTestEntity("c", 10, id1); + StrIntTestEntity site2 = new StrIntTestEntity("a", 20, id2); + + List result = getAuditReader().createQuery().forEntitiesModifiedAtRevision(StrIntTestEntity.class, 2).getResultList(); + RevisionType revisionType = (RevisionType) getAuditReader().createQuery().forEntitiesModifiedAtRevision(StrIntTestEntity.class, 2) + .addProjection(AuditEntity.revisionType()).add(AuditEntity.id().eq(id1)) + .getSingleResult(); + + Assert.assertTrue(TestTools.checkList(result, site1, site2)); + Assert.assertEquals(revisionType, RevisionType.MOD); + } + + @Test + public void testEntitiesRemovedAtRevision() { + StrIntTestEntity site1 = new StrIntTestEntity(null, null, id1); + + List result = getAuditReader().createQuery().forEntitiesModifiedAtRevision(StrIntTestEntity.class, 4).getResultList(); + RevisionType revisionType = (RevisionType) getAuditReader().createQuery().forEntitiesModifiedAtRevision(StrIntTestEntity.class, 4) + .addProjection(AuditEntity.revisionType()).add(AuditEntity.id().eq(id1)) + .getSingleResult(); + + Assert.assertTrue(TestTools.checkList(result, site1)); + Assert.assertEquals(revisionType, RevisionType.DEL); + } + + @Test + public void testEntityNotModifiedAtRevision() { + List result = getAuditReader().createQuery().forEntitiesModifiedAtRevision(StrIntTestEntity.class, 3) + .add(AuditEntity.id().eq(id1)).getResultList(); + Assert.assertTrue(result.isEmpty()); + } + + @Test + public void testNoEntitiesModifiedAtRevision() { + List result = getAuditReader().createQuery().forEntitiesModifiedAtRevision(StrIntTestEntity.class, 5).getResultList(); + Assert.assertTrue(result.isEmpty()); + } } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/trackmodifiedentities/DefaultTrackingEntitiesTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/trackmodifiedentities/DefaultTrackingEntitiesTest.java index 6e6b6b59e2..df28c9b7a9 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/trackmodifiedentities/DefaultTrackingEntitiesTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/trackmodifiedentities/DefaultTrackingEntitiesTest.java @@ -68,7 +68,7 @@ public class DefaultTrackingEntitiesTest extends AbstractEntityTest { Iterator tableIterator = getCfg().getTableMappings(); while (tableIterator.hasNext()) { Table table = tableIterator.next(); - if ("REVENTITY".equals(table.getName())) { + if ("REVCHANGES".equals(table.getName())) { assert table.getColumnSpan() == 2; assert table.getColumn(new Column("REV")) != null; assert table.getColumn(new Column("ENTITYTYPE")) != null;