How to implement Seed and Next when extending UserVersionType

I’m trying to implement a String based UserVersionType. I have found examples enough to understand how to use the UserType methods to an extent. I can’t find anything that shows me exactly what to do with next() and seed().

So I have something like this

public class StringVersionType implements UserType, UserVersionType {

    public int compare(Object o1, Object o2) {
        String a = (String) o1;
        String b = (String) o2;

        return a.compareTo(b);
    }

    public Object next(Object arg0, SharedSessionContractImplementor arg1)           
    {

           return "DUMMY SEED";  // + LocalTime.now().toString();
    }

    public Object seed(SharedSessionContractImplementor session){
        return "DUMMY SEED"; // LocalTime.now().toString();
    }

}

I’ve tried adding simple code to return a string that is always the same and code that might change the version number. I always get an error on update. Looking at the hibernate console output when I add almost anything to these UserVersionType methods hibernate stops doing a select and then an update but always goes straight to a new insert query and so fails on a primary key still exists.

Obviously I’m misunderstanding what seed and next should do but I can’t find any useful documentation ?

Can anyone tell me more about how to use them ?

The UserVersionType is very straightforward about these two methods:

  • next(Object current, SharedSessionContractImplementor session) - Increment the version.
  • seed(SharedSessionContractImplementor session) - Generate an initial version.

Now, the version cannot be a String. It has to be either a numeric value or a timestamp.

Why do you want to provide a custom optimistic locking mechanism?

Thanks, I missed the explanations of these methods (and also was struggling to understand exactly what to return but I’ve realised I was getting a bit sidetracked). I’ll get back to it soon and check I understand it now. The documentation does state that version
can be any type if you extend UserVersionType ( "The version column can be any kind of type, as long as you define and implement the appropriate UserVersionType" - https://docs.jboss.org/hibernate/orm/4.0/devguide/en-US/html/ch05.html which is why I’m trying to extend it - when I used int it worked out of the box)

We are just doing a PoC of an idea to see if we can get away without changing the underlying data structures.

But if it’s not a number (logical clock) or a timestamp (physical clock), what else can it be?

We wanted to experiment with UUID’s. I tend to agree this is not the best solution but we wanted to do a PoC before making any final decisions and having been asked to complete the task I would like to get it working (alongside an out of the box ‘logical clock’ version) before arguing that we should stick to one of the existing (almost certainly superior!) solutions. Are you saying that if I implement the UUID generator myself / in the Postgres DB this would still be impossible to implement in the UserVersionType ?

We wanted to experiment with UUID’s.

I don’t see how you could use a UUID for optimistic locking which requires a Happens Before ordering. How would a UUID provide that?

I tend to agree this is not the best solution but we wanted to do a PoC before making any final decisions and having been asked to complete the task I would like to get it working (alongside an out of the box ‘logical clock’ version) before arguing that we should stick to one of the existing (almost certainly superior!) solutions.

What’s the goal of that PoC?

Are you saying that if I implement the UUID generator myself / in the Postgres DB this would still be impossible to implement in the UserVersionType ?

I didn’t say anything about UUID so far. UUIDs are meant for unique identifiers while optimistic locking implies a logical ordering value generation scheme.

I think you should definitely review your requirements since using UUIDs for optimistic locking does not sound like a good idea to me.

For more details about transactions and concurrency control, check out these resources:

Okay thanks for those resources. I think my understanding is a bit simplistic at the moment and so I’ll try and get a better understanding and come back if I can think of anything to say! My understanding was that (to oversimplify my simplistic understanding) if version=“u” when the record was read then if version=“u” when the update was applied - good, but if version = “d” then optimistic concurrency fails. At this stage (and I realise this must be infuriating!) I’m not trying to argue it’s a good way forward I’m just trying to show I can do it before arguing it is a possible but a bad idea. I’m not looking for you to explain that to me (although you are welcome to!) I will read more about it to understand what I’m missing. Thanks for your help.

If you read those articles, you are going to get a better understanding of how optimistic locking is supposed to work to prevent losing updates.