Is it possible to customise the @Version comparison when using Timestamp?

Hello Hibernate and JPA community.

We are considering to use @Version annotation for Optimistic Concurrency Control in our projects. During the analysis we were comparing the Long and Timestamp solution.

By enabling the debug mode, we have seen that version is compared with an equads ‘=’ to the one stored in the database (which makes sense). We were exploring the possibility if we could:

  • Use @Version as timestamp
  • Make a comparison using < or > instead of =

Is it possible to customise the comparison when using Timestamps to use lower and upper comparisons? Or should we create our own @CustomVersion annotation for achieving this?

Thanks.

Why would you want to compare the version with any operator other than =? The point of optimistic locking is that you read a version value at T1, then some time passes and other transactions possibly change the state and hence version of a row. At a later point in time you write your changes back, with the condition version = <T1> which will ensure that nobody else updated the data in the meantime.

Thanks for the quick @beikov.

I agree on that should be the way and how it works.

Which would be the potential problems of comparing <= for Timestamps versions instead of =?

Why we were exploring this option?

We have an exotic situation in our current project and we were exploring some “quick / dirty” solutions to some challenges.

Our enterprise APIs using the standard @Version will be sufficient.

However, we were exploring how to be less impactful (not re-factoring every JSON) of our Experience API layer which has been build exclusively for the UI.
This layer mimics aggregations and mutations (like a custom GraphQL layer) for the UI. Unfortunately, the amount of APIs / Operation is too huge and the JSON structure have not respected the entities etc… so we can’t just include / provide a version attribute without re-factoring accordingfly.

The idea we had for this was. The regular APIs (non-experinece) can follow the @Version standard without issues. These APIs are invoked from our UIs through an aggregation / mutation layer which we call Experience layer.

In our Experience layer when a UI component make GET, then we will return the server/db timestamp when the GET has happened. This means we generate a unique timestamp when the multiple retrieval have been performed (not using the version timestamps coming from the multiple objects). During th PUT update through the experience layer, may different services are invoked internally. So, we wanted to add the timestamp generated in the GET as part fo the DTOs send in the PUT.
As this Timestamp does not belong to the version entity itself, we wanted to force a comparisong “<=”.

I know it can be dirty, but we are just exploring some “less” impactful options (and probably not very elegant).

Still not quite sure how using <= would help here. If you read the data once with version T1 and it gets updated to T2, how would it help if you compare it with version <= T1, since T2 will always be greater than T1?

Hello,

Maybe I haven’t explained my situation well, but it is more I am trying to gain time / budget with a quick fix rather than going through a hard re-factor

UI = User Interface, App
XP = API layer created for the UI which is an aggregation or mutation layer (like GraphQL, but custom)
DS = Our Data Services, Microservices with version optimistic concurrency control implemented (same as you explained)

Example:
UI calls XP (GET), and XP internally aggregate GET different DS (you get 3 different version of 3 differnt entities)

UI calls XP (PUT), and XP only needs to call 1 PUT API which orchestrates (saga-pattern) over 2 DS of the previous obtained.

In the perfect world, the XP GET will provide in the XP PUT the version number associated to every entity if the JSON format was correctly aggregated, structured according to the entities aggegated.
However, due to our current situation (which is out of my hands). The APIs designed for the XP are using a JSON structure format which makes difficult to understand the separation between entities.

What I was trying to avoid is to re-factor around 350 REST operation JSONs and the UI app to accomodate the version attribute properly to the entity mapped obtained in the DS.

Out of curiosity, I thought that if it would be possible that <= is used instead of = as it will solve my problem easier as I can hide the version attribute in my XP layer, and just send in any DTO entity back what was the timestamp during retrieaval. This timestamp is one generated by the XP (GET), not one of the multiple that can come from the DS.

Any other providers, can consume the DS layer with concurrency control without issues, as they will get JSON and update it with the same structure. However, our UI API + UI will be affected to accomodate this.

To summary the question is.
Is it possible to tune the @Version comparison behaviour?
If not, I think I will not have any other choice that re-factor the XP layer (JSON structures, so I can map each version entity to the corresponding one)

Short answer, with Hibernate 6.2 it is possible to override how this is rendered by providing a custom SqlAstTranslator, but I would recommend you rather bite the sour apple and do the refactoring.

Thanks and sorry for the delayed answer.