Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use the Hibernate optimistic locking version property on the front end?

Optimistic locking using the version attribute for an entity works fine and is easy to implement:

<version property="VERSION" type="int" column="EX_VERSION" />

The entity has a property of the following type:

private int VERSION;
public int getVERSION() { return VERSION; }
public void setVERSION(int VERSION) { this.VERSION = VERSION; }

So far, so good. Now service methods return a data transfer object (DTO) for the entity above, which the views display in HTML. For update pages, the VERSION attribute is stored in an HTML hidden field and submitted with the form.

The intent is to use the version property to ensure that a user's update will fail if the information displayed is accompanied by an old version.

The controller responds to a users update request by invoking a service method with the DTO containing the updated information (including the version property), and the service method in turn uses a data access object (DAO) to persist the changes:

public void update(SimpleDTO dto) {
    SimplyEntity entity = getSimpleDao().load(dto.getId());
    copyProperties(dto, entity); // all properties, including VERSION copied to entity
    getSimpleDao().update(entity);
}

The problem is that the version property copied into the entity by copyProperties(...) is not respected by Hibernate. I tracked down the reason in the following forum: https://forum.hibernate.org/viewtopic.php?f=1&t=955893&p=2418068

In short, when load() is called, Hibernate caches the version property in the session cache and it doesn't matter what it's value is subsequently changed to. I agree that this is the correct behavior, but I have been instructed by Bosses to pass the version via an HTML form property (if there is a better pattern for this, I'd love to hear it).

One solution I am exploring now is to evict the entity from the session after it's version has been set using hibernateTemplate.evict(simpleEntity) before the update happens. I hope this works, but it doesn't seem efficient.

I would like to ask Hibernate to check the version property on the instance itself, rather than only from the session cache.

Thanks in advance for answers!

-- LES

like image 573
les2 Avatar asked Sep 14 '09 18:09

les2


People also ask

How does Hibernate optimistic locking work?

1.2 Optimistic Locking in Hibernate Version checks the version numbers or the timestamps to detect conflicting updates and to prevent lost updates. In here, A record is only locked while updating and when it is updated, hibernate increments the version count by one.

How do you handle optimistic lock exception?

Solution. To resolve this error we have two ways: Get the latest object from the database and set the old object values if you need those values to be persisted to the new object and merge it. For the old object set the latest version from Database.

What is optimistic and pessimistic locking in Hibernate?

There are two models for locking data in a database: Optimistic locking , where a record is locked only when changes are committed to the database. Pessimistic locking , where a record is locked while it is edited.


1 Answers

Do you really need to use DTO? You wouldn't have had this problem if you were passing the actual entity around - nor would you have to load the entity again, which isn't exactly great for performance.

But even if you do have a legitimate reason to use DTO, I'm not quite grasping why you would try to update the version number on your freshly reloaded entity prior to saving. Consider different scenarios possible in your workflow:

  1. Entity is loaded initially, has version = V1
  2. It's transferred to DTO which goes to UI, comes back and is ready to be saved.
  3. Entity is loaded again, has version = V2

You have two possibilities now:

  1. V1 == V2. Peachy, you don't have to do anything.
  2. V1 is less than V2, meaning entity was updated by someone else while you were editing it. There's no reason to try to set version to V1 and attempt to save because saving will fail. You can either save it with V2 (thus overriding someone else's changes) or fail now.(without involving Hibernate).
like image 79
ChssPly76 Avatar answered Sep 19 '22 09:09

ChssPly76