hibernate simultaneous updates - java

Consider a scenario- 2 applications accessing/updating a single database. one of the applications is using hibernate & has got some records from db, will now process them & save it back. But before it saves, the same set of records is updated by the other application. What will happen in this scenario?
Will hibernate throw an error on saving ? or hibernate will have the intelligence to sync the updated records?

The hibernate will throw StaleObjectException. Here is why.
Hibernate uses optimistic locking to handle database concurrency. A StaleObjectExceptionis thrown if the data to be updated is modified by another transaction before current transaction commits the changes.
EDIT:
and how does hibernate identify that the state of object in memory is stale?
Hibernate uses a version field to track the changes to the entity. This version field updated on every commit. Now if the version number just before commit does not match the version number when the entity was read at the beginning of transaction,StaleObjectException is thrown.

Related

Hibernate Envers and Hibernate Auto Flush

I've got a Spring application using Hibernate. I've implemented Envers into it, which is working fine. However, Hibernate will by default automatically flush before some transactions are committed.
For example, I have an MVC endpoint that will update a record, but before saving it, will have to make various other queries to retrieve some other data. Each time another query is run, Hibernate flushes and this results in there being multiple audit rows for each change. This creates some confusion, as there is already a modified date on my record which isn't changed in each update (as it's flushing before this property is changed).
What are my options for managing this more effectively, and creating a reliable audit log even with Hibernate flushing in this way? Is the only answer to implement my own listener with some custom logic to check if it should actually be committing an audit change or not?
You can detach the entity and merge when you are done. These queries are only executed if they touch tables that would be affected by pending inserts/updates/deletes. If you use native queries, this is a different topic. Hibernate has no SQL parser to figure out which tables you are touching so it is conservative and flushes all pending changes.

Hibernate optimistic locking and external programs

I have a progam using hibernate #Version annotation to do optimistic locking.
I want to update a row on the database without doing it via hibernate.
Is it possible to simply increase the value in the column in my DB-Update script and will hibernate then follow the right behavior (throw an exception since the version has changed)?
Yes, it should be possible to increment the version number externally and hibernate will throw an exception if you try and save with an out of date version number.
If you are not seeing that behaviour, you should look into the "hibernate.jdbc.batch_versioned_data" property in your hibernate configuration.
See Hibernate saves stale data with hibernate.jdbc.batch_versioned_data for more info.

synchronize EntityManager with database

I deleted a record from the database, and the entity manager still references that deleted record.
I have the following query:
List results = em.createNamedQuery("Customers.findNew")
.setParameter("status", "n")
.getResultList();
I am getting back results which include the deleted record. I've read the entity manager caches the database for better performance. This is fine if only the application using the entity manager is accessing the database. But what happens when multiple systems will access the same database?
I have tried:
1. em.flush()
2. em.refresh()
3. em.clear()
right before I use entity manager to query the database, to try and force a re synchronization but none of them do. I am still getting the same record that isn't in the database anymore.
UPDATE
The program I used to delete record, Oracle SQL Developer, didn't commit changes. So JPA was working fine, it was the program I was using to make changes to the database hadn't committed the changes. If you are experiencing similar problem make sure the db admin program committed changes.
EntityManagers cache Objects themselves, for their own use. This is generally save.
In addition, you can enable the 2nd level cache, where inconsistencies can arise between systems. If you enabled this, try to disable it.
Did you delete the entity using the same EntityManager? If no, make sure the transaction to delete the entity is commited and make sure the transaction of your reading EntityManager starts after the deletion is commited.

Eclipselink/JPA persist a record once or insert each field separately?

I have a question about persist and merge strategy of eclipselink. I would like to know how eclipselink/JPA inserts and updates records. Is it insert/update one by one into database? or it is saving them in a log file and then flush them to the database?
It is important for me, because I am going to have a history table with trigger that triggs when insertion and update. so if for example update is happening on each field, and 3 fields are updated, then I will have 3 records in history table or one?
I will be appreciated if anyone answers me and also leave some reference link for further information.
The persistence provider is quite free to flush changes whenever it sees fit. So you cannot reliably predict the number of update callbacks or the expected SQL statements.
In general, the provider will flush changes before each query to make changes in the persistence context available to the query. You can hint the provider to defer the flush until commit time, but the provider still can flush at will.
Please see the relevant chapters of the JPA (2.0) spec:
§3.2.4 Synchronization to the Database
§3.8.7 Queries and Flush Mode
EDIT: There is an important point to flushing and transaction isolation. The changes are flushed to the database and the lifecycle listeners are invoked, but the data is not committed and not visible to other transactions - the read-committed isolation is the default. The commit itself is atomic.
I am not sure what the consequences of a server crash would be, but under normal circumstances, data integrity is ensured.

hibernate's transaction read and subsequent update

I have situation in which I read a record from a database. And if everything is ok I'll modify few properties and commit transaction.
But in situations two threads do the same, they will update the same record.
How to make it in hibernate?
You can use optimistic locking: give entities a version and let it throw an exception and try again later if the version isn't the same because something else (other thread, other node in a cluster or even some independant sql script that bothers to update the version) changed the same entity.
Or you can use pessimistic locking: really lock the entities in the database.
See the Transactions and Concurrency chapter in the hibernate documentation for more details.

Categories