Reputation: 6623
I have the following setup.
To save a record in the DB via Hibernate I have the following workflow
send JSON {id:1,name:"test",children:[...]}
to Spring MVC App and use Jackson to transform it into an object graph (if it is an existing instance the JSON has the proper ID of the record in the DB set
save the object in DB via service layer call (details below)
the save function of service layer interface SomeObjectService
has the @Transactional annotation on it with readOnly=false
and Propagation REQUIRED
the implementation of this service layer SomeObjectServieImpl
calls the DAO save
method
the DAO saves the new data via a call of hibernate's merge e.g. hibernateTempate().merge(someObj)
hibernate merge
loads the object first from the DB via SELECT
I have a EntityListener who is wired to spring (I used this technique Spring + EntityManagerFactory +Hibernate Listeners + Injection) and listens to @PostLoad
The listener uses a LockingServie
to updates one field of someObject
to set it as locked (this should actually only happen when someObject
is loaded via Hibernate HQL,SQL or Criteria calls but gets called also on merge)
the LockingServie
has a function lock(someObj,userId)
which is also annotated with @Transactional with readOnly=false
and REQUIRED
the update happens via a call of Query query = sess.createQuery("update someObj set lockedBy=:userId");
and then
query.executeUpdate();
after merge has loaded the data it start with updating someObject
and inserting relevant children (<= exacely here is the point where the deadlock happens)
return JSON result (this also includes the newly created object ID) back to client.
The problem seems for me that first
I can see via MySQL's
SHOW OPEN TABLES
that a child table (that is part of the object graph) is locked.
Interesting fact is that the deadlock doesn't occur on the someObj table but rather on a table that represents a child.
I am a bit lost here. Any help is more than welcome.
BTW can maybe the isolation level get me out of this problem here?
Upvotes: 3
Views: 6577
Reputation: 6623
I ended up using @Bozho's HibernateExtendedJpaDialect
which is explained here >> Hibernate, spring, JPS & isolation - custom isolation not supported
To set the isolation to READ_UNCOMMITED
@Transactional(readOnly = false, propagation = Propagation.REQUIRED, isolation=Isolation.READ_UNCOMMITTED)
public Seizure merge(Seizure seizureObj);
Not a very nice solution I know but at least this solved my problem.
If somebody wanna have a detailed description please ask...
Upvotes: 1
Reputation: 597016
I don't know the solution to the problem, but I would not have a transactional lock method. If at all you need to lock something manually, make it within another transactional service method.
Upvotes: 1