HHH-7555 - Add ability to query revision entity instances of an entity class without instantiating the entity instances.
(backport from wip/6.0)
This commit is contained in:
parent
4a3f7c19c0
commit
fea7f348ee
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.envers.query;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.envers.boot.internal.EnversService;
|
||||
import org.hibernate.envers.exception.NotAuditedException;
|
||||
import org.hibernate.envers.internal.reader.AuditReaderImplementor;
|
||||
|
@ -171,7 +172,8 @@ public class AuditQueryCreator {
|
|||
auditReaderImplementor,
|
||||
c,
|
||||
selectEntitiesOnly,
|
||||
selectDeletedEntities
|
||||
selectDeletedEntities,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -211,7 +213,60 @@ public class AuditQueryCreator {
|
|||
c,
|
||||
entityName,
|
||||
selectEntitiesOnly,
|
||||
selectDeletedEntities
|
||||
selectDeletedEntities,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a query that selects the revision entities associated with the specified entity. You may also
|
||||
* specify whether the revision entities list should include those for deletions of the entity class.
|
||||
*
|
||||
* @param clazz Class of the entities for which to query.
|
||||
* @param selectDeletedEntities If true, the result will include revision entities where deletions occurred.
|
||||
*
|
||||
* @return A query of revision entities based on the specified entity class. The results of the query will
|
||||
* be stored in ascending order by the revision number unless an order is specified.
|
||||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
@Incubating
|
||||
public AuditQuery forRevisionsOfEntity(Class<?> clazz, boolean selectDeletedEntities) {
|
||||
clazz = getTargetClassIfProxied( clazz );
|
||||
return new RevisionsOfEntityQuery(
|
||||
enversService,
|
||||
auditReaderImplementor,
|
||||
clazz,
|
||||
false,
|
||||
selectDeletedEntities,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a query that selects the revision entities associated with the specified entity. You may also
|
||||
* specify whether the revision entities list should include those for deletions of the entity class.
|
||||
*
|
||||
* @param clazz Class of the entities for which to query.
|
||||
* @param entityName Name of the entity (for cases where it cannot be guessed based on class clazz).
|
||||
* @param selectDeletedEntities If true, the result will include revision entities where deletions occurred.
|
||||
*
|
||||
* @return A query of revision entities based on the specified entity class. The results of the query will
|
||||
* be stored in ascending order by the revision number unless an order is specified.
|
||||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
@Incubating
|
||||
public AuditQuery forRevisionsOfEntity(Class<?> clazz, String entityName, boolean selectDeletedEntities) {
|
||||
clazz = getTargetClassIfProxied( clazz );
|
||||
return new RevisionsOfEntityQuery(
|
||||
enversService,
|
||||
auditReaderImplementor,
|
||||
clazz,
|
||||
entityName,
|
||||
false,
|
||||
selectDeletedEntities,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.hibernate.LockMode;
|
|||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.envers.boot.internal.EnversService;
|
||||
import org.hibernate.envers.exception.AuditException;
|
||||
import org.hibernate.envers.exception.NotAuditedException;
|
||||
import org.hibernate.envers.internal.entities.EntityInstantiator;
|
||||
import org.hibernate.envers.internal.reader.AuditReaderImplementor;
|
||||
import org.hibernate.envers.internal.tools.query.QueryBuilder;
|
||||
|
@ -79,6 +80,9 @@ public abstract class AbstractAuditQuery implements AuditQueryImplementor {
|
|||
entityClassName = cls.getName();
|
||||
this.entityName = entityName;
|
||||
versionsEntityName = enversService.getAuditEntitiesConfiguration().getAuditEntityName( entityName );
|
||||
if ( !enversService.getEntitiesConfigurations().isVersioned( entityName ) ) {
|
||||
throw new NotAuditedException( entityName, "Entity [" + entityName + "] is not versioned" );
|
||||
}
|
||||
aliasToEntityNameMap.put( REFERENCED_ENTITY_ALIAS, entityName );
|
||||
|
||||
qb = new QueryBuilder( versionsEntityName, REFERENCED_ENTITY_ALIAS );
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.envers.query.internal.impl;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.persistence.criteria.JoinType;
|
||||
|
||||
|
@ -30,17 +31,20 @@ import org.hibernate.proxy.HibernateProxy;
|
|||
public class RevisionsOfEntityQuery extends AbstractAuditQuery {
|
||||
private final boolean selectEntitiesOnly;
|
||||
private final boolean selectDeletedEntities;
|
||||
private final boolean selectRevisionInfoOnly;
|
||||
|
||||
public RevisionsOfEntityQuery(
|
||||
EnversService enversService,
|
||||
AuditReaderImplementor versionsReader,
|
||||
Class<?> cls,
|
||||
boolean selectEntitiesOnly,
|
||||
boolean selectDeletedEntities) {
|
||||
boolean selectDeletedEntities,
|
||||
boolean selectRevisionInfoOnly) {
|
||||
super( enversService, versionsReader, cls );
|
||||
|
||||
this.selectEntitiesOnly = selectEntitiesOnly;
|
||||
this.selectDeletedEntities = selectDeletedEntities;
|
||||
this.selectRevisionInfoOnly = selectRevisionInfoOnly && !selectEntitiesOnly;
|
||||
}
|
||||
|
||||
public RevisionsOfEntityQuery(
|
||||
|
@ -48,11 +52,13 @@ public class RevisionsOfEntityQuery extends AbstractAuditQuery {
|
|||
AuditReaderImplementor versionsReader,
|
||||
Class<?> cls, String entityName,
|
||||
boolean selectEntitiesOnly,
|
||||
boolean selectDeletedEntities) {
|
||||
boolean selectDeletedEntities,
|
||||
boolean selectRevisionInfoOnly) {
|
||||
super( enversService, versionsReader, cls, entityName );
|
||||
|
||||
this.selectEntitiesOnly = selectEntitiesOnly;
|
||||
this.selectDeletedEntities = selectDeletedEntities;
|
||||
this.selectRevisionInfoOnly = selectRevisionInfoOnly && !selectEntitiesOnly;
|
||||
}
|
||||
|
||||
private Number getRevisionNumber(Map versionsEntity) {
|
||||
|
@ -121,6 +127,9 @@ public class RevisionsOfEntityQuery extends AbstractAuditQuery {
|
|||
if ( hasProjection() ) {
|
||||
return queryResult;
|
||||
}
|
||||
else if ( selectRevisionInfoOnly ) {
|
||||
return queryResult.stream().map( e -> ( (Object[]) e )[1] ).collect( Collectors.toList() );
|
||||
}
|
||||
else {
|
||||
List entities = new ArrayList();
|
||||
String revisionTypePropertyName = verEntCfg.getRevisionTypePropName();
|
||||
|
|
|
@ -7,14 +7,23 @@
|
|||
package org.hibernate.envers.test.integration.auditReader;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.hibernate.envers.enhanced.SequenceIdRevisionEntity;
|
||||
import org.hibernate.envers.exception.NotAuditedException;
|
||||
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
|
||||
import org.hibernate.envers.test.Priority;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* A test which checks the correct behavior of AuditReader.isEntityClassAudited(Class entityClass).
|
||||
*
|
||||
|
@ -45,13 +54,17 @@ public class AuditReaderAPITest extends BaseEnversJPAFunctionalTestCase {
|
|||
ent1.setStr1( "str2" );
|
||||
ent2.setStr1( "str2" );
|
||||
em.getTransaction().commit();
|
||||
|
||||
em.getTransaction().begin();
|
||||
ent1 = em.find( AuditedTestEntity.class, 1 );
|
||||
em.remove( ent1 );
|
||||
em.getTransaction().commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEntityClassAuditedForAuditedEntity() {
|
||||
assert getAuditReader().isEntityClassAudited( AuditedTestEntity.class );
|
||||
|
||||
assert Arrays.asList( 1, 2 ).equals( getAuditReader().getRevisions( AuditedTestEntity.class, 1 ) );
|
||||
assertTrue( getAuditReader().isEntityClassAudited( AuditedTestEntity.class ) );
|
||||
assertEquals( Arrays.asList( 1, 2, 3 ), getAuditReader().getRevisions( AuditedTestEntity.class, 1 ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -68,5 +81,37 @@ public class AuditReaderAPITest extends BaseEnversJPAFunctionalTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-7555" )
|
||||
public void testFindRevisionEntitiesWithoutDeletions() {
|
||||
List<?> revisionInfos = getAuditReader().createQuery()
|
||||
.forRevisionsOfEntity( AuditedTestEntity.class, false )
|
||||
.getResultList();
|
||||
assertEquals( 2, revisionInfos.size() );
|
||||
revisionInfos.forEach( e -> assertTyping( SequenceIdRevisionEntity.class, e ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-7555" )
|
||||
public void testFindRevisionEntitiesWithDeletions() {
|
||||
List<?> revisionInfos = getAuditReader().createQuery()
|
||||
.forRevisionsOfEntity( AuditedTestEntity.class, true )
|
||||
.getResultList();
|
||||
assertEquals( 3, revisionInfos.size() );
|
||||
revisionInfos.forEach( e -> assertTyping( SequenceIdRevisionEntity.class, e ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-7555" )
|
||||
public void testFindRevisionEntitiesNonAuditedEntity() {
|
||||
try {
|
||||
List<?> revisionInfos = getAuditReader().createQuery()
|
||||
.forRevisionsOfEntity( NotAuditedTestEntity.class, false )
|
||||
.getResultList();
|
||||
fail( "Expected a NotAuditedException" );
|
||||
}
|
||||
catch ( NotAuditedException e ) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue