HHH-5580 - Naming and EntitiesModifiedAtRevisionQuery tests

This commit is contained in:
Lukasz Antoniak 2011-05-28 17:01:26 +02:00
parent 36e0d7eced
commit 4022571196
8 changed files with 90 additions and 11 deletions

View File

@ -253,8 +253,8 @@
</entry> </entry>
<entry> <entry>
Should entity types, that have been modified during each revision, be tracked. The default Should entity types, that have been modified during each revision, be tracked. The default
implementation creates <literal>REVENTITY</literal> table that stores fully qualified names implementation creates <literal>REVCHANGES</literal> table that stores fully qualified names
of Java classes changed in a specified revision. Single record encapsulates the revision of Java classes modified in a specified revision. Single record encapsulates the revision
identifier (foreign key to <literal>REVINFO</literal> table) and a string value. This identifier (foreign key to <literal>REVINFO</literal> table) and a string value. This
feature shall be used when entity name can be clearly identified by Java class type. Otherwise feature shall be used when entity name can be clearly identified by Java class type. Otherwise
extend <interfacename>org.hibernate.envers.EntityTrackingRevisionListener</interfacename> extend <interfacename>org.hibernate.envers.EntityTrackingRevisionListener</interfacename>
@ -470,8 +470,8 @@ public class ExampleListener implements RevisionListener {
<para> <para>
By default entity types that have been changed in each revision are not being tracked. This implies the 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 necessity to query all tables storing audited data in order to retrieve changes made during
specified revision. Envers provides a simple mechanism that creates <literal>REVENTITY</literal> specified revision. Envers provides a simple mechanism that creates <literal>REVCHANGES</literal>
table which stores fully qualified names of Java classes changed in each revision. table which stores fully qualified names of Java classes modified in each revision.
Single record encapsulates the revision identifier (foreign key to <literal>REVINFO</literal> table) Single record encapsulates the revision identifier (foreign key to <literal>REVINFO</literal> table)
and a string value. Note that this mechanism shall be used when entity name can be clearly identified and a string value. Note that this mechanism shall be used when entity name can be clearly identified
by Java class type. Otherwise extend <interfacename>org.hibernate.envers.EntityTrackingRevisionListener</interfacename> by Java class type. Otherwise extend <interfacename>org.hibernate.envers.EntityTrackingRevisionListener</interfacename>
@ -508,7 +508,7 @@ public class AnnotatedTrackingRevisionEntity {
... ...
@ElementCollection @ElementCollection
@JoinTable(name = "REVENTITY", joinColumns = @JoinColumn(name = "REV")) @JoinTable(name = "REVCHANGES", joinColumns = @JoinColumn(name = "REV"))
@Column(name = "ENTITYTYPE") @Column(name = "ENTITYTYPE")
@ModifiedEntityTypes @ModifiedEntityTypes
private Set<String> modifiedEntityTypes; private Set<String> modifiedEntityTypes;

View File

@ -16,7 +16,7 @@ import java.util.Set;
@MappedSuperclass @MappedSuperclass
public class DefaultTrackingModifiedTypesRevisionEntity extends DefaultRevisionEntity { public class DefaultTrackingModifiedTypesRevisionEntity extends DefaultRevisionEntity {
@ElementCollection(fetch = FetchType.EAGER) @ElementCollection(fetch = FetchType.EAGER)
@JoinTable(name = "REVENTITY", joinColumns = @JoinColumn(name = "REV")) @JoinTable(name = "REVCHANGES", joinColumns = @JoinColumn(name = "REV"))
@Column(name = "ENTITYTYPE") @Column(name = "ENTITYTYPE")
@Fetch(FetchMode.JOIN) @Fetch(FetchMode.JOIN)
@ModifiedEntityTypes @ModifiedEntityTypes

View File

@ -99,7 +99,7 @@ public class RevisionInfoConfiguration {
MetadataTools.addColumn(timestampProperty, "REVTSTMP", null, 0, 0, null, null, null, false); MetadataTools.addColumn(timestampProperty, "REVTSTMP", null, 0, 0, null, null, null, false);
if (globalCfg.isTrackEntitiesChangedInRevisionEnabled()) { if (globalCfg.isTrackEntitiesChangedInRevisionEnabled()) {
generateEntityTypesTrackingTableMapping(class_mapping, "modifiedEntityTypes", "REVENTITY", "REV", "ENTITYTYPE", "string"); generateEntityTypesTrackingTableMapping(class_mapping, "modifiedEntityTypes", "REVCHANGES", "REV", "ENTITYTYPE", "string");
} }
return document; return document;

View File

@ -79,11 +79,27 @@ public class AuditQueryCreator {
* In comparison to {@link #forEntitiesAtRevision(Class, String, Number)} this query will return an empty * 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. * 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 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. * @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 * @return A query for entities changed at a given revision, to which conditions can be added and which
* can then be executed. * can then be executed.
* @see #forEntitiesAtRevision(Class, String, Number) * @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) { public AuditQuery forEntitiesModifiedAtRevision(Class<?> c, Number revision) {
checkNotNull(revision, "Entity revision"); checkNotNull(revision, "Entity revision");
checkPositive(revision, "Entity revision"); checkPositive(revision, "Entity revision");

View File

@ -24,6 +24,12 @@ public class EntitiesModifiedAtRevisionQuery extends AbstractAuditQuery {
this.revision = revision; 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"}) @SuppressWarnings({"unchecked"})
public List list() { public List list() {
/* /*

View File

@ -24,7 +24,7 @@ public class AnnotatedTrackingRevisionEntity {
private long customTimestamp; private long customTimestamp;
@ElementCollection @ElementCollection
@JoinTable(name = "REVENTITY", joinColumns = @JoinColumn(name = "REV")) @JoinTable(name = "REVCHANGES", joinColumns = @JoinColumn(name = "REV"))
@Column(name = "ENTITYTYPE") @Column(name = "ENTITYTYPE")
@ModifiedEntityTypes @ModifiedEntityTypes
private Set<String> entityTypes; private Set<String> entityTypes;

View File

@ -31,6 +31,7 @@ import org.hibernate.envers.test.AbstractEntityTest;
import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.Priority;
import org.hibernate.envers.test.entities.StrIntTestEntity; import org.hibernate.envers.test.entities.StrIntTestEntity;
import org.hibernate.envers.test.tools.TestTools; import org.hibernate.envers.test.tools.TestTools;
import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
@ -40,6 +41,7 @@ import java.util.List;
/** /**
* @author Adam Warski (adam at warski dot org) * @author Adam Warski (adam at warski dot org)
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
*/ */
@SuppressWarnings({"unchecked"}) @SuppressWarnings({"unchecked"})
public class SimpleQuery extends AbstractEntityTest { public class SimpleQuery extends AbstractEntityTest {
@ -267,4 +269,59 @@ public class SimpleQuery extends AbstractEntityTest {
assert result.size() == 0; 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());
}
} }

View File

@ -68,7 +68,7 @@ public class DefaultTrackingEntitiesTest extends AbstractEntityTest {
Iterator<Table> tableIterator = getCfg().getTableMappings(); Iterator<Table> tableIterator = getCfg().getTableMappings();
while (tableIterator.hasNext()) { while (tableIterator.hasNext()) {
Table table = tableIterator.next(); Table table = tableIterator.next();
if ("REVENTITY".equals(table.getName())) { if ("REVCHANGES".equals(table.getName())) {
assert table.getColumnSpan() == 2; assert table.getColumnSpan() == 2;
assert table.getColumn(new Column("REV")) != null; assert table.getColumn(new Column("REV")) != null;
assert table.getColumn(new Column("ENTITYTYPE")) != null; assert table.getColumn(new Column("ENTITYTYPE")) != null;