Javers - What are advantages of using Javers instead of Envers? - spring

I am developing a RESTful API using Spring Data REST. Now for auditing, Spring does have the option to auditing meta data like created_date and modified_date but they don't provide entity versioning.
Currently there are two popular libraries for entity version which are Envers and Javers. I have looked over for a comparison of both but there arent any articles on this matter.
So what are the benefits and drawbacks of using Javers over Envers?

There are two big difference 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 choosed NoSQL database or SQL but with other persistence framework like
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 data model is a copy of application’s data model. As the doc says:
For each audited entity, an audit table is created.
By default, the audit table name is created by adding a _AUD suffix to the original name.
It can be advantage, you have audit data close to your live data. Envers’ tables look familiar.
It’s easy to query them with SQL.
JaVers uses its own Snapshot model for audit data.
Snapshots are decoupled from live data,
JaVers saves them to the single table (jv_snapshots) as JSON documents with unified structure.
Advantages? You can choose where to store audit data.
By default JaVers uses the same database as application does,
but you can point another database. For example, SQL for application and MongoDB for JaVers
or centralized JaVers database shared for all applications in your company).
Read this blogpost with full JaVers vs Envers comparison:
https://javers.org/blog/2017/12/javers-vs-envers-comparision.html

Enver is like git for a database.
I do not know Javers but a complete Envers databinding has this advantages:
A table is created in the database called REVINFO having a timestamp and a PK.
To every entity that is audited, one shadow-copy is created. Theese shadow-copies have every field nullable and the PK is not a PK. Theese shadow-copies have a new field, the reference to the table REVINFO.
This gives Enver the possibility to record changes that has been made in the past in this shadow-copies. You can move that shadow-tables into an different database.

Related

Spring boot hibernate application throws Negative revision numbers are not allowed when inserting

I have taken a DB dump from my dev database to QA database ( oracle) for testing. My application is a spring boot application and uses hibernate envers for auditing. I get above error when trying to insert data to the tables. I tried removing data from all the audit tables and revinfo table. But the issue is still there. Anybody has any idea on this?
Same error after updating the version of hibernate-envers for springboot3+. One quick solution for me was to (first backup) remove all tables related to audit + remove revinfo table and also the sequencer (revinfo_seq if you created some). Then let the ddl-auto property do the work by setting in application.yml
jpa.hibernate.ddl-auto: update
It creates all needed tables and sequencers by its needed definition, and after that inserts were committed.

Creating tables on fly with Spring Boot Data JPA

Trying to build application where tables & its fields are managed by master table & creation of tables & its fields happens on demand, on fly based on user data posted to server.
Tried to look over similar question like this but wasnt able to find clue how to execute dynamic queries in DB without creating Repository & Entity in spring boot.
Robert Niestroj is correct when he writes in the comments
If you have dynamic tables JPA is the wrong approach. JPA is for static schema
I guess in theory you could do something where you generate code and possibly restart your ApplicationContext but it is bound to be really painful and you won't benefit from using JPA.
You should look into more dynamic technologies. MyBatis and plain old JdbcTemplate or NamedParameterJdbcTemplate come to my mind.
Possibly with your own abstraction layer on top of it if you have recurring scenarios.

Spring Data JPA to Spring Data Redis - what all changes are needed?

I am new to Redis and trying to implement change Postgres DB into the Redis DB. Current implementation we've used Spring Data JPA (Entity Classes + JPA Repository). Now I wanted to use Spring Data Redis and backend as Redis In Memory DB.
Could you please suggest what changes do I need to make in all Entity classes ? How the persistence will happen ? Do I need to make any changes in Join Table etc.. where I have #ManyToOne and #ManyToMany relationship.
Redis a nosql solution so you will not get the befit of foreign keys as in a RDBMS. You will instead need to convert you data into data-structures supported by Redis. https://redis.io/topics/data-types-intro

How to insert/update native queries in DB using spring JPA?

Am working on a Spring boot application using spring data JPA. The DB is a legacy one. There is a staging table which contains insert/update queries as CLOB data.
I have written a pojo for the staging table. The pojo implements CRUDRepository interface. I fetched the records from list() method and iterate the CLOB data. The queries present in the CLOB needs to be executed in other DB. The queries are insert/update queries related to 20+ tables.
Without creating pojos for that 20+ tables, how can I execute those SQL's.
The SQL's need no modifications, just need to execute the same that I fetch from the staging table. Is
EntityManager.createNativeQuery("insert/update")
a possible solution, or is there a better approach to handle it.
You could do that with JPA native queries for sure. Or even with plain JDBC.
But I recommend having a look at jOOQ. jOOQ generates POJOs for accessing and modifying the data and has a DSL that leads to compile time checked data access:
https://www.jooq.org/
jOOQ is free for OpenSource databases like MySQL, PostgreSQL etc. and affordable for commercial ones like Oracle.

how to manage dynamic tables with hibernate - multi tenant database

I am using hibernate 3 using spring 3.5 for a SaaS application. I am expecting upto 10-15 customers , not more. I do not want to implement separate db or schema per customer as its too complicated and costly for a small enterprise like mine. I am currently using a multi-tenant strategy which works fine for a host of small features. Here is the use case where my design fails:
For reporting feature each customer will have a different table for data (because of various reasons like legacy, source of data etc). Table structure differs and so does service/controller behaviors.
I am currently planning to create separate Controllers, Services (DAOs), etc for each customer, thus mapping each of such customer tables with a separate hibernate class. But this approach is not clean and for every new customer I add (which is not that often though), I would need to add its table, and also code a hibernate entity class mapped to the new table, which is not ideal as it needs coding. Is there a way to manage/map such dynamic tables using hibernate which gets added when a new customer is added ?
Use Hibernate 4 multi-tenancy support, see the documentation here. There is support for separate databases per tenant, separate schemas per tenant and partitioning of the same table per tenant.
Is there a way to manage/map such dynamic tables using hibernate which
gets added when a new customer is added ?
I don't know if this is directly supported by Hibernate. From the manual, the supported multi-tenant options are:
schema
database
discriminator
Discriminator is mentioned but is not supported in the current release of Hibernate (version 4.2). That leaves schema and database. You mentioned in your question that neither of these are currently applicable to your setup. So unless you're willing to do some major restructuring, you'll probably need to proceed with a different approach.
Option 1:
If I were you, I'd write a view that presents the data from each tenant's table. You can add the tenant ID as a column in the view. Map the reporting class to the view with Hibernate. When you run a query against the view, set the current tenant's ID as a query parameter.
If you go this route, you won't need to add new controllers and POJOs when you add a customer. Just modify the view to also include the new customer's data and it should work.
Option 2:
Hibernate can bind native SQL query results to entities. You can have one entity that represents the data in any reporting table (this assumes that the separate per-customer tables have a similar structure).
In your reporting DAO, you'd fetch a SQL query from a properties file or specify a named SQL query based on the current tenant identifier. Note that the named query approach will only meet your needs (no recompilation of Java classes) if you have things mapped with HBM files. If your mapping is done with annotations, you'd need to rebuild the project to add a named query.

Resources