+ All Categories
Home > Technology > Devoxx 2012 hibernate envers

Devoxx 2012 hibernate envers

Date post: 21-Jun-2015
Category:
Upload: romain-linsolas
View: 2,183 times
Download: 0 times
Share this document with a friend
Description:
My presentation (Quickie) about Hibernate Envers, made at Devoxx 2012.
Popular Tags:
24
Transcript
Page 1: Devoxx 2012   hibernate envers
Page 2: Devoxx 2012   hibernate envers

Easy Entity AuditingWith Hibernate Envers

Romain LinsolasJava & Web Developer

Société Générale

@romaintaz

Page 3: Devoxx 2012   hibernate envers

3

Romain Linsolas

Who am I?■ Java & Web developer;■ Technical architect, Software Factory gardener;■ @ Société Générale (french bank)

http://linsolas.free.fr/wordpress

@romaintaz

https://github.com/linsolas

Page 4: Devoxx 2012   hibernate envers

(1) What is Hibernate Envers?

Page 5: Devoxx 2012   hibernate envers

Definition

Hibernate Envers

Hibernate module to enable easy auditing of persistent classes!

Audit = keep a revision of your entity after every "event" (insert, update, delete)

Available since 2009…

http://www.jboss.org/envers

http://docs.jboss.org/envers/docs/index.html

http://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html/ch15.html

Page 6: Devoxx 2012   hibernate envers

(2) Activation

Page 7: Devoxx 2012   hibernate envers

7

Add the Envers library in classpath

<!-- Requires:

* Hibernate 3+

* Hibernate annotations -->

<dependency>

<groupId>org.hibernate</groupId>

<artifactId>hibernate-envers</artifactId>

<version>4.1.8.Final</version>

</dependency>

Page 8: Devoxx 2012   hibernate envers

(3) Start the audit

Page 9: Devoxx 2012   hibernate envers

9

Audit a simple entity class@Entity

@Audited

public class Person {

@Id @GeneratedValue

private int id;

private String name;

private String surname;

@ManyToOne

private Address address;

// getters, setters, constructors, equals and hashCode…

}

Page 10: Devoxx 2012   hibernate envers

10

Some useful Envers @nnotations@Audited

@AuditTable(“T_PERSON_AUDIT”)

public class Person {

@NotAudited

private String comments;

@AuditJoinTable(name=“T_PERSON_ADDRESS_AUDIT”,

inverseJoinColumns=@JoinColumn(name=“ADDRESS_ID”))

public List<Address> address;

}

Page 11: Devoxx 2012   hibernate envers

What about the database?

Table T_PERSON

Id Name Surname Comments

Table T_PERSON_AUD

Id REV Name Surname REVTYPE

Table REVINFO

REV REVTSTMP (additional info)

0 Add

1 Mod

2 Del

Page 12: Devoxx 2012   hibernate envers

12

Additional information in revisions@Entity

@RevisionEntity(UsernameRevisionListener.class)

public class MyEntityRevision extends DefaultRevisionEntity {

private String username; // + getter / setter

}

public class UsernameRevisionListener implements RevisionListener {

@Override

public void newRevision(Object revisionEntity) {

((MyEntityRevision) revisionEntity).setUsername(getCurrentUsername());

}

}

Page 13: Devoxx 2012   hibernate envers

Tracking modified fields<property name="org.hibernate.envers.global_with_modified_flag" value="true"/>

Or

@Audited(withModifiedFlag = true)

private String myField;

Table T_PERSON_AUD

Id REV Name Name_MOD Surname Surname_MOD REVTYPE

Still an experimental feature…

Page 14: Devoxx 2012   hibernate envers

(4) Query audit information

Page 15: Devoxx 2012   hibernate envers

15

AuditReader// Get all the revisions of my current object

int personId = somePerson.getId();

AuditReader auditReader = AuditReaderFactory.get(entityManager);

List<Number> allRevisions = auditReader.getRevisions(Person.class, personId);

for (Number n: allRevisions) {

Person p = auditReader.find(Person.class, personId, n);

System.out.printf("\t[Rev #%1$s] > %2$s\n", n, p);

}

[Rev #1] > Person { id=10, name='Romain', surname='', comments=''}

[Rev #3] > Person { id=10, name='Romain', surname='Linsolas', comments=''}

[Rev #4] > null

Page 16: Devoxx 2012   hibernate envers

16

AuditQuery - 1

AuditQuery query1 = auditReader.createQuery()

.forEntitiesAtRevision(Person.class, 42);

List<Person> persons = query1.getResultList();

Person { id=11, name='Chuck', surname='Norris', comments=''}

Person { id=10, name='Romain', surname='Linsolas', comments=''}

Page 17: Devoxx 2012   hibernate envers

17

AuditQuery - 2

AuditQuery query2 = auditReader.createQuery()

.forRevisionsOfEntity(Person.class, false, true);

List<Object[]> revisions = query2.getResultList();

Person EntityRevision REVTYPE{ id=10, name='Romain', surname='', comments='' }

{id=1, timestamp=1352936106653, username='Devoxx'} ADD

{ id=11, name='Chuck', surname='Norris', comments='' }

{id=2, timestamp=1352936106669, username='Devoxx'} ADD

{ id=10, name='Romain', surname='Linsolas', comments='' }

{id=3, timestamp=1352936106687, username='Devoxx'} MOD

{ id=10, name='null', surname='', comments='' }

{id=4, timestamp=1352936106734, username='Devoxx'} DEL

Page 18: Devoxx 2012   hibernate envers

18

AuditQuery - 3

List<Person> persons = auditReader.createQuery()

.forEntitiesAtRevision(Person.class, 42)

.addOrder(AuditEntity.property(“surname”).desc())

.add(AuditEntity.relatedId(“address”).eq(theAddressId))

.setFirstResult(4)

.setMaxResults(2)

.getResultList();

Page 19: Devoxx 2012   hibernate envers

AuditQuery - 4

AuditQuery query = auditReader().createQuery()

.forEntitiesAtRevision(Person.class, 42)

.add(AuditEntity.property("surname").hasChanged())

.add(AuditEntity.property("name").hasNotChanged());

Page 20: Devoxx 2012   hibernate envers

Demo

https://github.com/linsolas/devoxx-envers

Page 21: Devoxx 2012   hibernate envers

To summarize…

Pros

Really easy to use!

Configurable

Ready-to-use audit query tool

Fully integrated in Hibernate

No similar project (?)

Cons

Require Hibernate

Not compatible with Hibernate XML configuration (cf. HHH-3887)

Page 22: Devoxx 2012   hibernate envers

Q&A

Page 23: Devoxx 2012   hibernate envers

(5) Annexes

Page 24: Devoxx 2012   hibernate envers

24

Register Envers Listener<!-- Needed in persistence.xml or Hibernate configuration if you use older versions of Envers (3.x) -->

<property name="hibernate.ejb.event.post-insert"

value="org.hibernate.ejb.event.EJB3PostInsertEventListener,org.hibernate.envers.event.AuditEventListener" />

<property name="hibernate.ejb.event.post-update"

value="org.hibernate.ejb.event.EJB3PostUpdateEventListener,org.hibernate.envers.event.AuditEventListener" />

<property name="hibernate.ejb.event.post-delete"

value="org.hibernate.ejb.event.EJB3PostDeleteEventListener,org.hibernate.envers.event.AuditEventListener" />

<property name="hibernate.ejb.event.pre-collection-update"

value="org.hibernate.envers.event.AuditEventListener" />

<property name="hibernate.ejb.event.pre-collection-remove"

value="org.hibernate.envers.event.AuditEventListener" />

<property name="hibernate.ejb.event.post-collection-recreate"

value="org.hibernate.envers.event.AuditEventListener" />


Recommended