HHH-11886 - Elaborate Envers documentation and switch to actual source code examples
Add examples about reading revisions and reconstructing entity state
This commit is contained in:
parent
d671fe1391
commit
7c5213171b
|
@ -106,7 +106,81 @@ The `REVTYPE` column value is taken from the https://docs.jboss.org/hibernate/or
|
|||
|=================================
|
||||
|
||||
The audit (history) of an entity can be accessed using the `AuditReader` interface, which can be obtained having an open `EntityManager` or `Session` via the `AuditReaderFactory`.
|
||||
See the https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/envers/AuditReaderFactory.html[Javadocs] for these classes for details on the functionality offered.
|
||||
|
||||
[[envers-audited-revisions-example]]
|
||||
.Getting a list of revisions for the `Customer` entity
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/AuditTest.java[tags=envers-audited-revisions-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/envers-audited-revisions-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
Using the previously fetched revisions, we can now inspect the state of the `Customer` entity at that particular revision:
|
||||
|
||||
[[envers-audited-rev1-example]]
|
||||
.Getting the first revision for the `Customer` entity
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/AuditTest.java[tags=envers-audited-rev1-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/envers-audited-rev1-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
When executing the aforementioned SQL query, there are two parameters:
|
||||
|
||||
revision_number::
|
||||
The first parameter marks the revision number we are interested in or the latest one that exist up to this particular revision.
|
||||
revision_type::
|
||||
The second parameter specifies that we are not interested in `DEL` `RevisionType` so that deleted entries are filtered out.
|
||||
|
||||
The same goes for the second revision associated to the `UPDATE` statement.
|
||||
|
||||
[[envers-audited-rev2-example]]
|
||||
.Getting the second revision for the `Customer` entity
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/AuditTest.java[tags=envers-audited-rev2-example]
|
||||
----
|
||||
====
|
||||
|
||||
For the deleted entity revision, Envers throws a `NoResultException` since the entity was no longer valid at that revision.
|
||||
|
||||
[[envers-audited-rev3-example]]
|
||||
.Getting the third revision for the `Customer` entity
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/AuditTest.java[tags=envers-audited-rev3-example]
|
||||
----
|
||||
====
|
||||
|
||||
You can use the
|
||||
https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/envers/AuditReader.html#find-java.lang.Class-java.lang.String-java.lang.Object-java.lang.Number-boolean-[`find(Class<T> cls, String entityName, Object primaryKey, Number revision, boolean includeDeletions)`]
|
||||
method to get the deleted entity revision so that, instead of a `NoResultException`,
|
||||
all attributes, except for the entity identifier, are going to be `null`.
|
||||
|
||||
[[envers-audited-rev4-example]]
|
||||
.Getting the third revision for the `Customer` entity without getting a `NoResultException`
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/AuditTest.java[tags=envers-audited-rev4-example]
|
||||
----
|
||||
====
|
||||
|
||||
See the https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/envers/AuditReader.html[Javadocs] for details on other functionality offered.
|
||||
|
||||
[[envers-configuration]]
|
||||
=== Configuration
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
select
|
||||
c.id as id1_1_,
|
||||
c.REV as REV2_1_,
|
||||
c.REVTYPE as REVTYPE3_1_,
|
||||
c.created_on as created_4_1_,
|
||||
c.firstName as firstNam5_1_,
|
||||
c.lastName as lastName6_1_
|
||||
from
|
||||
Customer_AUD c
|
||||
where
|
||||
c.REV = (
|
||||
select
|
||||
max( c_max.REV )
|
||||
from
|
||||
Customer_AUD c_max
|
||||
where
|
||||
c_max.REV <= ?
|
||||
and c.id = c_max.id
|
||||
)
|
||||
and c.REVTYPE <> ?
|
||||
|
||||
-- binding parameter [1] as [INTEGER] - [1]
|
||||
-- binding parameter [2] as [INTEGER] - [2]
|
|
@ -0,0 +1,13 @@
|
|||
select
|
||||
c.REV as col_0_0_
|
||||
from
|
||||
Customer_AUD c
|
||||
cross join
|
||||
REVINFO r
|
||||
where
|
||||
c.id = ?
|
||||
and c.REV = r.REV
|
||||
order by
|
||||
c.REV asc
|
||||
|
||||
-- binding parameter [1] as [BIGINT] - [1]
|
|
@ -7,19 +7,29 @@
|
|||
package org.hibernate.userguide.envers;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.NonUniqueResultException;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
import org.hibernate.envers.AuditReader;
|
||||
import org.hibernate.envers.AuditReaderFactory;
|
||||
import org.hibernate.envers.Audited;
|
||||
import org.hibernate.envers.exception.AuditException;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
|
||||
import org.hibernate.test.legacy.Custom;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
|
@ -59,6 +69,70 @@ public class AuditTest extends BaseEntityManagerFunctionalTestCase {
|
|||
entityManager.remove( customer );
|
||||
//end::envers-audited-delete-example[]
|
||||
} );
|
||||
|
||||
//tag::envers-audited-revisions-example[]
|
||||
List<Number> revisions = doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
return AuditReaderFactory.get( entityManager ).getRevisions(
|
||||
Customer.class,
|
||||
1L
|
||||
);
|
||||
} );
|
||||
//end::envers-audited-revisions-example[]
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
//tag::envers-audited-rev1-example[]
|
||||
Customer customer = (Customer) AuditReaderFactory.get( entityManager )
|
||||
.createQuery()
|
||||
.forEntitiesAtRevision( Customer.class, revisions.get( 0 ) )
|
||||
.getSingleResult();
|
||||
|
||||
assertEquals("Doe", customer.getLastName());
|
||||
//end::envers-audited-rev1-example[]
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
//tag::envers-audited-rev2-example[]
|
||||
Customer customer = (Customer) AuditReaderFactory.get( entityManager )
|
||||
.createQuery()
|
||||
.forEntitiesAtRevision( Customer.class, revisions.get( 1 ) )
|
||||
.getSingleResult();
|
||||
|
||||
assertEquals("Doe Jr.", customer.getLastName());
|
||||
//end::envers-audited-rev2-example[]
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
//tag::envers-audited-rev3-example[]
|
||||
try {
|
||||
Customer customer = (Customer) AuditReaderFactory.get( entityManager )
|
||||
.createQuery()
|
||||
.forEntitiesAtRevision( Customer.class, revisions.get( 2 ) )
|
||||
.getSingleResult();
|
||||
|
||||
fail("The Customer was deleted at this revision: " + revisions.get( 2 ));
|
||||
}
|
||||
catch (NoResultException expected) {
|
||||
}
|
||||
//end::envers-audited-rev3-example[]
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
//tag::envers-audited-rev4-example[]
|
||||
Customer customer = (Customer) AuditReaderFactory.get( entityManager )
|
||||
.createQuery()
|
||||
.forEntitiesAtRevision(
|
||||
Customer.class,
|
||||
Customer.class.getName(),
|
||||
revisions.get( 2 ),
|
||||
true )
|
||||
.getSingleResult();
|
||||
|
||||
assertEquals( Long.valueOf( 1L ), customer.getId() );
|
||||
assertNull( customer.getFirstName() );
|
||||
assertNull( customer.getLastName() );
|
||||
assertNull( customer.getCreatedOn() );
|
||||
//end::envers-audited-rev4-example[]
|
||||
} );
|
||||
}
|
||||
|
||||
//tag::envers-audited-mapping-example[]
|
||||
|
|
Loading…
Reference in New Issue