Merge pull request #100 from lukasz-antoniak/HHH-4760
HHH-4760 - NotAuditedException occurs when AuditReader.getRevisions() is called for Javassist proxies
This commit is contained in:
commit
c93ce70f9d
|
@ -30,6 +30,7 @@ import org.hibernate.envers.query.impl.RevisionsOfEntityQuery;
|
|||
import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||
|
||||
import static org.hibernate.envers.tools.ArgumentsTools.*;
|
||||
import static org.hibernate.envers.tools.Tools.getTargetClassIfProxied;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
|
@ -57,6 +58,7 @@ public class AuditQueryCreator {
|
|||
public AuditQuery forEntitiesAtRevision(Class<?> c, Number revision) {
|
||||
checkNotNull(revision, "Entity revision");
|
||||
checkPositive(revision, "Entity revision");
|
||||
c = getTargetClassIfProxied(c);
|
||||
return new EntitiesAtRevisionQuery(auditCfg, auditReaderImplementor, c, revision);
|
||||
}
|
||||
|
||||
|
@ -73,6 +75,7 @@ public class AuditQueryCreator {
|
|||
public AuditQuery forEntitiesAtRevision(Class<?> c, String entityName, Number revision) {
|
||||
checkNotNull(revision, "Entity revision");
|
||||
checkPositive(revision, "Entity revision");
|
||||
c = getTargetClassIfProxied(c);
|
||||
return new EntitiesAtRevisionQuery(auditCfg, auditReaderImplementor, c, entityName, revision);
|
||||
}
|
||||
|
||||
|
@ -92,6 +95,7 @@ public class AuditQueryCreator {
|
|||
public AuditQuery forEntitiesModifiedAtRevision(Class<?> c, String entityName, Number revision) {
|
||||
checkNotNull(revision, "Entity revision");
|
||||
checkPositive(revision, "Entity revision");
|
||||
c = getTargetClassIfProxied(c);
|
||||
return new EntitiesModifiedAtRevisionQuery(auditCfg, auditReaderImplementor, c, entityName, revision);
|
||||
}
|
||||
|
||||
|
@ -110,6 +114,7 @@ public class AuditQueryCreator {
|
|||
public AuditQuery forEntitiesModifiedAtRevision(Class<?> c, Number revision) {
|
||||
checkNotNull(revision, "Entity revision");
|
||||
checkPositive(revision, "Entity revision");
|
||||
c = getTargetClassIfProxied(c);
|
||||
return new EntitiesModifiedAtRevisionQuery(auditCfg, auditReaderImplementor, c, revision);
|
||||
}
|
||||
|
||||
|
@ -134,6 +139,7 @@ public class AuditQueryCreator {
|
|||
* unless an order or projection is added.
|
||||
*/
|
||||
public AuditQuery forRevisionsOfEntity(Class<?> c, boolean selectEntitiesOnly, boolean selectDeletedEntities) {
|
||||
c = getTargetClassIfProxied(c);
|
||||
return new RevisionsOfEntityQuery(auditCfg, auditReaderImplementor, c, selectEntitiesOnly,selectDeletedEntities);
|
||||
}
|
||||
|
||||
|
@ -159,6 +165,7 @@ public class AuditQueryCreator {
|
|||
* unless an order or projection is added.
|
||||
*/
|
||||
public AuditQuery forRevisionsOfEntity(Class<?> c, String entityName, boolean selectEntitiesOnly, boolean selectDeletedEntities) {
|
||||
c = getTargetClassIfProxied(c);
|
||||
return new RevisionsOfEntityQuery(auditCfg, auditReaderImplementor, c, entityName, selectEntitiesOnly,selectDeletedEntities);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
package org.hibernate.envers.reader;
|
||||
import static org.hibernate.envers.tools.ArgumentsTools.checkNotNull;
|
||||
import static org.hibernate.envers.tools.ArgumentsTools.checkPositive;
|
||||
import static org.hibernate.envers.tools.Tools.getTargetClassIfProxied;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
@ -90,13 +91,14 @@ public class AuditReaderImpl implements AuditReaderImplementor {
|
|||
|
||||
public <T> T find(Class<T> cls, Object primaryKey, Number revision) throws
|
||||
IllegalArgumentException, NotAuditedException, IllegalStateException {
|
||||
|
||||
cls = getTargetClassIfProxied(cls);
|
||||
return this.find(cls, cls.getName(), primaryKey, revision);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public <T> T find(Class<T> cls, String entityName, Object primaryKey, Number revision) throws
|
||||
IllegalArgumentException, NotAuditedException, IllegalStateException {
|
||||
cls = getTargetClassIfProxied(cls);
|
||||
checkNotNull(cls, "Entity class");
|
||||
checkNotNull(entityName, "Entity name");
|
||||
checkNotNull(primaryKey, "Primary key");
|
||||
|
@ -128,7 +130,7 @@ public class AuditReaderImpl implements AuditReaderImplementor {
|
|||
|
||||
public List<Number> getRevisions(Class<?> cls, Object primaryKey)
|
||||
throws IllegalArgumentException, NotAuditedException, IllegalStateException {
|
||||
|
||||
cls = getTargetClassIfProxied(cls);
|
||||
return this.getRevisions(cls, cls.getName(), primaryKey);
|
||||
}
|
||||
|
||||
|
@ -136,6 +138,7 @@ public class AuditReaderImpl implements AuditReaderImplementor {
|
|||
public List<Number> getRevisions(Class<?> cls, String entityName, Object primaryKey)
|
||||
throws IllegalArgumentException, NotAuditedException, IllegalStateException {
|
||||
// todo: if a class is not versioned from the beginning, there's a missing ADD rev - what then?
|
||||
cls = getTargetClassIfProxied(cls);
|
||||
checkNotNull(cls, "Entity class");
|
||||
checkNotNull(entityName, "Entity name");
|
||||
checkNotNull(primaryKey, "Primary key");
|
||||
|
@ -193,6 +196,7 @@ public class AuditReaderImpl implements AuditReaderImplementor {
|
|||
@SuppressWarnings({"unchecked"})
|
||||
public <T> T findRevision(Class<T> revisionEntityClass, Number revision) throws IllegalArgumentException,
|
||||
RevisionDoesNotExistException, IllegalStateException {
|
||||
revisionEntityClass = getTargetClassIfProxied(revisionEntityClass);
|
||||
checkNotNull(revision, "Entity revision");
|
||||
checkPositive(revision, "Entity revision");
|
||||
checkSession();
|
||||
|
@ -217,6 +221,7 @@ public class AuditReaderImpl implements AuditReaderImplementor {
|
|||
@SuppressWarnings({"unchecked"})
|
||||
public <T> Map<Number, T> findRevisions(Class<T> revisionEntityClass, Set<Number> revisions) throws IllegalArgumentException,
|
||||
IllegalStateException {
|
||||
revisionEntityClass = getTargetClassIfProxied(revisionEntityClass);
|
||||
Map<Number, T> result = new HashMap<Number, T>(revisions.size());
|
||||
|
||||
for (Number revision : revisions) {
|
||||
|
@ -303,6 +308,7 @@ public class AuditReaderImpl implements AuditReaderImplementor {
|
|||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public <T> T getCurrentRevision(Class<T> revisionEntityClass, boolean persist) {
|
||||
revisionEntityClass = getTargetClassIfProxied(revisionEntityClass);
|
||||
if (!(session instanceof EventSource)) {
|
||||
throw new IllegalArgumentException("The provided session is not an EventSource!");
|
||||
}
|
||||
|
@ -319,6 +325,7 @@ public class AuditReaderImpl implements AuditReaderImplementor {
|
|||
}
|
||||
|
||||
public boolean isEntityClassAudited(Class<?> entityClass) {
|
||||
entityClass = getTargetClassIfProxied(entityClass);
|
||||
return this.isEntityNameAudited(entityClass.getName());
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import javassist.util.proxy.ProxyFactory;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
|
@ -39,6 +40,7 @@ import org.hibernate.proxy.HibernateProxy;
|
|||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
* @author Hern<EFBFBD>n Chanfreau
|
||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
*/
|
||||
public class Tools {
|
||||
public static <K,V> Map<K,V> newHashMap() {
|
||||
|
@ -95,6 +97,23 @@ public class Tools {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param clazz Class wrapped with a proxy or not.
|
||||
* @param <T> Class type.
|
||||
* @return Returns target class in case it has been wrapped with a proxy. If {@code null} reference is passed,
|
||||
* method returns {@code null}.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public static <T> Class<T> getTargetClassIfProxied(Class<T> clazz) {
|
||||
if (clazz == null) {
|
||||
return null;
|
||||
} else if (ProxyFactory.isProxyClass(clazz)) {
|
||||
// Get the source class of Javassist proxy instance.
|
||||
return (Class<T>) clazz.getSuperclass();
|
||||
}
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public static boolean objectsEqual(Object obj1, Object obj2) {
|
||||
if (obj1 == null) {
|
||||
return obj2 == null;
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
package org.hibernate.envers.test.integration.proxy;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.envers.test.AbstractSessionTest;
|
||||
import org.hibernate.envers.test.Priority;
|
||||
import org.hibernate.envers.test.entities.StrTestEntity;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
*/
|
||||
public class QueryingWithProxyObjectTest extends AbstractSessionTest {
|
||||
private Integer id = null;
|
||||
|
||||
@Override
|
||||
protected void initMappings() throws MappingException, URISyntaxException {
|
||||
config.addAnnotatedClass(StrTestEntity.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Priority(10)
|
||||
public void initData() {
|
||||
// Revision 1
|
||||
getSession().getTransaction().begin();
|
||||
StrTestEntity ste = new StrTestEntity("data");
|
||||
getSession().persist(ste);
|
||||
getSession().getTransaction().commit();
|
||||
id = ste.getId();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey="HHH-4760")
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testQueryingWithProxyObject() {
|
||||
StrTestEntity originalSte = new StrTestEntity("data", id);
|
||||
// Load the proxy instance
|
||||
StrTestEntity proxySte = (StrTestEntity) getSession().load(StrTestEntity.class, id);
|
||||
|
||||
Assert.assertTrue(getAuditReader().isEntityClassAudited(proxySte.getClass()));
|
||||
|
||||
StrTestEntity ste = getAuditReader().find(proxySte.getClass(), proxySte.getId(), 1);
|
||||
Assert.assertEquals(originalSte, ste);
|
||||
|
||||
List<Number> revisions = getAuditReader().getRevisions(proxySte.getClass(), proxySte.getId());
|
||||
Assert.assertEquals(Arrays.asList(1), revisions);
|
||||
|
||||
List<StrTestEntity> entities = getAuditReader().createQuery().forEntitiesAtRevision(proxySte.getClass(), 1).getResultList();
|
||||
Assert.assertEquals(Arrays.asList(originalSte), entities);
|
||||
|
||||
ste = (StrTestEntity) getAuditReader().createQuery().forRevisionsOfEntity(proxySte.getClass(), true, false).getSingleResult();
|
||||
Assert.assertEquals(originalSte, ste);
|
||||
|
||||
ste = (StrTestEntity) getAuditReader().createQuery().forEntitiesModifiedAtRevision(proxySte.getClass(), 1).getSingleResult();
|
||||
Assert.assertEquals(originalSte, ste);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue