Skip to content

Commit

Permalink
HHH-11886 - Elaborate Envers documentation and switch to actual sourc…
Browse files Browse the repository at this point in the history
…e code examples

Migrate code snippets to test cases for Join relations queries with multiple predicates
  • Loading branch information
vladmihalcea committed Sep 7, 2017
1 parent 742d8be commit ab98bcb
Show file tree
Hide file tree
Showing 7 changed files with 324 additions and 62 deletions.
103 changes: 59 additions & 44 deletions documentation/src/main/asciidoc/userguide/chapters/envers/Envers.adoc
Expand Up @@ -997,7 +997,7 @@ include::{sourcedir}/QueryAuditTest.java[tags=envers-querying-entity-relation-le

Like any other query, constraints may be added to restrict the results.

For example, to find all `Customers` entities whose addresses are in `România`,
For example, to find a `Customers` entities at a given revision whose addresses are in `România`,
you can use the following query:

[[envers-querying-entity-relation-join-restriction]]
Expand All @@ -1016,8 +1016,8 @@ include::{extrasdir}/envers-querying-entity-relation-join-restriction.sql[]

It is also possible to traverse beyond the first relation in an entity graph.

For example, to find all `Customer` entities
where the country entity belonging to the address attribute is `România`:
For example, to find all `Customer` entities at a given revision
with the country attribute of the address property being `România`:

[[envers-querying-entity-relation-nested-join-restriction]]
.Filtering a nested join relation with a WHERE clause predicate
Expand All @@ -1033,63 +1033,78 @@ include::{extrasdir}/envers-querying-entity-relation-nested-join-restriction.sql
----
====

Complex constraints may also be added that are applicable to properties of nested relations or the base query entity or
relation state, such as testing for `null`. For example, the following query illustrates how to find all `Car` entities where
the owner's age is `20` or that the car has _no_ owner:
Constraints may also be added to the properties of nested joined relations, such as testing for `null`.

[source,java]
For example, the following query illustrates how to find all `Customer` entities at a given revision
having the `address` in `Cluj-Napoca` or the `address` does _not_ have any country entity reference:

[[envers-querying-entity-relation-join-multiple-restrictions]]
.Filtering a join relation using multiple predicates
====
[source, JAVA, indent=0]
----
include::{sourcedir}/QueryAuditAdressCountryTest.java[tags=envers-querying-entity-relation-join-multiple-restrictions]
----
AuditQuery query = getAuditReader().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() );
[source, SQL, indent=0]
----
include::{extrasdir}/envers-querying-entity-relation-join-multiple-restrictions.sql[]
----
====

[NOTE]
====
Queries can use the `up` method to navigate back up the entity graph.
====

Disjunction criterion may also be applied to relation join queries. For example, the following query will find all
`Car` entities where the owner's age is `20` or that the owner lives at an address where the street number equals `1234`:
Disjunction criterion may also be applied to relation join queries.

[source,java]
For example, the following query will find all `Customer` entities at a given revision
where the country name is `România` or that the `Customer` lives in `Cluj-Napoca`:

[[envers-querying-entity-relation-nested-join-multiple-restrictions]]
.Filtering a nested join relation using multiple predicates
====
[source, JAVA, indent=0]
----
include::{sourcedir}/QueryAuditAdressCountryTest.java[tags=envers-querying-entity-relation-nested-join-multiple-restrictions]
----
AuditQuery query = getAuditReader().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", "streetNumber" ).eq( 1234 )
)
)
.addOrder( AuditEntity.property( "make" ).asc() );
[source, SQL, indent=0]
----
include::{extrasdir}/envers-querying-entity-relation-nested-join-multiple-restrictions.sql[]
----
====

Lastly, this example illustrates how related entity properties can be compared as a constraint. This query shows how to
find the `Car` entities where the owner's `age` equals the `streetNumber` of where the owner lives:
Lastly, this example illustrates how related entity properties can be compared in a single constraint.

[source,java]
Assuming, the `Customer` and the `Address` were previously changed as follows:

[[envers-querying-entity-relation-nested-join-multiple-restrictions-combined-entities]]
.Changing the `Address` to match the `Country` name
====
[source, JAVA, indent=0]
----
AuditQuery query = getAuditReader().createQuery()
.forEntitiesAtRevision( Car.class, 1 )
.traverseRelation( "owner", JoinType.INNER, "p" )
.traverseRelation( "address", JoinType.INNER, "a" )
.up()
.up()
.add( AuditEntity.property( "p", "age" ).eqProperty( "a", "streetNumber" ) );
include::{sourcedir}/QueryAuditAdressCountryTest.java[tags=envers-querying-entity-relation-nested-join-multiple-restrictions-combined-entities]
----
====

The following query shows how to find the `Customer` entities
where the `city` property of the `address` attribute equals the `name` of the associated `country` attribute.

[[envers-querying-entity-relation-nested-join-multiple-restrictions-combined]]
.Filtering a nested join relation using multiple predicates
====
[source, JAVA, indent=0]
----
include::{sourcedir}/QueryAuditAdressCountryTest.java[tags=envers-querying-entity-relation-nested-join-multiple-restrictions-combined]
----
[source, SQL, indent=0]
----
include::{extrasdir}/envers-querying-entity-relation-nested-join-multiple-restrictions-combined.sql[]
----
====

[[envers-conditional-auditing]]
=== Conditional auditing
Expand Down
@@ -0,0 +1,48 @@
select
c.id as id1_5_,
c.REV as REV2_5_,
c.REVTYPE as REVTYPE3_5_,
c.REVEND as REVEND4_5_,
c.created_on as created_5_5_,
c.firstName as firstNam6_5_,
c.lastName as lastName7_5_,
c.address_id as address_8_5_
from
Customer_AUD c
left outer join
Address_AUD a
on (
c.address_id=a.id
or (
c.address_id is null
)
and (
a.id is null
)
)
where
c.REV<=?
and c.REVTYPE<>?
and (
c.REVEND>?
or c.REVEND is null
)
and (
a.REV is null
or a.REV<=?
and (
a.REVEND>?
or a.REVEND is null
)
)
and (
a.city=?
or a.country_id is null
)

-- binding parameter [1] as [INTEGER] - [1]
-- binding parameter [2] as [INTEGER] - [2]
-- binding parameter [3] as [INTEGER] - [1]
-- binding parameter [4] as [INTEGER] - [1]
-- binding parameter [5] as [INTEGER] - [1]
-- binding parameter [6] as [VARCHAR] - [Cluj-Napoca]
@@ -0,0 +1,59 @@
select
cu.id as id1_5_,
cu.REV as REV2_5_,
cu.REVTYPE as REVTYPE3_5_,
cu.REVEND as REVEND4_5_,
cu.created_on as created_5_5_,
cu.firstName as firstNam6_5_,
cu.lastName as lastName7_5_,
cu.address_id as address_8_5_
from
Customer_AUD cu
inner join
Address_AUD a
on (
cu.address_id=a.id
or (
cu.address_id is null
)
and (
a.id is null
)
)
inner join
Country_AUD cr
on (
a.country_id=cr.id
or (
a.country_id is null
)
and (
cr.id is null
)
)
where
cu.REV<=?
and cu.REVTYPE<>?
and a.city=cr.name
and (
cu.REVEND>?
or cu.REVEND is null
)
and a.REV<=?
and (
a.REVEND>?
or a.REVEND is null
)
and cr.REV<=?
and (
cr.REVEND>?
or cr.REVEND is null
)

-- binding parameter [1] as [INTEGER] - [2]
-- binding parameter [2] as [INTEGER] - [2]
-- binding parameter [3] as [INTEGER] - [2]
-- binding parameter [4] as [INTEGER] - [2]
-- binding parameter [5] as [INTEGER] - [2]
-- binding parameter [6] as [INTEGER] - [2]
-- binding parameter [7] as [INTEGER] - [2]
@@ -0,0 +1,66 @@
select
cu.id as id1_5_,
cu.REV as REV2_5_,
cu.REVTYPE as REVTYPE3_5_,
cu.REVEND as REVEND4_5_,
cu.created_on as created_5_5_,
cu.firstName as firstNam6_5_,
cu.lastName as lastName7_5_,
cu.address_id as address_8_5_
from
Customer_AUD cu
inner join
Address_AUD a
on (
cu.address_id=a.id
or (
cu.address_id is null
)
and (
a.id is null
)
)
inner join
Country_AUD co
on (
a.country_id=co.id
or (
a.country_id is null
)
and (
co.id is null
)
)
where
cu.REV<=?
and cu.REVTYPE<>?
and (
cu.REVEND>?
or cu.REVEND is null
)
and (
a.city=?
or co.name=?
)
and a.REV<=?
and (
a.REVEND>?
or a.REVEND is null
)
and co.REV<=?
and (
co.REVEND>?
or co.REVEND is null
)
order by
cu.created_on asc

-- binding parameter [1] as [INTEGER] - [1]
-- binding parameter [2] as [INTEGER] - [2]
-- binding parameter [3] as [INTEGER] - [1]
-- binding parameter [4] as [VARCHAR] - [Cluj-Napoca]
-- binding parameter [5] as [VARCHAR] - [România]
-- binding parameter [6] as [INTEGER] - [1]
-- binding parameter [7] as [INTEGER] - [1]
-- binding parameter [8] as [INTEGER] - [1]
-- binding parameter [9] as [INTEGER] - [1]
Expand Up @@ -98,6 +98,7 @@ public static class Person {
@Id
@GeneratedValue
private Long id;

@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<Address> addresses = new ArrayList<>();

Expand Down

0 comments on commit ab98bcb

Please sign in to comment.