How to implement history data changes with Spring Boot/Spring Data - java

The problem is how to implement tracking of data changes on e.g. master detail tables i.e. two entities in one to many relationship in Spring Boot/Spring Data.
After storing data, to be able to get the master entity with its details at specific version, and to have functionality to revert it to specific version.

You can use Hibernate Envers to audit and version your persistence entities changes.
The Envers project aims to enable easy auditing of persistent
classes. All that you have to do is annotate your persistent class or
some of its properties, 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 the entity. You can then retrieve and query
historical data without much effort.
Similarly to Subversion, the library has a concept of revisions.
Basically, 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 query for various entities at that
revision, retrieving a (partial) view of the database at that
revision. You can find a revision number having a date, and the other
way round, you can get the date at which a revision was commited.
The library works with Hibernate and requires Hibernate Annotations or
Entity Manager. For the auditing to work properly, the entities must
have immutable unique identifiers (primary keys). You can use Envers
wherever Hibernate works: standalone, inside JBoss AS, with JBoss Seam
or Spring. source
You can query for historic data in a way similar to querying data via
the Hibernate criteria API. The audit history of an entity can be
accessed using the AuditReader interface, which can be obtained with
an open EntityManager or Session via the AuditReaderFactory. source
With Hibernate Envers you can record your data changes and then access it whether using your persistence context or SQL in order to apply your version changes using the provide revision id. With it you've the 80% of the task done.
Check this tutorials
Setting up Hibernate Envers with Spring Boot
Auditing with JPA, Hibernate, and Spring Data JPA
Hibernate Envers: Simple Implementations

If you use JPA, object auditing frameworks like hibernate envers or javers might help

Related

How to validate JPA schema so that it matches the real database schema

Hopefully i won't misuse any technical term.
We have a DB2 schema with many tables which we will connect with the appropriate connections (one-to-many, many-to-many etc) in the next days.
The goal is to make this exact schema in the Java side using Spring JPA. We want to validate the schema created using the Spring JPA so that it matches the database schema.
I'm using the following property
spring.jpa.hibernate.ddl-auto=validate and it seems to work only in one direction, that is, it checks if the database schema satisfies the Jpa schema. It doesn't seem to work the other way around: the database schema has tables that are not defined in the Java side and the application can run successfully.
Can we somehow validate the Jpa schema so that it matches the database schema absolutely?

Diffrence between JPA API and hibernate native API

I am still a beginner in hibernate.I have started reading the user guide in which i found this architecture.
I know that hibernate is a jpa implementation and the jpa jar contains only interfaces.But i want to understand why JPA API is in the same level as Hibernate native api.
And if JPA contains only Interfaces how can we call for example entityManger.persist(entity) and normaly the entity manager is an interface.
where is the entity manger implementation ???
I know that hibernate is a jpa implementation and the jpa jar contains only interfaces.But i want to understand why JPA API is in the same level as Hibernate native api.
Because you can either use the JPA API (EntityManager, EntityManagerFactory etc) or Hibernate native API (Session, SessionFactory etc) to interact with the ORM entities and the database.
And if JPA contains only Interfaces how can we call for example entityManger.persist(entity) and normaly the entity manager is an interface. where is the entity manger implementation ???
JPA API like EntityManager, EntityManagerFactory etc are implemented by Hibernate (one of the JPA implementations, other like EclipseLink etc do exist). You will find that implementation in one of the hibernate jar files. .
A quick ref of Hibernate implementation of EntityManagerFactory here on grepcode

What is the class and method where Envers is passing audit tables metadata to Hibernate?

I would like to exclude Envers audit tables form Hibernate generate / validate phase, but they still need to be present in Evners context. I can't see a place where Envers is passing them to Hibernate.
Any ideas where could it be?
Do you want to exclude the DDL scripts for the envers audit table while doing hibernate schema generation? If this is your question, then sadly you cannot (AFAIK). Envers picks up all entities that are marked auditable and creates their DDL queries.

JPA: Map multiple Oracle users on single persistence unit

I am using EclipseLink 2.5.2 (JPA 2.1), Spring 4.1.5, and I am deploying on Weblogic 12 and Oracle 12c.
I need to deploy my application to use 2 schemas (2 users on the same DB). The first contains the application data, the second contains lookup date which will never change. This is a hard requirement set by my client (the lookup schema may be used by other applications), however I know that they will be on the same Oracle instance. My JPA data model contains entities from both schemas and references between them. Likewise, at the DB level there are FKs in the data schema to the lookup schema.
I would like to:
map my entities in a way that will abstract away the fact that they reside on a different schema (prefixing the generated SQL queries with the user will be sufficient)
build a war file that is portable (no schema is hardcoded)
avoid synonyms, they are hard to maintain and the 2 schemas have a couple of metadata tables with the same name
My current solution:
I have a single persistence unit with all the entities from both schemas. I added an orm.xml for the lookup entities, where I define their schema at build time through Maven:
<entity class="my.package.lookup.ActionTaken">
<table name="ACTION_TAKEN" schema="${db.lookup.username}"/>
</entity>
I do this to avoid hardcoding the lookup schema in the #Table annotation on the lookup entities.
This works well, the generated SQL has the correct prefix for tables in the lookup schema. The problem is, However, as the lookup schema is defined at build time, the resulting war file is not portable.
Any thoughts on how to achieve this?
Some more thoughts:
I currently have a single persistence unit. I don't think that multiple persistence units would work well with entities from the first persistence unit referencing entities from the second.
I tried to have Spring filter the orm.xml file (i.e. I could define the lookup schema in a Spring profile), but Spring seems to be able to filter its own configuration only.
EclipseLink has is own Composite persistence unit, but I am ruling it out because:
Joins across tables in different data sources are not supported.
If you can use the same datasource to access the different schemas, then you can change the schema name using EclipseLink's customizers as described here: http://eclipse.org/eclipselink/documentation/2.5/jpa/extensions/a_customizer.htm .
You will need to change the table/schema name on both the entity's descriptor as well as any 1:M and M:M mappings that use a join table.

Open Session in View with Pure JPA and Spring - not Hibernate Session

I'm creating a Java EE application that's using JPA for data access. Initially I used EclipseLink, but the bundled Geronimo Javamail implementation that it depends on via Moxy was giving me some odd issues and I couldn't force it to use Sun Javamail, so I've switched to Hiberate as the JPA provider.
EclipseLink was ignoring the lazy/eager annotations, it was eagerly loading everything. Hibernate pays attention to those annotations, and so dependant objects aren't loaded. That means if I load say a person, with a lazy loading of the persons parents, if I access the parents in the view it's not lazy loaded, I get an exception that says the database session's closed.
I understand there are two ways to get around this:
- Open Session in View pattern/antipattern (which isn't great from a layered point of view, and can have the N+1 database calls problem, but is easy)
- Have service methods that load all the data the view needs (which makes the service layer messy with lots of duplicate methods to get varying amounts of data)
For reference my layers are View -> Controller -> Service -> Entity Object -> JPA. I don't have a dto as it's a small app and I don't like the DTO anti-pattern.
Thinking about the Open Session in View pattern, the problem is the OpenSessionInViewInterceptor and OpenSessionInViewFilter are both Hibernate specific, and both require you to declare a hiberate session on your Spring configuration files. I prefer to stay with pure JPA, configured with a persistence.xml file.
What are my options here? Can I just change my Spring configuration to load Hibernate explicitly, but then use pure JPA inside my application? Is there a pure JPA way achieve the same result, lazy loading from the view?
it sounds odd the EclipseLink ignores standard JPA annotations.
the javamail implementation should not be in any way related to JPA
there is OpenEntityManagerInViewX (filter/interceptor) which handle the same scenario for JPA
you can easily go without this pattern if you declare and use your collections wisely.

Categories