From 28dae5c9f3f78311aed3e264638f08702301449c Mon Sep 17 00:00:00 2001 From: Adam Warski Date: Sat, 4 Sep 2010 07:40:43 +0000 Subject: [PATCH] HHH-5499: Extend AuditReader interface with findRevisions() method Applying patch by Erik-Berndt Scheper - thanks! git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@20309 1b8cb986-b30d-0410-93ca-fae66ebed9b2 --- .../org/hibernate/envers/AuditReader.java | 21 +++++++ .../envers/reader/AuditReaderImpl.java | 59 +++++++++++++++---- .../RevisionInfoQueryCreator.java | 11 ++-- .../test/integration/reventity/Custom.java | 21 ++++++- .../integration/reventity/CustomBoxed.java | 23 +++++++- .../test/integration/reventity/Inherited.java | 21 ++++++- .../test/integration/reventity/Listener.java | 21 ++++++- .../integration/reventity/LongRevNumber.java | 23 +++++++- 8 files changed, 170 insertions(+), 30 deletions(-) diff --git a/envers/src/main/java/org/hibernate/envers/AuditReader.java b/envers/src/main/java/org/hibernate/envers/AuditReader.java index 267e7586a4..305d89c293 100644 --- a/envers/src/main/java/org/hibernate/envers/AuditReader.java +++ b/envers/src/main/java/org/hibernate/envers/AuditReader.java @@ -25,6 +25,8 @@ package org.hibernate.envers; import java.util.Date; import java.util.List; +import java.util.Map; +import java.util.Set; import org.hibernate.envers.exception.NotAuditedException; import org.hibernate.envers.exception.RevisionDoesNotExistException; @@ -133,6 +135,25 @@ public interface AuditReader { T findRevision(Class revisionEntityClass, Number revision) throws IllegalArgumentException, RevisionDoesNotExistException, IllegalStateException; + /** + * Find a map of revisions using the revision numbers specified. + * + * @param revisionEntityClass + * Class of the revision entity. Should be annotated with + * {@link RevisionEntity}. + * @param revisions + * Revision numbers of the revision for which to get the data. + * @return A map of revision number and the given revision entity. + * @throws IllegalArgumentException + * If a revision number is less or equal to 0 or if the class of + * the revision entity is invalid. + * @throws IllegalStateException + * If the associated entity manager is closed. + */ + Map findRevisions(Class revisionEntityClass, + Set revisions) throws IllegalArgumentException, + IllegalStateException; + /** * Gets an instance of the current revision entity, to which any entries in the audit tables will be bound. * Please note the if {@code persist} is {@code false}, and no audited entities are modified in this session, diff --git a/envers/src/main/java/org/hibernate/envers/reader/AuditReaderImpl.java b/envers/src/main/java/org/hibernate/envers/reader/AuditReaderImpl.java index 8be955a339..3296e9dfe3 100644 --- a/envers/src/main/java/org/hibernate/envers/reader/AuditReaderImpl.java +++ b/envers/src/main/java/org/hibernate/envers/reader/AuditReaderImpl.java @@ -23,26 +23,31 @@ */ package org.hibernate.envers.reader; -import java.util.Date; -import java.util.List; -import javax.persistence.NoResultException; - -import org.hibernate.envers.configuration.AuditConfiguration; -import org.hibernate.envers.exception.NotAuditedException; -import org.hibernate.envers.exception.RevisionDoesNotExistException; -import org.hibernate.envers.exception.AuditException; -import org.hibernate.envers.query.AuditEntity; -import org.hibernate.envers.query.AuditQueryCreator; import static org.hibernate.envers.tools.ArgumentsTools.checkNotNull; import static org.hibernate.envers.tools.ArgumentsTools.checkPositive; -import org.hibernate.envers.synchronization.AuditProcess; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.persistence.NoResultException; + +import org.hibernate.HibernateException; import org.hibernate.NonUniqueResultException; import org.hibernate.Query; import org.hibernate.Session; -import org.hibernate.event.EventSource; import org.hibernate.engine.SessionImplementor; +import org.hibernate.envers.configuration.AuditConfiguration; +import org.hibernate.envers.exception.AuditException; +import org.hibernate.envers.exception.NotAuditedException; +import org.hibernate.envers.exception.RevisionDoesNotExistException; +import org.hibernate.envers.query.AuditEntity; +import org.hibernate.envers.query.AuditQueryCreator; +import org.hibernate.envers.synchronization.AuditProcess; +import org.hibernate.event.EventSource; /** * @author Adam Warski (adam at warski dot org) @@ -190,7 +195,9 @@ public class AuditReaderImpl implements AuditReaderImplementor { checkPositive(revision, "Entity revision"); checkSession(); - Query query = verCfg.getRevisionInfoQueryCreator().getRevisionQuery(session, revision); + Set revisions = new HashSet(1); + revisions.add(revision); + Query query = verCfg.getRevisionInfoQueryCreator().getRevisionsQuery(session, revisions); try { T revisionData = (T) query.uniqueResult(); @@ -205,6 +212,32 @@ public class AuditReaderImpl implements AuditReaderImplementor { } } + @SuppressWarnings({"unchecked"}) + public Map findRevisions(Class revisionEntityClass, Set revisions) throws IllegalArgumentException, + IllegalStateException { + Map result = new HashMap(revisions.size()); + + for (Number revision : revisions) { + checkNotNull(revision, "Entity revision"); + checkPositive(revision, "Entity revision"); + } + checkSession(); + + Query query = verCfg.getRevisionInfoQueryCreator().getRevisionsQuery(session, revisions); + + try { + List revisionList = query.list(); + for (T revision : revisionList) { + Number revNo = verCfg.getRevisionInfoNumberReader().getRevisionNumber(revision); + result.put(revNo, revision); + } + + return result; + } catch (HibernateException e) { + throw new AuditException(e); + } + } + @SuppressWarnings({"unchecked"}) public T getCurrentRevision(Class revisionEntityClass, boolean persist) { if (!(session instanceof EventSource)) { diff --git a/envers/src/main/java/org/hibernate/envers/revisioninfo/RevisionInfoQueryCreator.java b/envers/src/main/java/org/hibernate/envers/revisioninfo/RevisionInfoQueryCreator.java index bfcf4a7174..e5df18ca99 100644 --- a/envers/src/main/java/org/hibernate/envers/revisioninfo/RevisionInfoQueryCreator.java +++ b/envers/src/main/java/org/hibernate/envers/revisioninfo/RevisionInfoQueryCreator.java @@ -24,6 +24,7 @@ package org.hibernate.envers.revisioninfo; import java.util.Date; +import java.util.Set; import org.hibernate.Query; import org.hibernate.Session; @@ -34,7 +35,7 @@ import org.hibernate.Session; public class RevisionInfoQueryCreator { private final String revisionDateQuery; private final String revisionNumberForDateQuery; - private final String revisionQuery; + private final String revisionsQuery; private final boolean timestampAsDate; public RevisionInfoQueryCreator(String revisionInfoEntityName, String revisionInfoIdName, @@ -53,10 +54,10 @@ public class RevisionInfoQueryCreator { .append(" rev where ").append(revisionInfoTimestampName).append(" <= :_revision_date") .toString(); - revisionQuery = new StringBuilder() + revisionsQuery = new StringBuilder() .append("select rev from ").append(revisionInfoEntityName) .append(" rev where ").append(revisionInfoIdName) - .append(" = :_revision_number") + .append(" in (:_revision_numbers)") .toString(); } @@ -68,7 +69,7 @@ public class RevisionInfoQueryCreator { return session.createQuery(revisionNumberForDateQuery).setParameter("_revision_date", timestampAsDate ? date : date.getTime()); } - public Query getRevisionQuery(Session session, Number revision) { - return session.createQuery(revisionQuery).setParameter("_revision_number", revision); + public Query getRevisionsQuery(Session session, Set revisions) { + return session.createQuery(revisionsQuery).setParameterList("_revision_numbers", revisions); } } diff --git a/envers/src/test/java/org/hibernate/envers/test/integration/reventity/Custom.java b/envers/src/test/java/org/hibernate/envers/test/integration/reventity/Custom.java index 598424b0c1..b4f7c0edbc 100644 --- a/envers/src/test/java/org/hibernate/envers/test/integration/reventity/Custom.java +++ b/envers/src/test/java/org/hibernate/envers/test/integration/reventity/Custom.java @@ -25,8 +25,13 @@ package org.hibernate.envers.test.integration.reventity; import java.util.Arrays; import java.util.Date; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + import javax.persistence.EntityManager; +import org.hibernate.ejb.Ejb3Configuration; import org.hibernate.envers.AuditReader; import org.hibernate.envers.exception.RevisionDoesNotExistException; import org.hibernate.envers.test.AbstractEntityTest; @@ -35,8 +40,6 @@ import org.hibernate.envers.test.entities.reventity.CustomRevEntity; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import org.hibernate.ejb.Ejb3Configuration; - /** * @author Adam Warski (adam at warski dot org) */ @@ -119,6 +122,20 @@ public class Custom extends AbstractEntityTest { assert rev2Timestamp <= timestamp3; } + @Test + public void testFindRevisions() { + AuditReader vr = getAuditReader(); + + Set revNumbers = new HashSet(); + revNumbers.add(1); + revNumbers.add(2); + + Map revisionMap = vr.findRevisions(CustomRevEntity.class, revNumbers); + assert(revisionMap.size() == 2); + assert(revisionMap.get(1).equals(vr.findRevision(CustomRevEntity.class, 1))); + assert(revisionMap.get(2).equals(vr.findRevision(CustomRevEntity.class, 2))); + } + @Test public void testRevisionsCounts() { assert Arrays.asList(1, 2).equals(getAuditReader().getRevisions(StrTestEntity.class, id)); diff --git a/envers/src/test/java/org/hibernate/envers/test/integration/reventity/CustomBoxed.java b/envers/src/test/java/org/hibernate/envers/test/integration/reventity/CustomBoxed.java index 8495eede3e..d49c2736a9 100644 --- a/envers/src/test/java/org/hibernate/envers/test/integration/reventity/CustomBoxed.java +++ b/envers/src/test/java/org/hibernate/envers/test/integration/reventity/CustomBoxed.java @@ -25,8 +25,13 @@ package org.hibernate.envers.test.integration.reventity; import java.util.Arrays; import java.util.Date; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + import javax.persistence.EntityManager; +import org.hibernate.ejb.Ejb3Configuration; import org.hibernate.envers.AuditReader; import org.hibernate.envers.exception.RevisionDoesNotExistException; import org.hibernate.envers.test.AbstractEntityTest; @@ -34,8 +39,6 @@ import org.hibernate.envers.test.entities.StrTestEntity; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import org.hibernate.ejb.Ejb3Configuration; - /** * @author Adam Warski (adam at warski dot org) */ @@ -118,6 +121,20 @@ public class CustomBoxed extends AbstractEntityTest { assert rev2Timestamp <= timestamp3; } + @Test + public void testFindRevisions() { + AuditReader vr = getAuditReader(); + + Set revNumbers = new HashSet(); + revNumbers.add(1); + revNumbers.add(2); + + Map revisionMap = vr.findRevisions(CustomBoxedRevEntity.class, revNumbers); + assert(revisionMap.size() == 2); + assert(revisionMap.get(1).equals(vr.findRevision(CustomBoxedRevEntity.class, 1))); + assert(revisionMap.get(2).equals(vr.findRevision(CustomBoxedRevEntity.class, 2))); + } + @Test public void testRevisionsCounts() { assert Arrays.asList(1, 2).equals(getAuditReader().getRevisions(StrTestEntity.class, id)); @@ -131,4 +148,4 @@ public class CustomBoxed extends AbstractEntityTest { assert getAuditReader().find(StrTestEntity.class, id, 1).equals(ver1); assert getAuditReader().find(StrTestEntity.class, id, 2).equals(ver2); } -} \ No newline at end of file +} diff --git a/envers/src/test/java/org/hibernate/envers/test/integration/reventity/Inherited.java b/envers/src/test/java/org/hibernate/envers/test/integration/reventity/Inherited.java index ccba34734e..fd1cac5f25 100644 --- a/envers/src/test/java/org/hibernate/envers/test/integration/reventity/Inherited.java +++ b/envers/src/test/java/org/hibernate/envers/test/integration/reventity/Inherited.java @@ -25,8 +25,13 @@ package org.hibernate.envers.test.integration.reventity; import java.util.Arrays; import java.util.Date; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + import javax.persistence.EntityManager; +import org.hibernate.ejb.Ejb3Configuration; import org.hibernate.envers.AuditReader; import org.hibernate.envers.exception.RevisionDoesNotExistException; import org.hibernate.envers.test.AbstractEntityTest; @@ -34,8 +39,6 @@ import org.hibernate.envers.test.entities.StrTestEntity; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import org.hibernate.ejb.Ejb3Configuration; - /** * @author Adam Warski (adam at warski dot org) */ @@ -118,6 +121,20 @@ public class Inherited extends AbstractEntityTest { assert rev2Timestamp <= timestamp3; } + @Test + public void testFindRevisions() { + AuditReader vr = getAuditReader(); + + Set revNumbers = new HashSet(); + revNumbers.add(1); + revNumbers.add(2); + + Map revisionMap = vr.findRevisions(InheritedRevEntity.class, revNumbers); + assert(revisionMap.size() == 2); + assert(revisionMap.get(1).equals(vr.findRevision(InheritedRevEntity.class, 1))); + assert(revisionMap.get(2).equals(vr.findRevision(InheritedRevEntity.class, 2))); + } + @Test public void testRevisionsCounts() { assert Arrays.asList(1, 2).equals(getAuditReader().getRevisions(StrTestEntity.class, id)); diff --git a/envers/src/test/java/org/hibernate/envers/test/integration/reventity/Listener.java b/envers/src/test/java/org/hibernate/envers/test/integration/reventity/Listener.java index fe7ebc437d..9920f38fa3 100644 --- a/envers/src/test/java/org/hibernate/envers/test/integration/reventity/Listener.java +++ b/envers/src/test/java/org/hibernate/envers/test/integration/reventity/Listener.java @@ -25,8 +25,13 @@ package org.hibernate.envers.test.integration.reventity; import java.util.Arrays; import java.util.Date; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + import javax.persistence.EntityManager; +import org.hibernate.ejb.Ejb3Configuration; import org.hibernate.envers.AuditReader; import org.hibernate.envers.exception.RevisionDoesNotExistException; import org.hibernate.envers.test.AbstractEntityTest; @@ -34,8 +39,6 @@ import org.hibernate.envers.test.entities.StrTestEntity; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import org.hibernate.ejb.Ejb3Configuration; - /** * @author Adam Warski (adam at warski dot org) */ @@ -131,6 +134,20 @@ public class Listener extends AbstractEntityTest { assert "data2".equals(rev2Data.getData()); } + @Test + public void testFindRevisions() { + AuditReader vr = getAuditReader(); + + Set revNumbers = new HashSet(); + revNumbers.add(1); + revNumbers.add(2); + + Map revisionMap = vr.findRevisions(ListenerRevEntity.class, revNumbers); + assert(revisionMap.size() == 2); + assert(revisionMap.get(1).equals(vr.findRevision(ListenerRevEntity.class, 1))); + assert(revisionMap.get(2).equals(vr.findRevision(ListenerRevEntity.class, 2))); + } + @Test public void testRevisionsCounts() { assert Arrays.asList(1, 2).equals(getAuditReader().getRevisions(StrTestEntity.class, id)); diff --git a/envers/src/test/java/org/hibernate/envers/test/integration/reventity/LongRevNumber.java b/envers/src/test/java/org/hibernate/envers/test/integration/reventity/LongRevNumber.java index cf4d428d53..33c5079f00 100644 --- a/envers/src/test/java/org/hibernate/envers/test/integration/reventity/LongRevNumber.java +++ b/envers/src/test/java/org/hibernate/envers/test/integration/reventity/LongRevNumber.java @@ -24,16 +24,19 @@ package org.hibernate.envers.test.integration.reventity; import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + import javax.persistence.EntityManager; +import org.hibernate.ejb.Ejb3Configuration; import org.hibernate.envers.AuditReader; import org.hibernate.envers.test.AbstractEntityTest; import org.hibernate.envers.test.entities.StrTestEntity; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import org.hibernate.ejb.Ejb3Configuration; - /** * @author Adam Warski (adam at warski dot org) */ @@ -70,6 +73,20 @@ public class LongRevNumber extends AbstractEntityTest { assert vr.findRevision(LongRevNumberRevEntity.class, 2l).getCustomId() == 2l; } + @Test + public void testFindRevisions() { + AuditReader vr = getAuditReader(); + + Set revNumbers = new HashSet(); + revNumbers.add(1l); + revNumbers.add(2l); + + Map revisionMap = vr.findRevisions(LongRevNumberRevEntity.class, revNumbers); + assert(revisionMap.size() == 2); + assert(revisionMap.get(1l).equals(vr.findRevision(LongRevNumberRevEntity.class, 1l))); + assert(revisionMap.get(2l).equals(vr.findRevision(LongRevNumberRevEntity.class, 2l))); + } + @Test public void testRevisionsCounts() { assert Arrays.asList(1l, 2l).equals(getAuditReader().getRevisions(StrTestEntity.class, id)); @@ -83,4 +100,4 @@ public class LongRevNumber extends AbstractEntityTest { assert getAuditReader().find(StrTestEntity.class, id, 1l).equals(ver1); assert getAuditReader().find(StrTestEntity.class, id, 2l).equals(ver2); } -} \ No newline at end of file +}