Search code examples
javajpaversionembeddable

JPA @Version in @Embeddable class


when I use the JPA @Version annotaton in an @Embeddable I get the following exception pointing at my Updateable class:

org.hibernate.AnnotationException: Unable to define @Version on an embedded class

Here is my code:

@Embeddable
public class Updateable {
    @Version
    private long modcount;

    private String updatedBy;

    private DateTime updatedAt;

    // getters & setters
}
@Entity
public class SomeEntity  {
    @Id
    private Long id;

    @Embedded
    private Updateable updateAudit;

    // other stuff

}

Is it not possible to have a @Version in an @Embeddable, or is this Hibernate specific?


Solution

  • An embeddable class is just a convinience way of declaring reusable entity elements, i.e. your Updateable could be used in other entities without having to add the fields and the mapping again.

    As such, embeddables are part of the entity (as the name suggests they are embedded) and thus independent versioning doesn't make sense.

    Adding the @Version annotation to the embeddable only would also not make much sense since the embeddable itself can't be versioned and you'd have to deal with cases where multiple embeddables are contained in a single entity (e.g. which version should be used in that case?). So since @Version only makes sense for entities it's easier to just allow that annotation for entities or mapped superclasses.

    Actually although the JPA spec recommends that version properties are numeric, strings or timestamps Hibernate seems to provide user defined version types:

    The version column may be a numeric (the recommended solution) or a timestamp. Hibernate supports any kind of type provided that you define and implement the appropriate UserVersionType.

    So what you might be able to do (not tested, just derived from the docs) if you want to use Updateable as your version is to provide a custom user type for Updateable and then use it like this:

    @Entity
    public class SomeEntity  {
      @Id
      private Long id;
    
      @Type( "your.custom.UserVersionType" )
      @Version
      private Updateable updateAudit;
    
      // other stuff
    }