Can I use Hibernate Envers if I just want to keep deleted Entities around? - hibernate-envers

Right now we don't delete entities, but set a flag to "inactive" in the table (and filter these entities out for normal operations). Someone pointed me to Hibernate Envers, but it looks a little bit like overkill to me. My questions are:
Can we use Envers to perform our mechanism (active/inactive flag)?
If not, can Envers store a copy of a deleted entity in an archive table, but don't do any versioning / auditing stuff?
Are there lightweight alternatives for this task?

You could use Envers here, by extending the audit listener and ignoring insert/update events, however I agree that's an overkill.
Simply using an active flag with a dedicated DAO method or writing a simple Hibernate event listener should be much better suited for this task.

Related

How to keep a history of edit of Entities in a JPA application

A JavaEE and JPA application need to keep a record of all the changes made by the user.
Currently, for all the entities, there are fields to record createdBy and lastEditedBy properties. Yet, the requirement of recording all edits is not possible with those properties.
What is the best way to record the history of all edits for a particular entity?
I do not use Spring.
You can use Javers which is db and framework agnostic tool for maintaining operation history.
There are two big differences between JaVers and Envers:
Envers is the Hibernate plugin. It has good integration with Hibernate
but you can use it only with traditional SQL databases. If you chose
NoSQL database or SQL but with another persistence framework (for
example JOOQ) — Envers is not an option.
On the contrary, JaVers can be used with any kind of database and any
kind of persistence framework. For now, JaVers comes with repository
implementations for MongoDB and popular SQL databases. Other databases
(like Cassandra, Elastic) might be added in the future.
Envers’ audit model is table-oriented. You can think about Envers as
the tool for versioning database records.
JaVers’ audit model is object-oriented. It’s all about objects’
Snapshots. JaVers saves them to the single table (or the collection in
Mongo) as JSON documents with unified structure.
You can also achieve this using triggers and storing object differences.
Edit:
JaversAuditableAspect for any kind of repository.
It defines the pointcut on any method annotated with the method-level #JaversAuditable annotation. Choose it if you have repositories that are not managed by Spring Data.
#Bean public JaversAuditableAspect javersAuditableAspect() { return new JaversAuditableAspect(javers(), authorProvider(), commitPropertiesProvider()); }
You can use Hibernate's Envers to audit your entities. It allow you to keep track of ALL changes made to entities - even deleted ones. Most probably you are already using Hibernates (as JPA provider) so integration should be a no problem.
https://hibernate.org/orm/envers/

Optimistic Locking in Spring Data JDBC

I noticed that Spring Data JDBC doesn't seem to implemented Optimistic Locking (something like a JPA's #Version annotation).
I was thinking on creating a #Modifying query which considers the version field and returns boolean to check manually if the update was successful or not. But I'm afraid this approach is limited to simple entities, not aggregates implying multiple tables.
What's the best way to implement optimistic locking for aggregates?
It depends on your situation. If you just have 7 aggregates of which 5 are single entity aggregates go for the #Modifying solution for the single aggregates and write custom methods for the other 2.
If you have more aggregates consisting of more then one class consider properly implementing it and submitting a PR. The issue is already there: https://jira.spring.io/projects/DATAJDBC/issues/DATAJDBC-219
The main code changes will be in SqlGenerator which would need to add a where clause for aggregate roots if they have a version attribute.
If you are interested in doing a PR and need more assistance, please leave comment on the issue.

Writing revisions for all audit tables

I use Envers 3.5 with Spring.
Lets say I have a entity A with a relation to Entity B which has a relation to Entity C.
All Entities are audited. When I change something in entity C I can see the change in that audit table. What I want is to see the change in the audittable of entity A, too. It would be ok to see that change in entity B´s table.
Can this be done with envers?
(I´m sorry for my poor English knowledge)
This is a common question about Envers, however that is not possible currently.
First of all Envers doesn't have a way to automatically know what are the roots of entity trees, that is which entities should be marked as modified upon a child-entity modification.
Secondly it would cause a lot more data to be written on each change. It would be possible to implement using some custom annotations and "marker" revisions, but I guess that task waits for a contributor :)

Correct approach to using JPA 2

I saw this link at Nabble where someone (James Sutherland) stated to someone that they were "executing a delete all JPQL query. This is basically similar to executing your own SQL, you are responsible for executing the query correctly to maintain your constraints.
This is not the normal way to delete objects in JPA. In JPA you normally read the object, then call remove() on it.".
I was wondering if this is true or not; based on how difficult it's been to remove more than simple tables, I'd start thinking this is correct.
My thoughts thus far are to do it like this:
Perform select statements, however particular they may be (e.g.
select all students where student courses > 4 and marks >= 60 and
student registration between 2011 and 2012).
Display/edit/delete
objects (so EntityManager merge/persist/remove)
Rinse, lather, and so on
Does this sound reasonable as an approach to how one is suppose to use the JPA or am I off base?
The cascading of remove was discussed here: Google App Engine - DELETE JPQL Query and Cascading. Also for instance doing batch updates won't update version column when optimistic locking is used. Thus batch updates/deletes are a bit crippled in JPA.
But I wouldn't say This is not the normal way to delete objects in JPA. When I need to delete 2, 20 or 200 objects based on some condition selecting and fetching them first just to call remove() on each is a bad idea most of the time.
After all batch updates/deletes are there in the specification for a reason.

How to implement change log with JPA?

I have an entity class manged by with JPA, and I have one entity that needs to be loged changes in its property. Does JPA provides any ways to handle this kind of requirement ?
If you use Hibernate as JPA provider then have a look at Hibernate-Envers.
If you use Spring, then have at Hades, or its successor Spring-Data-JPA.
Both (Envers and Hades/Spring-Data-JPA) provide auditing functionality. Hibernate Envers is very powerful and Hades/Spring-Data-JPA is more light (Hades reference, chapter auditing).
If you do not want/can use any of them, then may you have to hook in the entity lifecycle. with #PostUpdate and co.
See,
http://en.wikibooks.org/wiki/Java_Persistence/Advanced_Topics#History
and,
http://en.wikibooks.org/wiki/Java_Persistence/Auditing_and_Security
If you are using EclipseLink it include historical support. You can enable a class to have all of its changes tracked in a separate historical table.