@Test public void testAssociationQuery() { final AuditReader auditReader = getAuditReader(); final Car result1 = (Car) auditReader.createQuery().forEntitiesAtRevision( Car.class, 1 ).traverseRelation( "owner", JoinType.INNER ) .add( AuditEntity.property( "name" ).like( "Ford%" ) ).getSingleResult(); assertEquals( "Unexpected single car at revision 1", ford.getId(), result1.getId() ); Car result2 = (Car) auditReader.createQuery().forEntitiesAtRevision( Car.class, 1 ).traverseRelation( "owner", JoinType.INNER ).traverseRelation( "address", JoinType.INNER ) .add( AuditEntity.property( "number" ).eq( 30 ) ).getSingleResult(); assertEquals( "Unexpected single car at revision 1", toyota.getId(), result2.getId() ); List<Car> resultList1 = auditReader.createQuery().forEntitiesAtRevision( Car.class, 1 ).traverseRelation( "owner", JoinType.INNER ) .add( AuditEntity.property( "age" ).ge( 30 ) ).add( AuditEntity.property( "age" ).lt( 40 ) ).up() .addOrder( AuditEntity.property( "make" ).asc() ).getResultList(); assertEquals( "Unexpected number of cars for query in revision 1", 2, resultList1.size() ); assertEquals( "Unexpected car at index 0 in revision 1", ford.getId(), resultList1.get( 0 ).getId() ); assertEquals( "Unexpected car at index 1 in revision 2", toyota.getId(), resultList1.get( 1 ).getId() ); Car result3 = (Car) auditReader.createQuery().forEntitiesAtRevision( Car.class, 2 ).traverseRelation( "owner", JoinType.INNER ) .add( AuditEntity.property( "age" ).ge( 30 ) ).add( AuditEntity.property( "age" ).lt( 40 ) ).up() .addOrder( AuditEntity.property( "make" ).asc() ).getSingleResult(); assertEquals( "Unexpected car at revision 2", ford.getId(), result3.getId() ); }
@Test public void testAssociationQueryWithOrdering() { AuditReader auditReader = getAuditReader(); List<Car> cars1 = auditReader.createQuery().forEntitiesAtRevision( Car.class, 1 ).traverseRelation( "owner", JoinType.INNER ).traverseRelation( "address", JoinType.INNER ) .addOrder( AuditEntity.property( "number" ).asc() ).up().addOrder( AuditEntity.property( "age" ).desc() ).getResultList(); assertEquals( "Unexpected number of results", 3, cars1.size() ); assertEquals( "Unexpected car at index 0", ford.getId(), cars1.get( 0 ).getId() ); assertEquals( "Unexpected car at index 1", vw.getId(), cars1.get( 1 ).getId() ); assertEquals( "Unexpected car at index 2", toyota.getId(), cars1.get( 2 ).getId() ); List<Car> cars2 = auditReader.createQuery().forEntitiesAtRevision( Car.class, 1 ).traverseRelation( "owner", JoinType.INNER ).traverseRelation( "address", JoinType.INNER ) .addOrder( AuditEntity.property( "number" ).asc() ).up().addOrder( AuditEntity.property( "age" ).asc() ).getResultList(); assertEquals( "Unexpected number of results", 3, cars2.size() ); assertEquals( "Unexpected car at index 0", vw.getId(), cars2.get( 0 ).getId() ); assertEquals( "Unexpected car at index 1", ford.getId(), cars2.get( 1 ).getId() ); assertEquals( "Unexpected car at index 2", toyota.getId(), cars2.get( 2 ).getId() ); }
.addProjection( AuditEntity.property( "age" ) ).addOrder( AuditEntity.property( "age" ).asc() ).getResultList(); assertEquals( "Unexpected number of results", 3, list1.size() ); assertEquals( "Unexpected age at index 0", Integer.valueOf( 20 ), list1.get( 0 ) ); .addOrder( AuditEntity.property( "age" ).asc() ).traverseRelation( "address", JoinType.INNER ).addProjection( AuditEntity.selectEntity( false ) ).getResultList(); assertEquals( "Unexpected number of results", 3, list2.size() ); assertEquals( "Unexpected address at index 0", address1.getId(), list2.get( 0 ).getId() ); assertEquals( "Unexpected address at index 2", address2.getId(), list2.get( 2 ).getId() ); List<Address> list3 = auditReader.createQuery().forEntitiesAtRevision( Car.class, 2 ).traverseRelation( "owner", JoinType.INNER ).traverseRelation( "address", JoinType.INNER ) .addProjection( AuditEntity.selectEntity( true ) ).addOrder( AuditEntity.property( "number" ).asc() ).getResultList(); assertEquals( "Unexpected number of results", 2, list3.size() ); assertEquals( "Unexpected address at index 0", address1.getId(), list3.get( 0 ).getId() ); .addOrder( AuditEntity.property( "age" ).asc() ).addProjection( AuditEntity.selectEntity( false ) ).traverseRelation( "address", JoinType.INNER ) .addProjection( AuditEntity.property( "number" ) ).getResultList(); assertEquals( "Unexpected number of results", 3, list4.size() ); final Object[] index0 = list4.get( 0 );
@Test public void testComparisonOfTwoPropertiesFromDifferentEntities() { AuditReader auditReader = getAuditReader(); // the car where the owner age is equal to the owner address number. Car result = (Car) auditReader.createQuery() .forEntitiesAtRevision( Car.class, 1 ) .traverseRelation( "owner", JoinType.INNER, "p" ) .traverseRelation( "address", JoinType.INNER, "a" ) .up().up().add(AuditEntity.property( "p", "age" ) .eqProperty( "a", "number" ) ).getSingleResult(); assertEquals( "Unexpected car returned", toyota.getId(), result.getId() ); }
private List getEntitiesModifiedAtRevisionUsingAssociationQueryResults(Number revision) { // Without fix HHH-11981, throw org.hibernate.QueryException - Parameter not bound : revision return getAuditReader().createQuery() .forEntitiesModifiedAtRevision( Template.class, revision ) .traverseRelation( "templateType", JoinType.INNER ) .addProjection( AuditEntity.selectEntity( false ) ) .up() .add( AuditEntity.property( "templateType" ).hasChanged() ) .getResultList(); } }
.forEntitiesAtRevision( Customer.class, 1 ) .traverseRelation( "address", JoinType.INNER ) .traverseRelation( "country", JoinType.INNER ) .add( AuditEntity.property( "name" ).eq( "România" ) ) .getResultList(); .forEntitiesAtRevision( Customer.class, 1 ) .traverseRelation( "address", JoinType.LEFT, "a" ) .add( AuditEntity.or( AuditEntity.property( "a", "city" ).eq( "Cluj-Napoca" ), .getResultList(); .forEntitiesAtRevision( Customer.class, 1 ) .traverseRelation( "address", JoinType.INNER, "a" ) .traverseRelation( "country", JoinType.INNER, "cn" ) .up() .up() .add( AuditEntity.disjunction() .forEntitiesAtRevision( Customer.class, revisions.get( revisions.size() - 1 ) ) .traverseRelation( "address", JoinType.INNER, "a" ) .traverseRelation( "country", JoinType.INNER, "cn" ) .up() .up() .add( AuditEntity.property( "a", "city" ).eqProperty( "cn", "name" ) ) .getResultList();
@Test public void testAuditQueryWithJoinedInheritanceSubclassPropertyProjectionWithRelationTraversal() { // HHH-11383 // This test was requested by the reporter so that we have a test that shows Hibernate is // automatically adding "INNER JOIN EntityA_AUD" despite the fact whether the query uses // the traverseRelation API or not. This test makes sure that if the SQL generation is // changed in the future, Envers would properly fail if so. List results = getAuditReader().createQuery().forEntitiesAtRevision( EntityB.class, 1 ) .addProjection( property( "name" ) ) .traverseRelation( "relationToC", JoinType.INNER ) .add( property( "foo" ).like( "bar" ) ) .getResultList(); assertEquals( 2, results.size() ); }
@Test public void testAuditQueryWithJoinedInheritanceUsingWithSemanticsToOne() { List results = getAuditReader().createQuery().forEntitiesAtRevision( EntityB.class, 1 ) .add( disjunction() .add( property( "name" ).like( "b1" ) ) .add( property( "name" ).like( "b2" ) ) ) .traverseRelation( "relationToC", JoinType.INNER ) .add( property( "foo" ).like( "bar" ) ) .up() .traverseRelation( "relationToD", JoinType.INNER ) .add( property( "foo" ).like( "bar" ) ) .getResultList(); assertEquals( 2, results.size() ); }
/** * In a first attempt to implement left joins in Envers, a full join * has been performed and than the entities has been filtered in the * where clause. However, this approach did only work for inner joins * but not for left joins. One of the defects in this approach is, * that audit entities, which have a null 'relatedId' and do match * the query criterias, have been returned multiple times by a query. * This test ensures that this defect is no longer in the current implementation. */ @Test public void testEntitiesWithANullRelatedIdAreNotReturnedMoreThanOnce() { final AuditReader auditReader = getAuditReader(); List<Car> resultList = auditReader.createQuery() .forEntitiesAtRevision( Car.class, 1 ) .traverseRelation( "owner", JoinType.LEFT, "p" ) .up().add( AuditEntity.or( AuditEntity.property( "make" ).eq( "car3" ), AuditEntity.property( "p", "age" ).eq( 10 ) ) ) .getResultList(); assertEquals( "Expected car3 to be returned but only once", 1, resultList.size() ); assertEquals( "Unexpected car at index 0", car3.getId(), resultList.get(0).getId() ); }
.getResultList(); assertEquals( 1, results.size() );
@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() ); }
@Test public void testDisjunctionOfPropertiesFromDifferentEntities() { AuditReader auditReader = getAuditReader(); // all cars where the owner has an age of 20 or lives in an address with number 30. List<Car> resultList = auditReader.createQuery() .forEntitiesAtRevision( Car.class, 1 ) .traverseRelation( "owner", JoinType.INNER, "p" ) .traverseRelation( "address", JoinType.INNER, "a" ) .up().up().add( AuditEntity.disjunction().add(AuditEntity.property( "p", "age" ) .eq( 20 ) ).add( AuditEntity.property( "a", "number" ).eq( 30 ) ) ) .addOrder( AuditEntity.property( "make" ).asc() ).getResultList(); assertEquals( "Expected two cars to be returned, Toyota and VW", 2, resultList.size() ); assertEquals( "Unexpected car at index 0", toyota.getId(), resultList.get(0).getId() ); assertEquals( "Unexpected car at index 1", vw.getId(), resultList.get(1).getId() ); }
@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() ); }
@Test public void testAuditQueryWithJoinedInheritanceUsingWithSemanticsManyToOne() { List results = getAuditReader().createQuery().forEntitiesAtRevision( EntityB.class, 1 ) .add( disjunction() .add( property( "name" ).like( "b1" ) ) .add( property( "name" ).like( "b2" ) ) ) .traverseRelation( "relationToC", JoinType.INNER ) .add( property( "foo" ).like( "bar" ) ) .getResultList(); assertEquals( 2, results.size() ); }
/** * In a first attempt to implement left joins in Envers, a full join * has been performed and than the entities has been filtered in the * where clause. However, this approach did only work for inner joins * but not for left joins. One of the defects in this approach is, * that audit entities, which have a null 'relatedId' are and do not * match the query criterias, still joined to other entities which matched * match the query criterias. * This test ensures that this defect is no longer in the current implementation. */ @Test public void testEntitiesWithANullRelatedIdAreNotJoinedToOtherEntities() { final AuditReader auditReader = getAuditReader(); List<Car> resultList = auditReader.createQuery() .forEntitiesAtRevision( Car.class, 1 ) .traverseRelation( "owner", JoinType.LEFT, "p" ) .up().add( AuditEntity.and( AuditEntity.property( "make" ).eq( "car3" ), AuditEntity.property( "p", "age" ).eq( 30 ) ) ) .getResultList(); assertTrue( "Expected no cars to be returned, because car3 does not have an owner", resultList.isEmpty() ); }
.forEntitiesAtRevision( Customer.class, 1 ) .traverseRelation( "address", JoinType.INNER ) .add( AuditEntity.property( "country" ).eq( "România" ) ) .getResultList();