@Override @SuppressWarnings({"unchecked"}) 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" ); checkSession(); return createQuery().forRevisionsOfEntity( cls, entityName, false, true ) .addProjection( AuditEntity.revisionNumber() ) .addOrder( AuditEntity.revisionNumber().asc() ) .add( AuditEntity.id().eq( primaryKey ) ) .getResultList(); }
@Test public void testMinimizeWithPropertyEq() { List result = getAuditReader().createQuery() .forRevisionsOfEntity( StrIntTestEntity.class, false, true ) .addProjection( AuditEntity.revisionNumber() ) .add( AuditEntity.property( "number" ).minimize() .add( AuditEntity.property( "str1" ).eq( "a" ) ) ) .getResultList(); assert Arrays.asList( 1 ).equals( result ); }
@Test public void testSelectRevisionTypeQuery() { List result = getAuditReader().createQuery() .forRevisionsOfEntity( StrIntTestEntity.class, false, true ) .addProjection( AuditEntity.revisionType() ) .add( AuditEntity.id().eq( id1 ) ) .addOrder( AuditEntity.revisionNumber().asc() ) .getResultList(); assert result.size() == 3; assert result.get( 0 ).equals( RevisionType.ADD ); assert result.get( 1 ).equals( RevisionType.MOD ); assert result.get( 2 ).equals( RevisionType.DEL ); }
@Test public void testMaximizeWithIdEq() { List revs_id1 = getAuditReader().createQuery() .forRevisionsOfEntity( StrIntTestEntity.class, false, true ) .addProjection( AuditEntity.revisionNumber() ) .add( AuditEntity.property( "number" ).maximize() .add( AuditEntity.id().eq( id2 ) ) ) .addOrder( AuditEntity.revisionNumber().asc() ) .getResultList(); assert Arrays.asList( 2, 3, 4 ).equals( revs_id1 ); }
@Test public void testRevisionTypeNeQuery() { // The query shouldn't be ordered as always, otherwise - we get an exception. List results = getAuditReader().createQuery() .forRevisionsOfEntity( StrIntTestEntity.class, true, true ) .add( AuditEntity.id().eq( id1 ) ) .add( AuditEntity.revisionType().ne( RevisionType.MOD ) ) .getResultList(); Assert.assertEquals( 1, results.size() ); Assert.assertEquals( new StrIntTestEntity( "a", 10, id1 ), results.get( 0 ) ); } }
List<Integer> queryIds = Arrays.asList( id2, id3 ); AuditDisjunction disjunction = AuditEntity.disjunction(); for ( Integer id : queryIds ) { AuditCriterion crit = AuditEntity.revisionNumber().maximize() .add( AuditEntity.id().eq( id ) ) .add( AuditEntity.revisionType().ne( RevisionType.DEL ) ); disjunction.add( crit ); .forRevisionsOfEntity( StrIntTestEntity.class, false, false ) .add( disjunction ) .addOrder( AuditEntity.property( "id" ).asc() ) .getResultList();
@Test public void testRevisionsOfEntityWithoutDelete() { List result = getAuditReader().createQuery() .forRevisionsOfEntity( StrIntTestEntity.class, false, false ) .add( AuditEntity.id().eq( id2 ) ) .getResultList(); assert result.size() == 1; assert ((Object[]) result.get( 0 ))[0].equals( new StrIntTestEntity( "b", 11, id2 ) ); assert ((SequenceIdRevisionEntity) ((Object[]) result.get( 0 ))[1]).getId() == 1; assert ((Object[]) result.get( 0 ))[2].equals( RevisionType.ADD ); } }
/** * Create restrictions, projections and specify order for a property of an audited entity. * * @param propertyName Name of the property. */ public static AuditProperty<Object> property(String propertyName) { return property( null, propertyName ); }
@SuppressWarnings("unchecked") public static <T extends AuditedEntity> List<Integer> getEditedBy(final EntityManager entityManager, final Class<T> clazz, final String idName, final String username) { final AuditReader reader = AuditReaderFactory.get(entityManager); final AuditQuery query = reader.createQuery() .forRevisionsOfEntity(clazz, true, false) .addProjection(AuditEntity.property("originalId." + idName).distinct()) .add(AuditEntity.revisionProperty("userName").eq(username)) .add(AuditEntity.revisionType().eq(RevisionType.MOD)); return query.getResultList(); } }
@Test public void testEntitiesReferencedByIng2ToId3() { List rev1_related = getAuditReader().createQuery() .forEntitiesAtRevision( SetRefIngEmbIdEntity.class, 1 ) .add( AuditEntity.relatedId( "reference" ).eq( id3 ) ) .add( AuditEntity.id().eq( id2 ) ) .getResultList(); List rev2_related = getAuditReader().createQuery() .forEntitiesAtRevision( SetRefIngEmbIdEntity.class, 2 ) .add( AuditEntity.relatedId( "reference" ).eq( id3 ) ) .add( AuditEntity.id().eq( id2 ) ) .getResultList(); Object rev3_related = getAuditReader().createQuery() .forEntitiesAtRevision( SetRefIngEmbIdEntity.class, 3 ) .add( AuditEntity.relatedId( "reference" ).eq( id3 ) ) .add( AuditEntity.id().eq( id2 ) ) .getSingleResult(); assert rev1_related.size() == 0; assert rev2_related.size() == 0; assert rev3_related.equals( new SetRefIngEmbIdEntity( id2, "y", null ) ); } }
@Test public void testAuditQueryWithJoinedInheritanceUsingWithSemanticsOneToOne() { List results = getAuditReader().createQuery().forEntitiesAtRevision( EntityB.class, 1 ) .add( disjunction() .add( property( "name" ).like( "b1" ) ) .add( property( "name" ).like( "b2" ) ) ) .traverseRelation( "relationToD", JoinType.INNER ) .add( property( "foo" ).like( "bar" ) ) .getResultList(); assertEquals( 2, results.size() ); }
TransactionUtil.doInJPA( this::entityManagerFactory, entityManager -> { List results = getAuditReader().createQuery().forRevisionsOfEntity( PersonDocument.class, false, true ) .add( AuditEntity.relatedId( "person" ).eq( 1 ) ) .add( AuditEntity.revisionNumber().eq( 1 ) ) .getResultList(); assertEquals( 1, results.size() ); .add( AuditEntity.relatedId( "person" ).eq( 1 ) ) .add( AuditEntity.revisionNumber().eq( 2 ) ) .getResultList(); assertEquals( 1, results.size() ); .add( AuditEntity.relatedId( "person" ).eq( 1 ) ) .add( AuditEntity.revisionNumber().eq( 3 ) ) .getResultList(); assertEquals( 1, results.size() ); .add( AuditEntity.relatedId( "document" ).eq( 1 ) ) .getResultList(); assertEquals( 2, results.size() ); .add( AuditEntity.relatedId( "document" ).eq( 2 ) ) .getResultList(); assertEquals( 1, results.size() );
@Test @FailureExpected(jiraKey = "HHH-11841", message = "Reverted fix in HHH-12018 and will be fixed in HHH-12043") public void testRevisionHistory() { final AuditReader reader = getAuditReader(); AuditQuery categoryQuery = reader.createQuery().forRevisionsOfEntity( Category.class, false, true ) .addOrder( AuditEntity.revisionProperty( "timestamp" ).asc() ) .add( AuditEntity.id().eq( category.getId() ) ); @SuppressWarnings( "unchecked" ) List<Object[]> history = (List<Object[]>) categoryQuery.getResultList(); assertNotNull( history ); assertEquals( 1, history.size() ); final Category category = (Category) reader.createQuery().forEntitiesAtRevision( Category.class, 1 ) .add( AuditEntity.property( "id" ).eq( this.category.getId() ) ) .setMaxResults( 1 ) .getSingleResult(); assertEquals( this.category.getName(), category.getName() ); assertEquals( this.category.getDescription(), category.getDescription() ); assertEquals( "The text", category.getText( this.item ) ); final Value value = category.getValue( this.item ); assertEquals( "The Value", value.getText() ); assertEquals( Long.valueOf( 4711L ), value.getNumberValue() ); }
public static <E> List<Integer> getEditedEntitiesByRevision(final EntityManager entityManager, final Class<E> type, final String pkColumnName, final Number startRevision, final Number endRevision) { if (startRevision == null && startRevision == null) return null; final AuditReader reader = AuditReaderFactory.get(entityManager); final AuditQuery query = reader.createQuery().forRevisionsOfEntity(type, true, false) .addOrder(AuditEntity.revisionProperty("timestamp").asc()) .addProjection(AuditEntity.property("originalId." + pkColumnName).distinct()); if (startRevision != null) query.add(AuditEntity.revisionNumber().ge(startRevision)); if (endRevision != null) query.add(AuditEntity.revisionNumber().le(endRevision)); final List<Integer> entityIds = query.getResultList(); return entityIds; }
@Test @TestForIssue(jiraKey = "HHH-7800") public void testMaximizeInDisjunction() { List<Integer> idsToQuery = Arrays.asList( id1, id3 ); AuditDisjunction disjunction = AuditEntity.disjunction(); for ( Integer id : idsToQuery ) { disjunction.add( AuditEntity.revisionNumber().maximize().add( AuditEntity.id().eq( id ) ) ); } List result = getAuditReader().createQuery() .forRevisionsOfEntity( StrIntTestEntity.class, true, true ) .add( disjunction ) .getResultList(); Set<Integer> idsSeen = new HashSet<Integer>(); for ( Object o : result ) { StrIntTestEntity entity = (StrIntTestEntity) o; Integer id = entity.getId(); Assert.assertTrue( "Entity with ID " + id + " returned but not queried for.", idsToQuery.contains( id ) ); if ( !idsSeen.add( id ) ) { Assert.fail( "Multiple revisions returned with ID " + id + "; expected only one." ); } } }
getAuditReader().createQuery() .forEntitiesAtRevision( SetRefIngEmbIdEntity.class, 1 ) .add( AuditEntity.relatedId( "reference" ).eq( id3 ) ) .getResultList() ); getAuditReader().createQuery() .forEntitiesAtRevision( SetRefIngEmbIdEntity.class, 1 ) .add( AuditEntity.property( "reference" ).eq( new SetRefEdEmbIdEntity( id3, null ) ) ) .getResultList() ); getAuditReader().createQuery() .forEntitiesAtRevision( SetRefIngEmbIdEntity.class, 2 ) .add( AuditEntity.relatedId( "reference" ).eq( id3 ) ) .getResultList() ); getAuditReader().createQuery() .forEntitiesAtRevision( SetRefIngEmbIdEntity.class, 2 ) .add( AuditEntity.property( "reference" ).eq( new SetRefEdEmbIdEntity( id3, null ) ) ) .getResultList() ); getAuditReader().createQuery() .forEntitiesAtRevision( SetRefIngEmbIdEntity.class, 3 ) .add( AuditEntity.relatedId( "reference" ).eq( id3 ) ) .getResultList() );
.traverseRelation( "address", JoinType.INNER ) .traverseRelation( "country", JoinType.INNER ) .add( AuditEntity.property( "name" ).eq( "România" ) ) .getResultList(); .traverseRelation( "address", JoinType.LEFT, "a" ) .add( AuditEntity.or( AuditEntity.property( "a", "city" ).eq( "Cluj-Napoca" ), AuditEntity.relatedId( "country" ).eq( null ) .up() .add( AuditEntity.disjunction() .add( AuditEntity.property( "a", "city" ).eq( "Cluj-Napoca" ) ) .add( AuditEntity.property( "cn", "name" ).eq( "România" ) ) .addOrder( AuditEntity.property( "createdOn" ).asc() ) .getResultList(); .up() .up() .add( AuditEntity.property( "a", "city" ).eqProperty( "cn", "name" ) ) .getResultList();
@Test public void testLeftJoinOnAuditedEntity() { final AuditReader auditReader = getAuditReader(); // all cars where the owner has an age of 20 or where there is no owner at all List<Car> resultList = auditReader.createQuery() .forEntitiesAtRevision( Car.class, 1 ) .traverseRelation( "owner", JoinType.LEFT, "p" ) .up().add( AuditEntity.or( AuditEntity.property( "p", "age").eq( 20 ), AuditEntity.relatedId( "owner" ).eq( null ) ) ) .addOrder( AuditEntity.property( "make" ).asc() ).getResultList(); assertEquals( "The result list should have 2 results, car1 because its owner has an age of 30 and car3 because it has no owner at all", 2, resultList.size() ); Car car0 = resultList.get(0); Car car1 = resultList.get(1); assertEquals( "Unexpected car at index 0", car2.getId(), car0.getId() ); assertEquals( "Unexpected car at index 0", car3.getId(), car1.getId() ); }
/** * Create restrictions, projections and specify order for the revision number, corresponding to an * audited entity. */ public static AuditProperty<Number> revisionNumber() { return revisionNumber( null ); }
/** * Create restrictions on an id of a related entity. * * @param propertyName Name of the property, which is the relation. */ public static AuditRelatedId relatedId(String propertyName) { return relatedId( null, propertyName ); }