Skip to content
Advertisement

Hibernate SaveOrUpdate – multiple workthreads

While I have been able to find information on how Hibernate’s transaction work, so the database doesn’t corrupted, it has been harder to understand how Hibernate treats an object which is shared between threads, and each thread tries to save it to the database.

This is my theoretical question:

1) I have a Person object with attributes (ssn, name, address). 2) Three threads have a reference to this person object and each thread calls the method savePersonToHibernate(…)

public void savePersonToHibernate(Person person)
{
...
session.saveOrUpdate(person)
...
}

How does Hibernate cope with 3 threads writing the same object to the storage? Does it put all the transactions in a queue so when the first thread creates the row and identifier (set the id) the remaining two thread will only update it with (in this case) no changes? Or will I actually have the chance of having 2 or 3 rows in the database with a current object only referring to the last identifier created?

I hope it makes some kinda sense… I’m making a queue system, and the data needs to be referred to categories which needs to be created on the fly… and if two or more thread get some data which both needs to have the same category created, I’d hate to have duplicated.

I hope this makes sense… what would you do?

Advertisement

Answer

I’m assuming that all mentioned threads use different sessions otherwise you are in trouble as hibernate session is not thread-safe.

Just to make things clear, if all three threads are using the same instance of person and this is a new object you are in trouble as hibernate doesn’t do any synchronization when accessing or modifying object. Basically each thread works as though other threads do not exist, so each will first check if person has non null id and try to generate it if id is null and then will assign it to appropriate entity field. Depending on the timing of check-generate-assign in different threads and visibility effects of changes result of concurrent creation is unpredictable.

Let’s see what will happen if all threads are using different instances of person but with the same attributes values. In this case each thread will try to create three different rows in database and if there are no unique constraints on the underlying table (like unique name) it will succeed.

Your particular scenario with category creation is not very straightforward to implement. The idea is to try to create category but catch exception if it is already exists. In the latter case read existing category from database and use it. But keep in mind that implementation of conditional insert is not trivial and may be RDBMS dependent. You may fine slightly more complex but related examples for upsert operation for PostgreSQL and SQL Server.

Advertisement