1

I have DB tables representing Employees and Departments. The server side(JavaEE) contains JPA entities representing the same.

The client is a standalone client and communicates with the server using DTOs. In my case, a single DTO contains both the Employee and Dept details.

I want to implement Optimistic locking using the Version annotation on these entities, but there is an issue: When the client send the DTO with the updated values to the server method(webservice), the server method creates entities using the values in the DTO and then it finds the entity using the find() method on JPA and then calls update(). There is not much gap between find() and update().

But the issue is that the value coming from the DTO itself might be stale. Since I am using standalone client, I do not have the context of the server's JPA entities. JPA itself cannot find that the value is old (because the version between find() and update() matches) and overwrites the entity with stale data. Is there a way to solve this issue?

  • What is the purpose of doing the find before the update? Doesn't your DTO contain all the information that is needed to perform an update? – Bart van Ingen Schenau Jun 18 '15 at 12:24
  • The find is to get a "JPA context attached" entity. E.g Employee emp = entityMgr.find(Employee.class, employeeDTO.getID); The emp object is then updated with information from DTO and entityMgr.update(emp) is called. – KayDK Jun 18 '15 at 12:38
  • @BartvanIngenSchenau one reason may be to check for stale data, verify that the record in the database hasn't been changed since the data presented to the user who submits the update is written. – jwenting Jul 19 '15 at 6:42
  • @jwenting: The find can't prevent that you try to update stale data, because some other process might do an update between your find and update. The only defence against that is to perform the check together with the update in an atomic action. – Bart van Ingen Schenau Jul 19 '15 at 7:53
  • @BartvanIngenSchenau lock, find, check, update, unlock. – jwenting Jul 19 '15 at 16:47
2

Optimistic locking using version numbers is based on the principle that you know which version of the data was retrieved from the database before making any modifications, so that you can verify that no intermediate updates have taken place between your retrieval of an entity and writing your changes back.

For this to work, the version number must be an integral part of the entity (and must only be changed by the database). This means that the version number must also be communicated in your DTO to the client, preferably as a read-only attribute.

If the version number is part of the DTO, then you can detect stale data in two ways:

  1. The find method checks the version number against the current version of the entity and reports "entity version mismatch" when the two don't match.
  2. The update method fails if the version of the entity doesn't match the version number in the database. To avoid race conditions, this check should always be performed, even if the find function also checks the version number.

If you did detect stale data, you can react in several ways:

  1. Report an error and let the user refresh the entity and re-enter his changes
  2. Report the conflict to the user and let him merge his changes into the new version of the entity (showing what was changed externally and what was changed by the user).
  3. Try to perform an automated merge, and if that doesn't work fall back to 2 (for example if multiple edits were made to the same field).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.