Note that there are some explanatory texts on larger screens.

plurals
  1. POJPA merge() best practice
    text
    copied!<p>I implemented a service for <code>entity object</code> and it uses pure <code>jpa</code>, I used <code>spring</code>, so in <code>spring xml config</code> configured <code>hibernate</code> as a <code>jpa</code> impl. I am using <code>spring</code> data for <code>crud</code> operations. But in our system our <code>entity</code> object is being <strong>pulled/updated</strong> many times and there is high contention(<code>concurrency</code>) to data. From our code in many places many <code>classes</code> just <code>inject</code> the service bean and call <code>getEntity</code> method to get an entity, after it they change the entity(which is detached as my understanding, but in the same thread so em object should be the same as per my knowledge) so it takes for a while the entity comes back to service to be updated, they call <code>save()</code> method of the service to save an entity. <code>Save()</code> method is nothing but just calls <code>merge()</code> crud operation. it is transactional with <code>@Transactional</code> annotation. Here is a problem arises, when someone pulls an entity object and while changing it someone else might pull and change it and save it back, so my entity read is dirty and if save it, I will override already updated entity. The problem is here we are changing the entity outside of service and calling save back. Here spring data repository classes are DAO layer. </p> <p><code>Optimistic lock</code> is one solution but We did not like it for some reasons, so it does not work for us. I am thinking about <code>pessimistic lock</code>. For example, when I get an entity for update by locking, then change it somewhere else in different place and call back(the <code>entity</code> was already locked against update!) does it work? I am not sure if it still <code>EntityManager</code> object there which I used for pulling an entity. If it is there it takes quite long time to pass those 'smart' logics before it gets updated and unlocks it. </p> <p>Here is simple example code for the scenario:</p> <pre><code>class SomeEntity { Long id; String field1; String field2; String field3; String field4; String field5; String field6; String field7; //getters and setters, column annotations } class SomeEntityServiceImple implemenet SomeEntityService{ @Transactional save(SomeEntity se){ //call to spring data's merge() method } get(Long id){ //call to spring data's findOne() } } //this class might be spring bean, might not be. If it is not I will get SomeEntityService bean from shared appContext class SomeCrazyClass{ @Autowired SomeEntityService service; someMethod(){ SomeEntity e = service.get(1L); //do tons of logic here, change entity object, call some another methods and again, takes 3 seond service.save(e); //Probably detached and someone updated this object, probably overriding it. } } } </code></pre> <p>Here I cannot move that <code>tons of logic</code> inside the service layer, it is quite specific and this kind of different logics are in 100s of places. </p> <p>So is there any way to come around and at least apply pessimistic lock to this situation?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload