Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Teneo/Hibernate/Auditing"

 
(23 intermediate revisions by one other user not shown)
Line 2: Line 2:
  
 
Teneo supports auditing (from November 2012), a summary of the functionality:
 
Teneo supports auditing (from November 2012), a summary of the functionality:
* auditing can be enabled for specific types
+
* auditing can be enabled/disabled for the complete model or for specific types
* earlier versions of objects can be retrieved
+
 
* possible to navigate/iterate over the history of an object
 
* possible to navigate/iterate over the history of an object
* query for version history using attribute and ereference values
+
* use HQL to query for version history using attribute and ereference values
  
 
== Enable auditing ==
 
== Enable auditing ==
  
Auditing can be enabled by calling setAuditing(true) on the datastore or setting the enable auditing option to true (see next section). To prevent auditing of specific types you can use the @NoAuditing annotation. Set this annotation in the EMF EAnnotation of the EClass using source 'teneo.jpa' and key 'value'.
+
Auditing can be enabled by calling setAuditing(true) on the datastore or setting the enable auditing option to true (see the 'Auditing Options' section). To prevent auditing of specific types you can use the @NoAuditing annotation. Set this annotation in the EMF EAnnotation of the EClass using source 'teneo.jpa' and key 'value'.
  
 
== Audit Entries ==
 
== Audit Entries ==
  
When auditing is enabled then each database action on an entity is persisted in a separate table. Each EClass will store its audit entries in a separate table. Teneo will store three types of events: ADD, UPDATE and DELETE. Teneo provides an api to retrieve the audit entries, this is described in more detail below.
+
When auditing is enabled then at each database action on an entity its state is persisted in a separate table. To support this persistence, Teneo will generate a separate additional type for each audited type, these audit types/eclasses are generated and mapped at runtime.
 +
 
 +
Each audit EClass models the audit entries for a domain EClass, its audit entries are stored in a separate table. Teneo will store three types of events: ADD, UPDATE and DELETE.  
 +
 
 +
Teneo provides an api to retrieve the audit entries, this is described in more detail below.
  
 
== Auditing Options ==
 
== Auditing Options ==
  
Teneo has many [[Teneo/Hibernate/Configuration_Options|configuration options]], three options are specific for auditing:
+
Teneo has many [[Teneo/Hibernate/Configuration_Options|configuration options]], the following options are specific for auditing:
 
* ENABLE_AUDITING (teneo.mapping.auditing.enable): default is false, enables auditing if set to "true"
 
* ENABLE_AUDITING (teneo.mapping.auditing.enable): default is false, enables auditing if set to "true"
 +
* AUDITING_PRUNE_OLD_ENTRIES_DAYS (teneo.mapping.auditing.prune.days): default is 0, if set > 0, then audit entries older than this number of days are deleted, this is done during the operation of the system (every 1000 commits a prune check is done and old entries are removed).
 +
* AUDITING_PRUNE_COMMIT_INTERVAL (teneo.mapping.auditing.prune.commit.interval): default is 1000, defines the number of commits before Teneo checks for to-be-pruned entries. Only commits which update the audit entry tables are counted. So with the default, every 1000 commits, all audit tables are checked for expired entries.
 +
* AUDITING_DB_SCHEMA (teneo.mapping.auditing.database.schema): database schema for the auditing tables, default is not set.
 
* AUDITING_ENTITY_PREFIX (teneo.naming.auditing.entity.prefix): defines the prefix which is set before the EClass name, this is used to compute the entity name and the table name used to store auditing entries.
 
* AUDITING_ENTITY_PREFIX (teneo.naming.auditing.entity.prefix): defines the prefix which is set before the EClass name, this is used to compute the entity name and the table name used to store auditing entries.
* AUDITING_ENTITY_PREFIX (teneo.naming.auditing.entity.prefix): defines the prefix which is set before the EClass name, this is used to compute the entity name and the table name used to store auditing entries.
+
* AUDITING_ENTITY_POSTFIX (teneo.naming.auditing.entity.postfix): (default is 'Auditing') defines the prefix which is set before the EClass name, this is used to compute the entity name and the table name used to store auditing entries.
  
 
== Retrieving Audit Entries ==
 
== Retrieving Audit Entries ==
 +
 +
Audit entries can be retrieved using the [http://git.eclipse.org/c/teneo/org.eclipse.emf.teneo.git/tree/hibernate/org.eclipse.emf.teneo.hibernate/src/org/eclipse/emf/teneo/hibernate/auditing/AuditVersionProvider.java AuditVersionProvider]. The AuditVersionProvider can be retrieved from the data store using the getAuditVersionProvider method.
  
 
=== By Object ===
 
=== By Object ===
 +
 +
The AuditVersionProvider provides several methods to retrieve the history of an object. You can retrieve the latest audit entries or all audit entries for an object. See the getAllAuditEntries, getLatestAuditEntry methods.
 +
 +
From an audit entry you can find the next or previous entries using the getNextEntry and getPreviousEntry methods of the AuditVersionProvider.
  
 
=== Query ===
 
=== Query ===
  
=== Iterating over version history ===
+
Each audit type/EClass is mapped to hibernate as a standard type. This means that you can query for audit entries using HQL.
 +
 
 +
Some things to note when querying:
 +
* Selecting on primitive types can be done in the same way as for the standard type.
 +
* the EClass name of the audit entry is controlled by the options discussed above, as a default the term Auditing is appended to the original EClass name, so if the domain EClass is Book, then the auditing EClass will be BookAuditing.
 +
* Teneo stores all references as strings, so association joining is not directly possible. Also when filtering on an EReference association you should use the id string representation of an entity. To get the id string representation call the getIdString method on the AuditVersionProvider.
 +
 
 +
This code snipper illustrates how to query for audit entries:
 +
<source lang="java">
 +
final AuditVersionProvider vp = testStore.getEmfDataStore().getAuditVersionProvider();
 +
// select on pages and the author
 +
final Query qry = testStore.getSession().createQuery("select e from BookAuditing e where pages=1 and author=:author");
 +
// set the author parameter, create the id string using the getIdString method.
 +
qry.setParameter("author", vp.getIdString(writer));
 +
final List<?> list = qry.list();
 +
</source>
 +
 
 +
=== Test cases ===
 +
 
 +
The following test cases give examples on how to iterate over audit entries or query for audit entries:
 +
* [http://git.eclipse.org/c/teneo/org.eclipse.emf.teneo.git/tree/tests/org.eclipse.emf.teneo.hibernate.test/src/org/eclipse/emf/teneo/hibernate/test/emf/auditing/SimpleLibraryAuditingAction.java#n203 SimpleLibraryAuditingAction.java]
 +
* [http://git.eclipse.org/c/teneo/org.eclipse.emf.teneo.git/tree/tests/org.eclipse.emf.teneo.hibernate.test/src/org/eclipse/emf/teneo/hibernate/test/emf/auditing/EMapAuditingTrueEMapAction.java#n204 EMapAuditingTrueEMapAction.java]
 +
 
 +
== Revisions ==
 +
 
 +
An audit entry represents the state at a certain point in time. Teneo also provides an api to get the actual instance with the values/references at a certain timestamp. The special feature is that also referenced objects are in the same state.
 +
 
 +
For example, a Book references a Writer, then when retrieving a Book in the state it has on the 1st of September 2011, then the referenced Writer will also be in the state of the 1st of September 2011.
 +
 
 +
To get actual instances you can use the getRevision methods of the [http://git.eclipse.org/c/teneo/org.eclipse.emf.teneo.git/tree/hibernate/org.eclipse.emf.teneo.hibernate/src/org/eclipse/emf/teneo/hibernate/auditing/AuditVersionProvider.java AuditVersionProvider] class.
 +
 
 +
Note that the AuditVersionProvider internally uses a Resource to resolve proxies against the audit entries in the database. This means that revisions retrieved through the getRevision method are part of a resource.
 +
 
 +
If a referenced entity is not audited (so there are no audit entries in the database) then the referenced entity is read from the database directly.
 +
 
 +
== Commit info, username ==
 +
 
 +
For each commit a separate commit info record is created in the database. To control the user name in the commit info a thread local is available in the [http://git.eclipse.org/c/teneo/org.eclipse.emf.teneo.git/tree/hibernate/org.eclipse.emf.teneo.hibernate/src/org/eclipse/emf/teneo/hibernate/auditing/AuditProcessHandler.java AuditProcessHandler] class. You can get the AuditProcessHandler from the data store (there is a getter).
 +
 
 +
== Pruning entries ==
 +
 
 +
You can tell Teneo to automatically prune older entries. This is controlled with 2 options:
 +
* AUDITING_PRUNE_OLD_ENTRIES_DAYS option controls how many days old entries are removed
 +
* AUDITING_PRUNE_COMMIT_INTERVAL option controls the interval by which Teneo checks the audit tables, so with a value of 1000, every 1000 commits, the audit tables are checked for expired entries, and they are removed. Only commits which update the audit entry tables are considered for the interval.
 +
 
 +
The pruning of old entries is done in a separate transaction.
 +
 
 +
== Auditing database schema/model ==
 +
 
 +
For single-occurence (isMany==false) EAttributes the annotations defined in the teneo.jpa EAnnotations are copied over to the auditing model element. For all other types of model elements or for specific behavior you can control the auditing database schema through EAnnotations with a specific source (teneo.jpa.auditing).
 +
 
 +
You can set table names, column names, join tables etc. To do this, you can make use of the [[Teneo/Hibernate/ModelRelational|same annotation functionality]] as available for standard domain types. The auditing annotations are specified on the domain types using a specific annotation source: '''teneo.jpa.auditing'''.
 +
 
 +
See also the AUDITING_DB_SCHEMA database schema discussed above in the wiki page, this option controls the database schema of the auditing tables.
  
 
== Limitations ==
 
== Limitations ==
Line 34: Line 99:
 
Auditing does not work in combination with specific functionality:
 
Auditing does not work in combination with specific functionality:
 
* EmbeddedId is not supported, this is neither supported with Hibernate envers.
 
* EmbeddedId is not supported, this is neither supported with Hibernate envers.
* [[Teneo/Hibernate/ModelRelational/Entity_Attribute_Value_Mapping|EAV]] mapping can not be combined with auditing. This can be solved but requires some work, please ask on the newsgroup if relevant for your case.
+
* [[Teneo/Hibernate/ModelRelational/Entity_Attribute_Value_Mapping|EAV]] mapping can not be combined with auditing. This can be solved, but requires some additional work, please ask on the newsgroup if relevant for your case.
* Embeddable/Embedded works fine but only if annotated in the model, so not using a separate xml/hbm mapping file. This can be solved but needs some work, please ask on the newsgroup if relevant for your case.
+
* OneToOne in combination with orphan removal does not work currently because of details in the flush process.
* the delete audit entry does not contain any collection values
+
* Embeddable/Embedded works fine in combination with auditing, but only if [[Teneo/Hibernate/ModelRelational/Annotations_Format#JPA_Annotations_in_EAnnotations_using_the_java_annotation_syntax|annotated in the model]], so not using a separate [[Teneo/Hibernate/ModelRelational/Annotations_Format#JPA_Annotations_in_XML|xml/hbm]] mapping file. This can be solved, but needs some additional work, please ask on the newsgroup if relevant for your case.
 +
* The delete audit entry does not contain any collection values

Latest revision as of 10:39, 29 November 2012

Teneo supports auditing (from November 2012), a summary of the functionality:

  • auditing can be enabled/disabled for the complete model or for specific types
  • possible to navigate/iterate over the history of an object
  • use HQL to query for version history using attribute and ereference values

Enable auditing

Auditing can be enabled by calling setAuditing(true) on the datastore or setting the enable auditing option to true (see the 'Auditing Options' section). To prevent auditing of specific types you can use the @NoAuditing annotation. Set this annotation in the EMF EAnnotation of the EClass using source 'teneo.jpa' and key 'value'.

Audit Entries

When auditing is enabled then at each database action on an entity its state is persisted in a separate table. To support this persistence, Teneo will generate a separate additional type for each audited type, these audit types/eclasses are generated and mapped at runtime.

Each audit EClass models the audit entries for a domain EClass, its audit entries are stored in a separate table. Teneo will store three types of events: ADD, UPDATE and DELETE.

Teneo provides an api to retrieve the audit entries, this is described in more detail below.

Auditing Options

Teneo has many configuration options, the following options are specific for auditing:

  • ENABLE_AUDITING (teneo.mapping.auditing.enable): default is false, enables auditing if set to "true"
  • AUDITING_PRUNE_OLD_ENTRIES_DAYS (teneo.mapping.auditing.prune.days): default is 0, if set > 0, then audit entries older than this number of days are deleted, this is done during the operation of the system (every 1000 commits a prune check is done and old entries are removed).
  • AUDITING_PRUNE_COMMIT_INTERVAL (teneo.mapping.auditing.prune.commit.interval): default is 1000, defines the number of commits before Teneo checks for to-be-pruned entries. Only commits which update the audit entry tables are counted. So with the default, every 1000 commits, all audit tables are checked for expired entries.
  • AUDITING_DB_SCHEMA (teneo.mapping.auditing.database.schema): database schema for the auditing tables, default is not set.
  • AUDITING_ENTITY_PREFIX (teneo.naming.auditing.entity.prefix): defines the prefix which is set before the EClass name, this is used to compute the entity name and the table name used to store auditing entries.
  • AUDITING_ENTITY_POSTFIX (teneo.naming.auditing.entity.postfix): (default is 'Auditing') defines the prefix which is set before the EClass name, this is used to compute the entity name and the table name used to store auditing entries.

Retrieving Audit Entries

Audit entries can be retrieved using the AuditVersionProvider. The AuditVersionProvider can be retrieved from the data store using the getAuditVersionProvider method.

By Object

The AuditVersionProvider provides several methods to retrieve the history of an object. You can retrieve the latest audit entries or all audit entries for an object. See the getAllAuditEntries, getLatestAuditEntry methods.

From an audit entry you can find the next or previous entries using the getNextEntry and getPreviousEntry methods of the AuditVersionProvider.

Query

Each audit type/EClass is mapped to hibernate as a standard type. This means that you can query for audit entries using HQL.

Some things to note when querying:

  • Selecting on primitive types can be done in the same way as for the standard type.
  • the EClass name of the audit entry is controlled by the options discussed above, as a default the term Auditing is appended to the original EClass name, so if the domain EClass is Book, then the auditing EClass will be BookAuditing.
  • Teneo stores all references as strings, so association joining is not directly possible. Also when filtering on an EReference association you should use the id string representation of an entity. To get the id string representation call the getIdString method on the AuditVersionProvider.

This code snipper illustrates how to query for audit entries:

final AuditVersionProvider vp = testStore.getEmfDataStore().getAuditVersionProvider();
// select on pages and the author
final Query qry = testStore.getSession().createQuery("select e from BookAuditing e where pages=1 and author=:author");
// set the author parameter, create the id string using the getIdString method.
qry.setParameter("author", vp.getIdString(writer));
final List<?> list = qry.list();

Test cases

The following test cases give examples on how to iterate over audit entries or query for audit entries:

Revisions

An audit entry represents the state at a certain point in time. Teneo also provides an api to get the actual instance with the values/references at a certain timestamp. The special feature is that also referenced objects are in the same state.

For example, a Book references a Writer, then when retrieving a Book in the state it has on the 1st of September 2011, then the referenced Writer will also be in the state of the 1st of September 2011.

To get actual instances you can use the getRevision methods of the AuditVersionProvider class.

Note that the AuditVersionProvider internally uses a Resource to resolve proxies against the audit entries in the database. This means that revisions retrieved through the getRevision method are part of a resource.

If a referenced entity is not audited (so there are no audit entries in the database) then the referenced entity is read from the database directly.

Commit info, username

For each commit a separate commit info record is created in the database. To control the user name in the commit info a thread local is available in the AuditProcessHandler class. You can get the AuditProcessHandler from the data store (there is a getter).

Pruning entries

You can tell Teneo to automatically prune older entries. This is controlled with 2 options:

  • AUDITING_PRUNE_OLD_ENTRIES_DAYS option controls how many days old entries are removed
  • AUDITING_PRUNE_COMMIT_INTERVAL option controls the interval by which Teneo checks the audit tables, so with a value of 1000, every 1000 commits, the audit tables are checked for expired entries, and they are removed. Only commits which update the audit entry tables are considered for the interval.

The pruning of old entries is done in a separate transaction.

Auditing database schema/model

For single-occurence (isMany==false) EAttributes the annotations defined in the teneo.jpa EAnnotations are copied over to the auditing model element. For all other types of model elements or for specific behavior you can control the auditing database schema through EAnnotations with a specific source (teneo.jpa.auditing).

You can set table names, column names, join tables etc. To do this, you can make use of the same annotation functionality as available for standard domain types. The auditing annotations are specified on the domain types using a specific annotation source: teneo.jpa.auditing.

See also the AUDITING_DB_SCHEMA database schema discussed above in the wiki page, this option controls the database schema of the auditing tables.

Limitations

Auditing does not work in combination with specific functionality:

  • EmbeddedId is not supported, this is neither supported with Hibernate envers.
  • EAV mapping can not be combined with auditing. This can be solved, but requires some additional work, please ask on the newsgroup if relevant for your case.
  • OneToOne in combination with orphan removal does not work currently because of details in the flush process.
  • Embeddable/Embedded works fine in combination with auditing, but only if annotated in the model, so not using a separate xml/hbm mapping file. This can be solved, but needs some additional work, please ask on the newsgroup if relevant for your case.
  • The delete audit entry does not contain any collection values

Back to the top