1

I'm placing an annotated field with @Version on it in all my JPA domain classes, however this just seems like additional boiler plate. Is there a way to get around this perhaps via configuration?

TIA, Ole

Neil Stockton
  • 11,383
  • 3
  • 34
  • 29
Ole
  • 41,793
  • 59
  • 191
  • 359

1 Answers1

1

As far as the JPA specification tells us you can't change the @Version annotation via "configuration". You either use @Version in your program code or you don't.

Referring to the official JPA specification (final version, JPA 2.1) in Section 3.4.2 (page 90) we find:

An entity is automatically enabled for optimistic locking if it has a property or field mapped with a Version mapping.

[...]

If only some entities contain version attributes, the persistence provider runtime is required to check those entities for which version attributes have been specified. The consistency of the object graph is not guaranteed, but the absence of version attributes on some of the entities will not stop operations from completing.

However, you can use the concept of inheritance to provide the @Versiononly in one spot via an abstract base class. This class you be written as follows:

@MappedSuperclass
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractBaseEntity { 

    public static final long INVALID_OBJECT_ID = -42;

    @Version
    private int version;    

    @Id
    @SequenceGenerator(name = "sequence-object", sequenceName = "ID_MASTER_SEQ")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence-object")
    @Column(name = "id")
    protected Long objectID = INVALID_OBJECT_ID;

    public final int getVersion() {
        return version;
    }

    @Override
    public long getObjectID() {
        return objectID;
    }

    // ... maybe other methods or fields ...
}

Thus, all your @Entity annotated sub-classes that inherit from AbstractPersistentEntity are provided with both properties: (i) objectIDand (ii) version at once. For instance, class SomeClass can be written as:

@Entity
public class SomeClass extends AbstractBaseEntity /*implements SomeInterface*/ {
    // ... specific methods or fields ...
} 

For details on the use of @MappedSuperclass see also this answer.

Hope it helps.

MWiesner
  • 8,868
  • 11
  • 36
  • 70
  • Awesome - thanks - I'm using Spring's AbstractPersitable ATM, so I'll probably just subclass that, unless you know of something within Spring that also provides the version property. – Ole Jul 17 '16 at 01:47