How does Hibernate Envers work? - java

I am using Hibernate envers in one of my projects. It works really good and does that job.
I am trying to understand the internal working mechanism of envers.
How does envers work internally?
What happens when the actual transaction is succeeded and the audit table update fails? Will the entire transaction be rolled back?
Does envers be executed in a different thread than the actual one serving the request? or can it be?

Hibernate Envers provides a very simple solution for CDC (Change Data Capture).
It uses the Hibernate Event system to intercept all entity state transitions and audit them.
The database transaction will roll back and both the actual changes and the audit log is rolled back.
No. Envers is a synchronous audit logging mechanism. For asynchronous audit logging, you need to use Debezium.
If you want to use Envers, make sure you are using the validity audit strategy because it performs better than the default one.

Related

Risk of data contamination due to in memory processing - JAVA

I am developing java application based on spring framework.
It
Connects to a MySQL database
Gets data from MySQLTable1 in POJOs
Manipulates (update,delete) it in memory
Inserts into a Netezza database table
The above 4 processes are done for each client (A,B,C) every hour.
I am using a spring JDBC template to get the data like this:
SELECT COL1,COL2,COL3 FROM MySQLTable1 WHERE CLIENTID='A' AND COL4='CONDITION'
and read each record into a POJO before I write it to a Netezza table.
There are going to be multiple instance of this application running every hour through a scheduler.
So Client A and Client B can be running concurrently but the SELECT will be unique,
I mean data for:
SELECT COL1,COL2,COL3 FROM MySQLTable1 WHERE CLIENTID='A' AND COL4='CONDITION'
will be different from
SELECT COL1,COL2,COL3 FROM MySQLTable1 WHERE CLIENTID='B' AND COL4='CONDITION'
But remember all of these are stored in memory as POJOs.
My questions are :
Is there a risk of data contamination?
Is there a need to implement database transaction using spring data transaction manager?
Does my application really need to use something like Spring Batch to deal with this?
I appreciate your thoughts and feedback.
I know this is a perfect scenario for using an ETL tool but that is out of scope.
Is there a risk of data contamination?
It depend on what you are doing with your data but I don't see how you can have data contamination if every instance is independant, you just have to make sure that every instances that run concurrently are not working on the same data (Client ID).
Is there a need to implement database transaction using spring data transaction manager?
You will probably need a transaction for insertion into the Netezza table. You certainly want your data to have a consistent state in the result table. If an error occur in the middle of the process, you'll probably want to rollback everything that was inserted before it failed. Regarding the transaction manager, you don't especially need the Spring transaction manager, but since you are using Spring it might be a good option.
Does my application really need to use something like Spring Batch to deal with this?
Does it really need it, probably not, but Spring Batch was made for those kind of application, so it might help you to structure your application (Spring Batch provides reusable functions that are essential in processing large volumes of records, including logging/tracing, transaction management, job processing statistics, job restart, skip, and resource management). Everything can be made without the framework and it might be overkill to use it if you have a really small application. But at the end, if you need those features, you'll probably want to use it...
Spring Batch is ETL, so using it would be a good fit for this use case and also a good alternative to a commercial ETL tool.
Is there a risk of data contamination? Client A and B read separate data, so they can never interfere with each other by reading or writing the same data by accident. The risk would be if two clients with the same ID are created, but that is not the case.
Is there a need to implement database transaction using spring data transaction manager?
There is no mandatory need to do that, although programatic transaction management has many pitfalls and is best avoided. Spring Batch would manage transactions for you, as well as other aspects such as paging.
Does my application really need to use something like Spring Batch to deal with this? There is no mandatory need to do this, although it would help a lot, especially in the paging aspect. How will you handle queries that return thousands of rows? Without a framework this needs to be handled manually.

Debugging JUnit Tests in a Hibernate driven Spring Application

Maybe this has been answered already, but i did not find any suggestions out there...
My Project is a Spring Utility Project, the database i use is MySQL and for persistence i´m using Hibernate in combination with c3p0 connection pooling. i´m on spring 3.2 and hibernate 3.5.
So here is what i want to do:
I want to debug a JUnit test, step over some persistence functions (save, update, etc. ) and then check the entries manually in the database via SQL. Because of the JUnit tests always running in a transaction, i cannot check the entries in the database, because a rollback happens every time a test finished / a commit never occurs.
Is there a way to fake transaction existence, or bypassing them during JUnit tests?
Perhaps you can flush the transaction in Hibernate during your debugging session and force Spring/Hibernate to write to the database.
Or you can turn off transactions for your debugging session.
Rather than fake transaction existence, the best approach to looking at the database while the transaction is taking place is to query with an isolation level that allows dirty reads. The mechanism for doing this varies from database to database, and in MySQL you can use
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
prior to querying.
Clearly you will also need to force Hibernate to flush writes to the database during your test, and set your breakpoint after the flush.

Using both JPA EntityManager and Hibernate session with shared transaction manager in Spring

We have a hard situation.
There is a large project which uses hibernate special features so cannot quit hibernate.
We are to add Activiti process engine to the project in embedded mode and make use of JPA extensions (which only works with EntityManager)
Some entities should not be present in JPA persistent unit because as activiti documentation says all entities must have #Id and cannot use #IdClass/#EmbeddedId so we have to exclude such entities from persistent unit
We wish to use one shared transaction manager for EntityManager and Session. Also the dataSources are identical (or even shared)
Everything is Spring!
All this effort is to enable Activiti to use EntityManager for its JPA extension while letting existing hibernate dependent codes to continue work.
First off, your 3rd point above may prove tricky to accommodate if you want to have one persistence unit and you're actually using #IdClass/#EmbeddedId in your Hibernate entities. Here are two possible solutions:
Pull JPA into your project and configure a persistence unit for your existing Hibernate entities, but continute to delegate the existing calls to Hibernate by accessing the Session directly. In this case, your configuration would be moved over to JPA, but your code would not. This approach also assumes that you have some reasonable abstraction dispensing Session objects in a pluggable fashion. See this question for the crux of the solution. If you have zero flexibility on point 3 above, this approach may not be an option for you.
Create both a session factory and persistence unit and coordinate transactions using JTA with two XA datasources. Even though your data may reside in the same database, you'll want to make sure you create distinct datasources in your configuration if you take this approach. This will prevent Spring's transactional proxy from getting confused when you participate in the distributed transaction. This is probably the cleanest approach, but does carry the stigma of XA transactions which, depending on your container, is more of a political problem these days than a technical one.

Distributed query with Hibernate multi-tenancy

I am using Hibernate's multi-tenancy feature via JPA, with a database per tenant strategy. One of my requirements is to be able to run a query against a table that exists in each database but obviously with different data. Is this possible?
Thanks in advance for your time.
Nope. this is not possible because when hibernate runs queries it is already initialized with a connection. MT support in Hibernate is basically done a little "outside of Hibernate" itself. It's kind of feeding hibernate with a proper connection and when it's fed :) it's bound to that connection.
If you need cross-tenant queries you might want to reconsider multitenancy or change JPA provider to the one that support "shared schema approach" e.g. EclipseLink. With shared shema approach you have two choices:
run native query agains table containing mt-aware entities
create additional entity - dont mark it as multitenant - map it to the table containing mt-ware entities and run JPQL query in standard manner

Needs clarity on hibernate second level cache

I need some clarification with the Hibernate second level cache.
How does the hibernate second level cache works?
Does it loads all the data from the tables for which there is #Cacheable annotation (with respect to hibernate annotation) in the entity classes on server start up in the Java EE environment?
Will the cache gets sync up when there is an update on those tables and how?
Last one is there any ways for my DAO code to get notified when there is an updated on some table which i am interested upon? (Looking for any listener which can intimate abt the updates of the tables).
How does the hibernate second level cache works?
When your entity is marked as cacheable and if you have configured the second level cache then hibernate will cache the entity to the second level cache after the first read.
Hibernate provides the flexibility to plugin any cache implementation that follows hibernates specification. Refer Hibernate Manual for more details on second level cache and configurations options.
Does it loads all the data from the tables for which there is #Cacheable annotation (with respect to hibernate annotation) in the entity classes on server start up in the Java EE environment?
I don't think there is any configuration for achieving this. Indirectly you can achieve this by reading the entire table in startup, this can adversely affect the system startup time. (i don't prefer this). If the entity is modified externally, then hibernate can't sync it and you will end up getting stale data.
Will the cache gets sync up when there is an update on those tables and how?
The cache won't get updated instantly after the table update. The subsequent call to fetch the updated record will go the database, hibernate achieves this internally by using session timestamps.
Last one is there any ways for my DAO code to get notified when there is an updated on some table which i am interested upon? (Looking for any listener which can intimate abt the updates of the tables).
No, hibernate doesn't support this.
That's a too broad question to be answered here.
No. It populates the cache lazily. Each time you get a cachable entity from the database, using the hibernate API or a query, this entity is stored in the cache. Later, when session.get() is called with an ID of an entity that is in the cache, no database query is necessary.
If the update is made through Hibernate, then the cache is updated. If it's done using an external application, or a SQL query, or even a bulk update HQL query, then the cache is unaware of the update. That's why you need to be careful about which entities you make cachable, which time-to-live you choose, etc. Sometimes, returning stale values is not problematic, and sometimes it is unacceptable.
No.

Categories

Resources