From hibernate-commits at lists.jboss.org Tue Nov 4 12:44:45 2008 Content-Type: multipart/mixed; boundary="===============6163320973523367121==" MIME-Version: 1.0 From: hibernate-commits at lists.jboss.org To: hibernate-commits at lists.jboss.org Subject: [hibernate-commits] Hibernate SVN: r15501 - in core/trunk/documentation/envers/src/main/docbook/en-US: content and 1 other directory. Date: Tue, 04 Nov 2008 12:44:44 -0500 Message-ID: --===============6163320973523367121== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Author: adamw Date: 2008-11-04 12:44:43 -0500 (Tue, 04 Nov 2008) New Revision: 15501 Added: core/trunk/documentation/envers/src/main/docbook/en-US/Envers_Reference.= xml core/trunk/documentation/envers/src/main/docbook/en-US/content/configura= tion.xml core/trunk/documentation/envers/src/main/docbook/en-US/content/example.x= ml core/trunk/documentation/envers/src/main/docbook/en-US/content/exception= s.xml core/trunk/documentation/envers/src/main/docbook/en-US/content/preface.x= ml core/trunk/documentation/envers/src/main/docbook/en-US/content/quickstar= t.xml core/trunk/documentation/envers/src/main/docbook/en-US/content/revisionl= og.xml Log: HHH-3556: Envers documentation partially migrated Added: core/trunk/documentation/envers/src/main/docbook/en-US/Envers_Refere= nce.xml =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- core/trunk/documentation/envers/src/main/docbook/en-US/Envers_Reference= .xml (rev 0) +++ core/trunk/documentation/envers/src/main/docbook/en-US/Envers_Reference= .xml 2008-11-04 17:44:43 UTC (rev 15501) @@ -0,0 +1,57 @@ + + + + + +]> + + + + + Hibernate Envers - Easy Entity Auditing + Hibernate Envers Reference Documentation + &versionNumber; + &versionNumber; + 1 + + ©rightYear; + ©rightHolder; + + + + + + + + + + + + + + + + Copied: core/trunk/documentation/envers/src/main/docbook/en-US/content/conf= iguration.xml (from rev 15500, core/trunk/documentation/manual/src/main/doc= book/en-US/content/basic_mapping.xml) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- core/trunk/documentation/envers/src/main/docbook/en-US/content/configur= ation.xml (rev 0) +++ core/trunk/documentation/envers/src/main/docbook/en-US/content/configur= ation.xml 2008-11-04 17:44:43 UTC (rev 15501) @@ -0,0 +1,207 @@ + + + + + + + + Configuration + + + To start working with Envers, all configuration that you must do i= s add the event + listeners to persistence.xml, as described in the . + + + + However, as Envers generates some tables, it is possible to set th= e prefix and suffix + that is added to the entity name to create a versions table for an= entity, as well + as set the names of the fields that are generated. + + + + In more detail, here are the properites that you can set: + + + + Envers Configuration Properties + + + + + + + Property name + Default value + Description + + + + + + org.hibernate.envers.auditTablePrefix + + + + + + String that will be prepended to the name of an au= dited entity to create + the name of the entity, that will hold audit infor= mation. + + + + + org.hibernate.envers.auditTableSuffix + + + _audit + + + String that will be appended to the name of an aud= ited entity to create + the name of the entity, that will hold audit infor= mation. If you + audit an entity with a table name Person, in the d= efault setting Envers + will generate a Person_audit ta= ble to store historical data. + + + + + org.hibernate.envers.revisionFieldName + + + REV + + + Name of a field in the audit entity that will hold= the revision number. + + + + + org.hibernate.envers.revisionTypeFieldNa= me + + + REVTYPE + + + Name of a field in the aduit entity that will hold= the type of the + revision (currently, this can be: add, mod, del). + + + + + org.hibernate.envers.revisionOnCollectio= nChange + + + true + + + Should a revision be generated when a not-owned re= lation field changes + (this can be either a collection in a one-to-many = relation, or the field + using "mappedBy" attribute in a one-to-one relatio= n). + + + + + org.hibernate.envers.warnOnUnsupportedTy= pes + + + false + + + TODO: remove + + + + + org.hibernate.envers.doNotAuditOptimisti= cLockingField + + + true + + + When true, properties to be used for optimistic lo= cking, annotated with + @Version, will be automatically= not audited + (their history won't be stored; it normally doesn'= t make sense to store it). + + + + +
+ + + To change the name of the revision table and its fields (the table= , in which the + numbers of revisions and their timestamps are stored), you can use= the + @RevisionEntity annotation. + For more information, see . + + + + To set the value of any of the properties described above, simply = add an entry to + your persistence.xml. For example: + + + <persistence-unit ...> +<provider>org.hibernate.ejb.HibernatePersistence</provider> +<class>...</class> +<properties> + <property name=3D"hibernate.dialect" ... /> + <!-- other hibernate properties --> + + <property name=3D"hibernate.ejb.event.post-insert" + value=3D"org.hibernate.envers.event.VersionsEventListener" /&= gt; + <property name=3D"hibernate.ejb.event.post-update" + value=3D"org.hibernate.envers.event.VersionsEventListener" /&= gt; + <property name=3D"hibernate.ejb.event.post-delete" + value=3D"org.hibernate.envers.event.VersionsEventListener" /&= gt; + <property name=3D"hibernate.ejb.event.pre-collection-update" + value=3D"org.hibernate.envers.event.VersionsEventListener" /&= gt; + <property name=3D"hibernate.ejb.event.pre-collection-remove" + value=3D"org.hibernate.envers.event.VersionsEventListener" /&= gt; + <property name=3D"hibernate.ejb.event.post-collection-recreate" + value=3D"org.hibernate.envers.event.VersionsEventListener" /&= gt; + + <property name=3D"org.hibernate.envers.versionsTableSuffix" value=3D= "_V" /> + <property name=3D"org.hibernate.envers.revisionFieldName" value=3D"v= er_rev" /> + <!-- other envers properties --> +</properties> +</persistence-unit> + + + You can also set the name of the versions table on a per-entity ba= sis, using the + @AuditTable annotation (see also in the javadoc= ). It may be tedious to add this + annotation to every audited entity, so if possible, it's better to= use a prefix/suffix. + + + + If you have a mapping with secondary tables, version tables for th= em will be generated in + the same way (by adding the prefix and suffix). If you wish to ove= rwrite this behaviour, + you can use the @SecondaryAuditTable and + @SecondaryAuditTables annotations. + + + + If you want to audit a relation mapped with @OneToMany+(a= )JoinColumn, + please see for a description of the= additional + @AuditJoinTable annotation that you'll probabl= y want to use. + +
Property changes on: core/trunk/documentation/envers/src/main/docbook/en-US= /content/configuration.xml ___________________________________________________________________ Name: svn:mergeinfo + = Added: core/trunk/documentation/envers/src/main/docbook/en-US/content/examp= le.xml =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- core/trunk/documentation/envers/src/main/docbook/en-US/content/example.= xml (rev 0) +++ core/trunk/documentation/envers/src/main/docbook/en-US/content/example.= xml 2008-11-04 17:44:43 UTC (rev 15501) @@ -0,0 +1,86 @@ + + + + + + + + Short example + + + For example, using the entities defined above, the following code = will generate + revision number 1, which will contain two new Person and + two new Address entities: + + + entityManager.getTransaction().begin(); + +Address address1 =3D new Address("Privet Drive", 4); +Person person1 =3D new Person("Harry", "Potter", address1); + +Address address2 =3D new Address("Grimmauld Place", 12); +Person person2 =3D new Person("Hermione", "Granger", address2); + +entityManager.persist(address1); +entityManager.persist(address2); +entityManager.persist(person1); +entityManager.persist(person2); + +entityManager.getTransaction().commit(); + + + Now we change some entities. This will generate revision number 2,= which will contain + modifications of one person entity and two address entities (as th= e collection of + persons living at address2 and address= 1 changes): + + + entityManager.getTransaction().begin(); + +Address address1 =3D entityManager.find(Address.class, address1.getId()); +Person person2 =3D entityManager.find(Person.class, person2.getId()); + +// Changing the address's house number +address1.setHouseNumber(5) + +// And moving Hermione to Harry +person2.setAddress(address1); + +entityManager.getTransaction().commit(); + + + We can retrieve the old versions (the audit) easily: + + + AuditReader reader =3D AuditReaderFactory.get(entityMa= nager); + +Person person2_rev1 =3D reader.find(Person.class, person2.getId(), 1); +assert person2_rev1.getAddress().equals(new Address("Grimmauld Place", 12)= ); + +Address address1_rev1 =3D reader.find(Address.class, address1.getId(), 1); +assert address1_rev1.getPersons().getSize() =3D=3D 1; + +// and so on + + \ No newline at end of file Copied: core/trunk/documentation/envers/src/main/docbook/en-US/content/exce= ptions.xml (from rev 15500, core/trunk/documentation/manual/src/main/docboo= k/en-US/content/basic_mapping.xml) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- core/trunk/documentation/envers/src/main/docbook/en-US/content/exceptio= ns.xml (rev 0) +++ core/trunk/documentation/envers/src/main/docbook/en-US/content/exceptio= ns.xml 2008-11-04 17:44:43 UTC (rev 15501) @@ -0,0 +1,105 @@ + + + + + + + Mapping exceptions + + + + What isn't and will not be supported + + + Bags (the corresponding Java type is List), as they can contai= n non-unique elements. + The reason is that persisting, for example a bag of String-s, = violates a principle + of relational databases: that each table is a set of tuples. I= n case of bags, + however (which require a join table), if there is a duplicate = element, the two + tuples corresponding to the elements will be the same. Hiberna= te allows this, + however Envers (or more precisely: the database connector) wil= l throw an exception + when trying to persist two identical elements, because of a un= ique constraint violation. + + + + There are at least two ways out if you need bag semantics: + + + + + + use an indexed collection, with the @IndexCol= umn annotation, or + + + + + provide a unique id for your elements with the @CollectionId annotation. + + + + + + + + + What isn't and <emphasis>will</emphasis> be supported</titl= e> + + <orderedlist> + <listitem> + <para> + collections of components + </para> + </listitem> + <listitem> + <para> + relations in components + </para> + </listitem> + <listitem> + <para> + joined and table-per-class inheritance + </para> + </listitem> + </orderedlist> + + </sect1> + + <sect1 id=3D"exceptions-onetomanyjoincolumn" revision=3D"3"> + + <title><literal>@OneToMany</literal>+<literal>@JoinColumn</literal= > + + + When a collection is mapped using these two annotations, Hiber= nate doesn't + generate a join table. Envers, however, has to do this, so tha= t when you read the + revisions in which the related entity has changed, you don't g= et false results. + + + To be able to name the additional join table, there is a speci= al annotation: + @AuditJoinTable, which has similar semantic= s to JPA's + @JoinTable. + + + + + Property changes on: core/trunk/documentation/envers/src/main/docbook/en-US= /content/exceptions.xml ___________________________________________________________________ Name: svn:mergeinfo + = Copied: core/trunk/documentation/envers/src/main/docbook/en-US/content/pref= ace.xml (from rev 15500, core/trunk/documentation/manual/src/main/docbook/e= n-US/content/preface.xml) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- core/trunk/documentation/envers/src/main/docbook/en-US/content/preface.= xml (rev 0) +++ core/trunk/documentation/envers/src/main/docbook/en-US/content/preface.= xml 2008-11-04 17:44:43 UTC (rev 15501) @@ -0,0 +1,84 @@ + + + + + + + Preface + + + The Envers project aims to enable easy auditing of persistent clas= ses. All that you + have to do is annotate your persistent class or some of its proper= ties, that you + want to audit, with @Audited. For each audited = entity, a table + will be created, which will hold the history of changes made to th= e entity. You + can then retrieve and query historical data without much effort. + + + + Similarly to Subversion, the library has a concept of revisions. B= asically, one + transaction is one revision (unless the transaction didn't modify = any audited entities). + As the revisions are global, having a revision number, you can que= ry for various + entities at that revision, retrieving a (partial) view of the data= base at that + revision. You can find a revision number having a date, and the ot= her way round, + you can get the date at which a revision was commited. + + + + The library works with Hibernate and Hibernate Annotations or Enti= ty Manager. + For the auditing to work properly, the entities must have immutabl= e unique + identifiers (primary keys). You can use Envers wherever Hibernate = works: + standalone, inside JBoss AS, with JBoss Seam or Spring. + + + + Some of the features: + + + + + + versioning of all mappings defined by the JPA specificatio= n, except joined and + table-per-class inheritance + + + + + versioning of some Hibernate mappings, which extend JPA, l= ike custom types and + collections/maps of "simple" types (Strings, Integers, etc= .) + (see for one exception) + + + + + logging data for each revision using a "revision entity" + + + + + querying historical data + + + + \ No newline at end of file Property changes on: core/trunk/documentation/envers/src/main/docbook/en-US= /content/preface.xml ___________________________________________________________________ Name: svn:mergeinfo + = Copied: core/trunk/documentation/envers/src/main/docbook/en-US/content/quic= kstart.xml (from rev 15500, core/trunk/documentation/manual/src/main/docboo= k/en-US/content/basic_mapping.xml) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- core/trunk/documentation/envers/src/main/docbook/en-US/content/quicksta= rt.xml (rev 0) +++ core/trunk/documentation/envers/src/main/docbook/en-US/content/quicksta= rt.xml 2008-11-04 17:44:43 UTC (rev 15501) @@ -0,0 +1,148 @@ + + + + + + + Quickstart + + + When configuring your persistence unit (the persistence.xml file),= add the following event + listeners: (this will allow Envers to check if any audited entitie= s were modified) + + + <persistence-unit ...> +<provider>org.hibernate.ejb.HibernatePersistence</provider> +<class>...</class> +<properties> + <property name=3D"hibernate.dialect" ... /> + <!-- other hibernate properties --> + + <property name=3D"hibernate.ejb.event.post-insert" + value=3D"org.hibernate.envers.event.VersionsEventListener" /&= gt; + <property name=3D"hibernate.ejb.event.post-update" + value=3D"org.hibernate.envers.event.VersionsEventListener" /&= gt; + <property name=3D"hibernate.ejb.event.post-delete" + value=3D"org.hibernate.envers.event.VersionsEventListener" /&= gt; + <property name=3D"hibernate.ejb.event.pre-collection-update" + value=3D"org.hibernate.envers.event.VersionsEventListener" /&= gt; + <property name=3D"hibernate.ejb.event.pre-collection-remove" + value=3D"org.hibernate.envers.event.VersionsEventListener" /&= gt; + <property name=3D"hibernate.ejb.event.post-collection-recreate" + value=3D"org.hibernate.envers.event.VersionsEventListener" /&= gt; +</properties> +</persistence-unit> + + + Then, annotate your persistent class with @Audited - this will make all + properties versioned. For example: + + + import org.hibernate.envers.Audited; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.GeneratedValue; +import javax.persistence.Column; + +(a)Entity +(a)Audited // that's the important part :) +public class Person { + @Id + @GeneratedValue + private int id; + + private String name; + + private String surname; + + @ManyToOne + private Address address; + + // add getters, setters, constructors, equals and hashCode here +} + + + And the referenced entity: + + + @Entity +(a)Audited +public class Address { + @Id + @GeneratedValue + private int id; + + private String streetName; + + private Integer houseNumber; + + private Integer flatNumber; + + @OneToMany(mappedBy =3D "address") + private Set<Person> persons; + + // add getters, setters, constructors, equals and hashCode here +} + + + + And that's it! You create, modify and delete the entites as always= . If you look + at the generated schema, you will notice that it is unchanged by a= dding auditing + for the Address and Person entities. Also, the data they hold is t= he same. There are, + however, two new tables - Address_audit and Person_audit, + which store the historical data, whenever you commit a transaction. + + + + Instead of annotating the whole class and auditing all properties,= you can annotate + only some persistent properties with @Audited. = This will cause only + these properties to be audited. + + + + You can access the audit of an entity using the AuditRead= er interface, which you + can obtain when having an open EntityManager. See also the javadoc= s. + + + AuditReader reader =3D AuditReaderFactory.get(entityMa= nager); +Person oldPerson =3D reader.find(Person.class, personId, revision) + + + + The T find(Class<T> cls, Object primaryKey, Number = revision) + method returns an entity with the given primary key, with the data= it contained at + the given revision. If the entity didn't exist at this revision, <= literal>null + is returned. Only the audited properties will be set on the return= ed entity. + The rest will be null. + + + + You can also get a list of revisions at which an entity was modifi= ed using the + getRevisions method, as well as retrieve the da= te, + at which a revision was created using the getRevisionDate= method. + + + Property changes on: core/trunk/documentation/envers/src/main/docbook/en-US= /content/quickstart.xml ___________________________________________________________________ Name: svn:mergeinfo + = Copied: core/trunk/documentation/envers/src/main/docbook/en-US/content/revi= sionlog.xml (from rev 15500, core/trunk/documentation/manual/src/main/docbo= ok/en-US/content/basic_mapping.xml) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- core/trunk/documentation/envers/src/main/docbook/en-US/content/revision= log.xml (rev 0) +++ core/trunk/documentation/envers/src/main/docbook/en-US/content/revision= log.xml 2008-11-04 17:44:43 UTC (rev 15501) @@ -0,0 +1,154 @@ + + + + + + + + Logging data for revisions + + + Envers provides an easy way to log additional data for each revisi= on. You simply need + to annotate one entity with @RevisionEntity, an= d a new instance of + this entity will be persisted when a new revision is created (that= is, whenever an + audited entity is modified). As revisions are global, you can have= at most one revisions entity. + + + + This entity must have at least two properties: + + + + + + an integer- or long-valued property, annotated with @RevisionNumber. Most + often, this will be an auto-generated primary key. + + + + + a long-valued property, annotated with @RevisionT= imestamp. Value of + this property will be automatically set by Envers. + + + + + + You can either add these properties to your entity, or extend + org.hibernate.envers.DefaultRevisionEntity, whi= ch already has those two properties. + + + + To fill the entity with additional data, you'll need to implement = the + org.jboss.envers.RevisionListener interface. It= s newRevision method will + be called when a new revision is created, before persisting the re= vision entity. + The implementation should be stateless and thread-safe. The listen= er then has to be + attached to the revisions entity by specifying it as a parameter t= o the + @RevisionEntity annotation. + + + + A simplest example of a revisions entity, which with each revision= associates the + username of the user making the change is: + + + package org.jboss.envers.example; + +import org.hibernate.envers.RevisionEntity; +import org.hibernate.envers.DefaultRevisionEntity; + +import javax.persistence.Entity; + +(a)Entity +(a)RevisionEntity(ExampleListener.class) +public class ExampleRevEntity extends DefaultRevisionEntity { + private String username; + + public String getUsername() { return username; } + public void setUsername(String username) { this.username =3D username; } +} + + + Or, if you don't want to extend any class: + + + package org.hibernate.envers.example; + +import org.hibernate.envers.RevisionNumber; +import org.hibernate.envers.RevisionTimestamp; +import org.hibernate.envers.RevisionEntity; + +import javax.persistence.Id; +import javax.persistence.GeneratedValue; +import javax.persistence.Entity; + +(a)Entity +(a)RevisionEntity(ExampleListener.class) +public class ExampleRevEntity { + @Id + @GeneratedValue + @RevisionNumber + private int id; + + @RevisionTimestamp + private long timestamp; + + private String username; + + // Getters, setters, equals, hashCode ... +} + + + An example listener, which, if used in a JBoss Seam application, s= tores the + currently logged in user username: + + + package org.hibernate.envers.example; + +import org.hibernate.envers.RevisionListener; +import org.jboss.seam.security.Identity; +import org.jboss.seam.Component; + +public class ExampleListener implements RevisionListener { + public void newRevision(Object revisionEntity) { + ExampleRevEntity exampleRevEntity =3D (ExampleRevEntity) revisionE= ntity; + Identity identity =3D (Identity) Component.getInstance("org.jboss.= seam.security.identity"); + + exampleRevEntity.setUsername(identity.getUsername()); + } +} + + + Having an "empty" revision entity - that is, with no additional pr= operties except the + two mandatory ones - is also an easy way to change the names of th= e table and of the + properties in the revisions table automatically generated by Enver= s. + + + + In case there is no entity annotated with @RevisionEntity= , a default + table will be generated, with the name REVINFO. + + + Property changes on: core/trunk/documentation/envers/src/main/docbook/en-US= /content/revisionlog.xml ___________________________________________________________________ Name: svn:mergeinfo + = --===============6163320973523367121==--