How to implement change log with JPA? - 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.

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/

Should JPA entities and DDD entities be the same classes?

There are classes that are entities according to DDD, and there are classes that have #javax.persistence.Entity annotation. Should they be the same classes? Or should JPA entities act just as a mechanism for a mapper (https://martinfowler.com/eaaCatalog/dataMapper.html) to load DDD entities from a database (and store them) and be kept outside the domain model?
Would it make a difference if database metadata were separated and stored externally (for example, in XML)? If such classes are entities, where is the boundary? I think classes generated from XSD (for example, with JAXB) or even from database with MyBatis Generator are not entities as understood in DDD.
That's an implementation detail really. They could be or they could not depending on the flexibility of your ORM. For instance, if your ORM allows to map your domain objects without polluting them with persistence concerns then that's the approach that requires the less overhead and which I'd go for.
On the other hand, if your ORM is not flexible enough then you could go for a pragmatic hybrid approach where your AR and it's state are two different classes and where the state class is simple enough to easily be mapped. Note that the AR would still be responsible to protect it's state here and the state object wouldn't be accessed directly from outside the AR. The approach is described by Vaughn Vernon here.
Your JPA entities should be the domain entities. Why?
Your domain entities should express some strong constraints, e.g. by
Having parameterized constructors
Not exposing all setters
Do validation on write operations
If possible, a domain entity should always remain a valid business entity.
By introducing some kind of mapper, you introduce a possibility to automagically write arbitrary stuff into your domain entities, which basically renders your constraints useless.
The other option would be enforcing the same constraints on JPA and domain entities which introduces redundancy.
Your best bet is keeping your JPA entities as ORM-agnostic as possible. Using Hibernate, this can be done using a configurating class or XML file. But I am no Java EE/JPA guy, so it's hard for me to give a good implementation advice.
After some more experience with JPA and microservices, I would say that I would most likely not separate them when using JPA, unless there's a reason that makes me do otherwise. On the other hand, entities in a single bounded context do not necessarily have to be only JPA entities. It's possible to have both entities mapped by JPA implementation and entities mapped from DTOs using other technologies (like JSON mappers) or manually.
I agree that both ways are possible. After programming some applications with DDD in mind, I find that this heuristic works well:
If you start from having an entity and not having JPA, it will probably be too hard to refactor an entity so that it can be used by ORM framework, so keep them separate
If you start from scratch, it is worth not distinguishing DDD entities from JPA entities

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

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.

Accessing JPA Class Mapping

Found an article in springsource which describes how to manipulate the schema name at runtime.
http://forum.springsource.org/showthread.php?18715-changing-hibernate-schemas-at-runtime
We're using pure jpa however where were using a LocalContainerEntityManagerFactory and don't have access to Session or Conofiguration instances.
Can anyone provide insight on how to access the metadata at runtime (via the entitymanager) to allow modifying the schema?
Thanks
Changing meta-data at runtime is JPA provider specific. JPA allows you to pass a Map of provider specific properties when creating an EntityManagerFactory or EntityManager. JPA also allows you to unwrap() an EntityManager to a provider specific implementation.
If you are using EclipseLink you can set the schema using the setTableQualifier() API on the Session's login.
You can't using standard JPA (which is your requirement going by your question); it doesn't allow you to dynamically define metadata, only view (a limited amount of) specified metadata via its metamodel API. You'd have to delve into implementation specifics to get further, but then your portability goes down the toilet at that point, which isn't a good thing.
JDO, on the other hand, does allow you to dynamically define metadata (and hence schema) using standardised APIs.

Auditing with Spring Data JPA

I am using Spring Data JPA in an application in which all entity objects need auditing. I know that I can have each either implement Auditable or extend AbstractAuditable, but my problem is coming with the overall auditing implementation.
The example on the Spring Data JPA reference pages seems to indicate that you need an AuditableAware bean for each entity. Is there any way to avoid this extra code and handle it in one place or through one configuration?
The generic parameter of AuditorAware is not the entity you want to capture the auditing information for but rather the creating/modifying one. So it will typically be the user currently logged in or the like.