HHH-5580 - Query fix
This commit is contained in:
parent
98342a7e2d
commit
88eda2b081
|
@ -25,8 +25,8 @@ package org.hibernate.envers.query;
|
|||
import static org.hibernate.envers.tools.ArgumentsTools.checkNotNull;
|
||||
import static org.hibernate.envers.tools.ArgumentsTools.checkPositive;
|
||||
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||
import org.hibernate.envers.query.impl.EntitiesModifiedAtRevisionQuery;
|
||||
import org.hibernate.envers.query.impl.EntitiesAtRevisionQuery;
|
||||
import org.hibernate.envers.query.impl.RevisionsOfEntityQuery;
|
||||
import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||
|
@ -55,18 +55,9 @@ public class AuditQueryCreator {
|
|||
* projection is added.
|
||||
*/
|
||||
public AuditQuery forEntitiesAtRevision(Class<?> c, Number revision) {
|
||||
return forEntitiesAtRevision(c, revision, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns deleted entities as well. Removed entities data depends on the value of
|
||||
* <code>org.hibernate.envers.store_data_at_delete</code> parameter.
|
||||
* @see #forEntitiesAtRevision(Class, Number)
|
||||
*/
|
||||
public AuditQuery forEntitiesAtRevision(Class<?> c, Number revision, boolean selectDeletedEntities) {
|
||||
checkNotNull(revision, "Entity revision");
|
||||
checkPositive(revision, "Entity revision");
|
||||
return new EntitiesAtRevisionQuery(auditCfg, auditReaderImplementor, c, revision, selectDeletedEntities);
|
||||
return new EntitiesAtRevisionQuery(auditCfg, auditReaderImplementor, c, revision);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,7 +74,22 @@ public class AuditQueryCreator {
|
|||
checkNotNull(revision, "Entity revision");
|
||||
checkPositive(revision, "Entity revision");
|
||||
return new EntitiesAtRevisionQuery(auditCfg, auditReaderImplementor, c, entityName, revision);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In comparison to {@link #forEntitiesAtRevision(Class, String, Number)} this method 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, String, Number)
|
||||
*/
|
||||
public AuditQuery forEntitiesAtCertainRevision(Class<?> c, Number revision) {
|
||||
checkNotNull(revision, "Entity revision");
|
||||
checkPositive(revision, "Entity revision");
|
||||
return new EntitiesModifiedAtRevisionQuery(auditCfg, auditReaderImplementor, c, revision);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a query, which selects the revisions, at which the given entity was modified.
|
||||
|
|
|
@ -39,28 +39,19 @@ import org.hibernate.envers.reader.AuditReaderImplementor;
|
|||
*/
|
||||
public class EntitiesAtRevisionQuery extends AbstractAuditQuery {
|
||||
private final Number revision;
|
||||
private final boolean selectDeletedEntities;
|
||||
|
||||
public EntitiesAtRevisionQuery(AuditConfiguration verCfg,
|
||||
AuditReaderImplementor versionsReader, Class<?> cls, String entityName,
|
||||
Number revision) {
|
||||
this(verCfg, versionsReader, cls, entityName, revision, false);
|
||||
}
|
||||
|
||||
public EntitiesAtRevisionQuery(AuditConfiguration verCfg,
|
||||
AuditReaderImplementor versionsReader, Class<?> cls,
|
||||
Number revision, boolean selectDeletedEntities) {
|
||||
Number revision) {
|
||||
super(verCfg, versionsReader, cls);
|
||||
this.revision = revision;
|
||||
this.selectDeletedEntities = selectDeletedEntities;
|
||||
}
|
||||
|
||||
public EntitiesAtRevisionQuery(AuditConfiguration verCfg,
|
||||
AuditReaderImplementor versionsReader, Class<?> cls, String entityName,
|
||||
Number revision, boolean selectDeletedEntities) {
|
||||
Number revision) {
|
||||
super(verCfg, versionsReader, cls, entityName);
|
||||
this.revision = revision;
|
||||
this.selectDeletedEntities = selectDeletedEntities;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
|
@ -95,10 +86,8 @@ public class EntitiesAtRevisionQuery extends AbstractAuditQuery {
|
|||
verEntCfg.getRevisionEndFieldName(), true, referencedIdData,
|
||||
revisionPropertyPath, originalIdPropertyName, "e", "e2");
|
||||
|
||||
if (!selectDeletedEntities) {
|
||||
// e.revision_type != DEL
|
||||
qb.getRootParameters().addWhereWithParam(verEntCfg.getRevisionTypePropName(), "<>", RevisionType.DEL);
|
||||
}
|
||||
// e.revision_type != DEL
|
||||
qb.getRootParameters().addWhereWithParam(verEntCfg.getRevisionTypePropName(), "<>", RevisionType.DEL);
|
||||
|
||||
// all specified conditions
|
||||
for (AuditCriterion criterion : criterions) {
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package org.hibernate.envers.query.impl;
|
||||
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
||||
import org.hibernate.envers.query.criteria.AuditCriterion;
|
||||
import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* In comparison to {@link EntitiesAtRevisionQuery} this query will return an empty collection if an entity
|
||||
* of a certain type has not been changed in a given revision.
|
||||
* @see EntitiesAtRevisionQuery
|
||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
*/
|
||||
public class EntitiesModifiedAtRevisionQuery extends AbstractAuditQuery {
|
||||
private final Number revision;
|
||||
|
||||
public EntitiesModifiedAtRevisionQuery(AuditConfiguration verCfg, AuditReaderImplementor versionsReader, Class<?> cls,
|
||||
Number revision) {
|
||||
super(verCfg, versionsReader, cls);
|
||||
this.revision = revision;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public List list() {
|
||||
/*
|
||||
* The query that we need to create:
|
||||
* SELECT new list(e) FROM versionsReferencedEntity e
|
||||
* WHERE
|
||||
* (all specified conditions, transformed, on the "e" entity) AND
|
||||
* e.revision = :revision
|
||||
*/
|
||||
AuditEntitiesConfiguration verEntCfg = verCfg.getAuditEntCfg();
|
||||
String revisionPropertyPath = verEntCfg.getRevisionNumberPath();
|
||||
qb.getRootParameters().addWhereWithParam(revisionPropertyPath, "=", revision);
|
||||
|
||||
// all specified conditions
|
||||
for (AuditCriterion criterion : criterions) {
|
||||
criterion.addToQuery(verCfg, entityName, qb, qb.getRootParameters());
|
||||
}
|
||||
|
||||
Query query = buildQuery();
|
||||
List queryResult = query.list();
|
||||
|
||||
if (hasProjection) {
|
||||
return queryResult;
|
||||
} else {
|
||||
List result = new ArrayList();
|
||||
entityInstantiator.addInstancesFromVersionsEntities(entityName, result, queryResult, revision);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -239,7 +239,7 @@ public class AuditReaderImpl implements AuditReaderImplementor {
|
|||
List<Class> clazz = findEntityTypesChangedInRevision(revision);
|
||||
List result = new ArrayList(clazz.size());
|
||||
for (Class c : clazz) {
|
||||
result.addAll(createQuery().forEntitiesAtRevision(c, revision, true).getResultList());
|
||||
result.addAll(createQuery().forEntitiesAtCertainRevision(c, revision).getResultList());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -249,7 +249,7 @@ public class AuditReaderImpl implements AuditReaderImplementor {
|
|||
List<Class> clazz = findEntityTypesChangedInRevision(revision);
|
||||
List result = new ArrayList(clazz.size());
|
||||
for (Class c : clazz) {
|
||||
result.addAll(createQuery().forEntitiesAtRevision(c, revision, true).add(new RevisionTypeAuditExpression(revisionType, "=")).getResultList());
|
||||
result.addAll(createQuery().forEntitiesAtCertainRevision(c, revision).add(new RevisionTypeAuditExpression(revisionType, "=")).getResultList());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -261,7 +261,7 @@ public class AuditReaderImpl implements AuditReaderImplementor {
|
|||
for (RevisionType revisionType : RevisionType.values()) {
|
||||
result.put(revisionType, new ArrayList());
|
||||
for (Class c : clazz) {
|
||||
List list = createQuery().forEntitiesAtRevision(c, revision, true).add(new RevisionTypeAuditExpression(revisionType, "=")).getResultList();
|
||||
List list = createQuery().forEntitiesAtCertainRevision(c, revision).add(new RevisionTypeAuditExpression(revisionType, "=")).getResultList();
|
||||
result.get(revisionType).addAll(list);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
package org.hibernate.envers.test.integration.reventity.trackmodifiedentities;
|
||||
|
||||
import org.hibernate.ejb.Ejb3Configuration;
|
||||
import org.hibernate.envers.test.AbstractEntityTest;
|
||||
import org.hibernate.envers.test.Priority;
|
||||
import org.hibernate.envers.test.entities.StrTestEntity;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
*/
|
||||
public class TrackingEntitiesMultipleChangesTest extends AbstractEntityTest {
|
||||
private Integer steId1 = null;
|
||||
private Integer steId2 = null;
|
||||
|
||||
@Override
|
||||
public void configure(Ejb3Configuration cfg) {
|
||||
cfg.setProperty("org.hibernate.envers.track_entities_changed_in_revision", "true");
|
||||
cfg.addAnnotatedClass(StrTestEntity.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Priority(10)
|
||||
public void initData() {
|
||||
EntityManager em = getEntityManager();
|
||||
|
||||
// Revision 1 - Adding two entities
|
||||
em.getTransaction().begin();
|
||||
StrTestEntity ste1 = new StrTestEntity("x");
|
||||
StrTestEntity ste2 = new StrTestEntity("y");
|
||||
em.persist(ste1);
|
||||
em.persist(ste2);
|
||||
steId1 = ste1.getId();
|
||||
steId2 = ste2.getId();
|
||||
em.getTransaction().commit();
|
||||
|
||||
// Revision 2 - Adding first and removing second entity
|
||||
em.getTransaction().begin();
|
||||
ste1 = em.find(StrTestEntity.class, steId1);
|
||||
ste2 = em.find(StrTestEntity.class, steId2);
|
||||
ste1.setStr("z");
|
||||
em.remove(ste2);
|
||||
em.getTransaction().commit();
|
||||
|
||||
// Revision 3 - Modifying and removing the same entity.
|
||||
em.getTransaction().begin();
|
||||
ste1 = em.find(StrTestEntity.class, steId1);
|
||||
ste1.setStr("a");
|
||||
em.merge(ste1);
|
||||
em.remove(ste1);
|
||||
em.getTransaction().commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTrackAddedTwoEntities() {
|
||||
StrTestEntity ste1 = new StrTestEntity("x", steId1);
|
||||
StrTestEntity ste2 = new StrTestEntity("y", steId2);
|
||||
|
||||
assert Arrays.asList(ste1, ste2).equals(getAuditReader().findEntitiesChangedInRevision(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTrackUpdateAndRemoveDifferentEntities() {
|
||||
StrTestEntity ste1 = new StrTestEntity("z", steId1);
|
||||
StrTestEntity ste2 = new StrTestEntity(null, steId2);
|
||||
|
||||
assert Arrays.asList(ste1, ste2).equals(getAuditReader().findEntitiesChangedInRevision(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTrackUpdateAndRemoveTheSameEntity() {
|
||||
StrTestEntity ste1 = new StrTestEntity(null, steId1);
|
||||
|
||||
assert Arrays.asList(ste1).equals(getAuditReader().findEntitiesChangedInRevision(3));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue