Old value in _aud table in envers - spring-boot

I have integrated hibernate envers in spring boot. Now my requirement is to have old value also for the particular column when value changed in *_AUD tables. However I cant see any feature available in Hibernate Envers plugin.
Please suggest.
Thanks

Unfortunately what you are looking to do just isn't someting supported.
It's one thing to think of an entity and needing to store basic type values such as strings or numeric data and have its old/new value represented by two columns in the audit table; however when you move beyond basic entity mappings to ones where you have relationships between entity types or collections; you begin to see that trying to store old/new data in the same row just isn't efficient and in some cases feasible.
That said, you can still read the audit history and deduce these old/new values using a variety of ways that include the Envers Query API, Debezium, or even basic database triggers.

Related

Hibernate envers + hibernate-search : Reading audit information over Lucene/Elasticsearhc indexes

I'm using hibernate-envers for audit purposes in an application. I'm also using hibernate-search in order to search/read the information of JPA entities in the application.
I was wondering if there's any kind of configuration/integration that can make hibernate-envers work with the audit enties/tables, over indexes too, in order to read with hibernate -search that information from the indexes.
I would like to avoid doing it "manually", for example, using envers event listeners in order to create/manipulate a new index manually for the audited entity, using a new JPA Entity modelling the Audit entity information including #Indexed annotation, fields etc.).
Ideally was wondering if there's support for envers/search integration out of the box, without custom development, to achieve storing all audit information in new _aud indexes.
Thanks in advance, any piece of advice is appreciated.
It's certainly not possible out of the box.
If it ever becomes possible, you won't benefit from all the Envers features such as "get me this entity at this revision". You will simply index all the revisions of each entity, and you will only be able to query (and retrieve) these revisions. That would be queries such as "get all revisions of the entity with id 1 where name contained "some text".
Also, this will not remove the need for audit tables. The indexes will exist in addition to the audit tables.
That being said, I just gave it a try and we could make it possible in Hibernate Search 6 with just a few changes. If you're still interested, you can have a look there: https://hibernate.atlassian.net/browse/HSEARCH-4238

Apply Pagination on two different tables and merge results in spring boot

I'm using Spring Data JPA to expose REST APIs. In my application, there are two types of tables available(current and archival) and structure of the current and archival tables are exactly similar and data will be moved for current table to archival table over the period of time for performance reasons. I'm having repository classes to retrieve the data from current and archival table separately and Pagination is also implemented for repositories.
Now I got a requirement to fetch the eligible records from both tables based on criteria and apply pagination at single shot. Is it possible with Spring Data JPA
You can keep the latest version in both tables and when you search for data you just do a regular search.
Another option would be to create a view over the two tables.
I also think Hibernate Envers was able to do that though I never tried it.

Where does spring/hibernate store the Id?

I am using spring with a basic ( except for the credentials for the access, everything is default values ) PostgreSQL database and, using JPA, I get the expected Id increment when using #Id and #GeneratedValue for my #Entity but when I drop the entire table I noticed that the Id is incremented from the previous ( and deleted ) values.
Where are the Id values stored ?
From the Hibernate documentation for identifier generators:
AUTO (the default)
Indicates that the persistence provider (Hibernate) should choose an appropriate generation strategy.
You didn't list GenerationType as one of the annotations present, so it would default to AUTO. From the documentation for how AUTO works:
If the identifier type is numerical (e.g. Long, Integer), then Hibernate is going to use the IdGeneratorStrategyInterpreter to resolve the identifier generator strategy. The IdGeneratorStrategyInterpreter has two implementations:
FallbackInterpreter
This is the default strategy since Hibernate 5.0. For older versions, this strategy is enabled through the hibernate.id.new_generator_mappings configuration property. When using this strategy, AUTO always resolves to SequenceStyleGenerator. If the underlying database supports sequences, then a SEQUENCE generator is used. Otherwise, a TABLE generator is going to be used instead.
Postgres supports sequences, so you get a sequence. From a bit farther down in the same document:
The simplest form is to simply request sequence generation; Hibernate will use a single, implicitly-named sequence (hibernate_sequence) for all such unnamed definitions.
Hibernate asks Postgres to create a sequence. The sequence keeps track of what ids have been handed out, the database persists this internally. You should be able to get into the admin UI of the database and reset this sequence if you want.
To clarify, a database sequence is a database object independent of any tables (multiple tables can use the same sequence), so in general dropping a table won't affect any sequences. The exception is when you're using auto-increment, in which case there is an ownership relationship, and the sequence implementing the auto-increment is reset when the table is dropped.
It's a judgment call on Hibernate's part whether to make the default implementation of id generation use a sequence directly or auto-increment. If it used auto-increment you would see the values get recycled like you expected, but with the sequence there is no automatic reset.

Truncate all database tables with Hibernate and Spring Boot

I need to truncate all database tables after each test. Is there a way to do so or at least a database agnostic way to get all table names so that they can be truncated.
Any other alternatives are welcome. But keep in mind #Transactional and #Rollback will not help as I'm dealing with integration tests which fire http request on the server.
I think you're going to struggle to truncate tables in a simple, database-agnostic way. For example, what do you do about foreign key constraints? Some DBs will let you just truncate the tables in the correct order, leaving you with the problem of how to define that order. But if I recall correctly, some won't let you truncate tables with foreign key constraints at all, even if empty. Then you need to use some DB-specific DDL to disable the constraints, or worse, drop and recreate them.
You are also ruling out parallelising your integration tests if you take this approach.
I've always found a better approach is to make each test clear up just the data that it created. For example, for your create API, you may be able to register a listener that records the IDs of all created entities in your test code, then on teardown you can just reverse iterate this list of IDs, calling your delete API. The downside of this approach is that you may need to implement APIs that your application doesn't actually need, just to support the tests. However these can then be disabled by a flag on deployment to production.
I read this property from a text file and add the 2 hibernate properties in the if statement which rebuilds the database every time I execute my project, perhaps this can help you?
if (environment.getProperty("dbReset").compareTo("ON") == 0)
{
properties.put("hbm2ddl.auto", "create");
properties.put("hibernate.hbm2ddl.auto", "create");
}

Cassandra Best Practice on edits: delete & re-insert vs. update?

I am new to Cassandra. I am looking at many examples online. Here is one from JHipster Cassandra examples on GitHub:
https://gist.github.com/jdubois/c3d3bedb869466731316
The repository save(user) method does a read (to look for existence) then a delete and re-insert of the existing user across all the denormalized tables whenever the user data changed.
Is this best practice?
Is this only because of how the data model for this sample is designed?
Is this sample's design a result of twisting a POJO framework into a NoSQL database design?
When would I want to just do a update in Cassandra? It supports updates at the field-level, so it seems like that would be preferred.
First of all, the delete operations should be part of the batch for more robust error handling. But it looks like there are also some concurrency issues with the code. It will update the user based on the current user value read before. It's not save to assume this will still be the latest value while save() is actually executed. It will also just overwrite any keys in the lookup table that might be in use for a different user at that point. E.g. the login could already exist for another user while executing insertByLoginStmt.
It is not necessary to delete a row before inserting a new one.
But if you are replacing rows and new columns are different from existing columns then you need to delete all existing columns and insert new columns. Or insert new and delete old, does not matter if happens in batch.

Resources