12
votes

I have doubts about which is the best type for a field annotated with @Version for optimistic locking in JPA.

The API javadoc (http://docs.oracle.com/javaee/7/api/javax/persistence/Version.html) says:

"The following types are supported for version properties: int, Integer, short, Short, long, Long, java.sql.Timestamp."

In other page (http://en.wikibooks.org/wiki/Java_Persistence/Locking#Optimistic_Locking) says:

"JPA supports using an optimistic locking version field that gets updated on each update. The field can either be numeric or a timestamp value. A numeric value is recommended as a numeric value is more precise, portable, performant and easier to deal with than a timestamp."

"Timestamp locking is frequently used if the table already has a last updated timestamp column, and is also a convenient way to auto update a last updated column. The timestamp version value can be more useful than a numeric version, as it includes the relevant information on when the object was last updated."

The questions I have are:

  • Is better a Timestamp type if you are going to have a lastUpdated field or is better to have a numeric version field and the timestamp in other field?

  • Between numeric types (int, Integer, short, Short, long, Long) which is the best to choose (considering the length of each type)? I mean, I think the best is Long but it requires a lot of space for each row.

  • What happens when the version field gets to the last number of a numeric type (for example 32,767 in a Short field)? Will it start from 1 again in the next increment?

2

2 Answers

10
votes

Just go with Long or Integer. BUT don't go with int or long. In opposite to other comment here, null value is expected when entity was never persisted yet. Having int or long might make Hibernate to think that entity is already persisted and in detached state as version value will be 0 when unset. Just finished debugging a FK violation where "int" was the cause, so save your time and just go with Long or Integer.

5
votes

First, know that locking is used to managed concurrent transactions.

1.Separate your concerns. If lastupdated field is business model specific, it should be separate from your versioning field - which is for - versioning.

2.Primitives and objects are usually mapped to your db as the same type. Except for the fact that Boolean by default will be nullable and boolean will be 'not nullable'. However, enforce nullability explicitly. In this case you want to use a primitive as the version field can't be nullable.

Integer or long are better than timestamp. Hibernate recommends numeric versionig and they don't take that much space.

  1. If you use long, you might not live to find out.

Use this and you should be fine.

private long version;

@Version
public long getVersion() {
    return version;
}

public void setVersion(long version) {
    this.version = version;
}