From 742df1f3fa13d8e6acff763b2f5e3b7ea9cd05a3 Mon Sep 17 00:00:00 2001 From: Vlad Mihalcea Date: Mon, 31 Jul 2017 16:25:18 +0300 Subject: [PATCH] HHH-11886 - Elaborate Envers documentation and switch to actual source code examples Add example for property-based changes --- .../userguide/chapters/envers/Envers.adoc | 30 +++++ ...rs-tracking-properties-changes-example.sql | 39 ++++++ ...ing-properties-changes-mapping-example.sql | 12 ++ .../envers/ModifiedFlagsAuditTest.java | 116 ++++++++++++++++++ 4 files changed, 197 insertions(+) create mode 100644 documentation/src/main/asciidoc/userguide/chapters/envers/extras/envers-tracking-properties-changes-example.sql create mode 100644 documentation/src/main/asciidoc/userguide/chapters/envers/extras/envers-tracking-properties-changes-mapping-example.sql create mode 100644 documentation/src/test/java/org/hibernate/userguide/envers/ModifiedFlagsAuditTest.java diff --git a/documentation/src/main/asciidoc/userguide/chapters/envers/Envers.adoc b/documentation/src/main/asciidoc/userguide/chapters/envers/Envers.adoc index 66f5f796eb..613910066d 100644 --- a/documentation/src/main/asciidoc/userguide/chapters/envers/Envers.adoc +++ b/documentation/src/main/asciidoc/userguide/chapters/envers/Envers.adoc @@ -633,6 +633,36 @@ This is due to the fact that every tracked property has to have an accompanying Of course it is Envers job to fill these columns accordingly - no additional work by the developer is required. Because of costs mentioned, it is recommended to enable the feature selectively, when needed with use of the granular configuration means described above. +[[envers-tracking-properties-changes-mapping-example]] +.Mapping for tracking entity changes at property level +==== +[source, JAVA, indent=0] +---- +include::{sourcedir}/ModifiedFlagsAuditTest.java[tags=envers-tracking-properties-changes-mapping-example] +---- + +[source, SQL, indent=0] +---- +include::{extrasdir}/envers-tracking-properties-changes-mapping-example.sql[] +---- +==== + +As you can see, every property features a `_MOD` column (e.g. `createdOn_MOD`) in the audit log. + +[[envers-tracking-properties-changes-example]] +.Tracking entity changes at property level example +==== +[source, JAVA, indent=0] +---- +include::{sourcedir}/ModifiedFlagsAuditTest.java[tags=envers-tracking-properties-changes-example] +---- + +[source, SQL, indent=0] +---- +include::{extrasdir}/envers-tracking-properties-changes-example.sql[] +---- +==== + To see how "Modified Flags" can be utilized, check out the very simple query API that uses them: <>. [[envers-queries]] diff --git a/documentation/src/main/asciidoc/userguide/chapters/envers/extras/envers-tracking-properties-changes-example.sql b/documentation/src/main/asciidoc/userguide/chapters/envers/extras/envers-tracking-properties-changes-example.sql new file mode 100644 index 0000000000..9be6480119 --- /dev/null +++ b/documentation/src/main/asciidoc/userguide/chapters/envers/extras/envers-tracking-properties-changes-example.sql @@ -0,0 +1,39 @@ +update + Customer +set + created_on = ?, + firstName = ?, + lastName = ? +where + id = ? + +-- binding parameter [1] as [TIMESTAMP] - [2017-07-31 15:58:20.342] +-- binding parameter [2] as [VARCHAR] - [John] +-- binding parameter [3] as [VARCHAR] - [Doe Jr.] +-- binding parameter [4] as [BIGINT] - [1] + +insert +into + REVINFO + (REV, REVTSTMP) +values + (null, ?) + +-- binding parameter [1] as [BIGINT] - [1501505900439] + +insert +into + Customer_AUD + (REVTYPE, created_on, createdOn_MOD, firstName, firstName_MOD, lastName, lastName_MOD, id, REV) +values + (?, ?, ?, ?, ?, ?, ?, ?, ?) + +-- binding parameter [1] as [INTEGER] - [1] +-- binding parameter [2] as [TIMESTAMP] - [2017-07-31 15:58:20.342] +-- binding parameter [3] as [BOOLEAN] - [false] +-- binding parameter [4] as [VARCHAR] - [John] +-- binding parameter [5] as [BOOLEAN] - [false] +-- binding parameter [6] as [VARCHAR] - [Doe Jr.] +-- binding parameter [7] as [BOOLEAN] - [true] +-- binding parameter [8] as [BIGINT] - [1] +-- binding parameter [9] as [INTEGER] - [2] \ No newline at end of file diff --git a/documentation/src/main/asciidoc/userguide/chapters/envers/extras/envers-tracking-properties-changes-mapping-example.sql b/documentation/src/main/asciidoc/userguide/chapters/envers/extras/envers-tracking-properties-changes-mapping-example.sql new file mode 100644 index 0000000000..8cf1c2896e --- /dev/null +++ b/documentation/src/main/asciidoc/userguide/chapters/envers/extras/envers-tracking-properties-changes-mapping-example.sql @@ -0,0 +1,12 @@ +create table Customer_AUD ( + id bigint not null, + REV integer not null, + REVTYPE tinyint, + created_on timestamp, + createdOn_MOD boolean, + firstName varchar(255), + firstName_MOD boolean, + lastName varchar(255), + lastName_MOD boolean, + primary key (id, REV) +) \ No newline at end of file diff --git a/documentation/src/test/java/org/hibernate/userguide/envers/ModifiedFlagsAuditTest.java b/documentation/src/test/java/org/hibernate/userguide/envers/ModifiedFlagsAuditTest.java new file mode 100644 index 0000000000..c690dd95ec --- /dev/null +++ b/documentation/src/test/java/org/hibernate/userguide/envers/ModifiedFlagsAuditTest.java @@ -0,0 +1,116 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +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.Temporal; +import javax.persistence.TemporalType; + +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.envers.AuditReaderFactory; +import org.hibernate.envers.Audited; +import org.hibernate.envers.DefaultRevisionEntity; +import org.hibernate.envers.RevisionEntity; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; + +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 + */ +public class ModifiedFlagsAuditTest extends BaseEntityManagerFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Customer.class + }; + } + + @Test + public void test() { + doInJPA( this::entityManagerFactory, entityManager -> { + Customer customer = new Customer(); + customer.setId( 1L ); + customer.setFirstName( "John" ); + customer.setLastName( "Doe" ); + + entityManager.persist( customer ); + } ); + + doInJPA( this::entityManagerFactory, entityManager -> { + //tag::envers-tracking-properties-changes-example[] + Customer customer = entityManager.find( Customer.class, 1L ); + customer.setLastName( "Doe Jr." ); + //end::envers-tracking-properties-changes-example[] + } ); + } + + //tag::envers-tracking-properties-changes-mapping-example[] + @Audited(withModifiedFlag = true) + @Entity(name = "Customer") + public static class Customer { + + @Id + private Long id; + + private String firstName; + + private String lastName; + + @Temporal( TemporalType.TIMESTAMP ) + @Column(name = "created_on") + @CreationTimestamp + private Date createdOn; + + //Getters and setters are omitted for brevity + //end::envers-tracking-properties-changes-mapping-example[] + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public Date getCreatedOn() { + return createdOn; + } + + public void setCreatedOn(Date createdOn) { + this.createdOn = createdOn; + } + //tag::envers-tracking-properties-changes-mapping-example[] + } + //end::envers-tracking-properties-changes-mapping-example[] +}