Is it possible to add JPA annotation to superclass instance variables?

22,447

Solution 1

You might want to annotate MyAbstractEntity with @MappedSuperclass class so that hibernate will import the configuration of MyAbstractEntity in the child and you won't have to override the field, just use the parent's. That annotation is the signal to hibernate that it has to examine the parent class too. Otherwise it assumes it can ignore it.

Solution 2

Here is an example with some explanations that may help.

@MappedSuperclass:

  • Is a convenience class
  • Is used to store shared state & behavior available to child classes
  • Is not persistable
  • Only child classes are persistable

@Inheritance specifies one of three mapping strategies:

  1. Single-Table
  2. Joined
  3. Table per Class

@DiscriminatorColumn is used to define which column will be used to distinguish between child objects.

@DiscriminatorValue is used to specify a value that is used to distinguish a child object.

The following code results in the following:

enter image description here

You can see that the id field is in both tables, but is only specified in the AbstractEntityId @MappedSuperclass.

Also, the @DisciminatorColumn is shown as PARTY_TYPE in the Party table.

The @DiscriminatorValue is shown as Person as a record in the PARTY_TYPE column of the Party table.

Very importantly, the AbstractEntityId class does not get persisted at all.

I have not specified @Column annotations and instead are just relying on the default values.

If you added an Organisation entity that extended Party and if that was persisted next, then the Party table would have:

  • id = 2
  • PARTY_TYPE = "Organisation"

The Organisation table first entry would have:

  • id = 2
  • other attribute value associated specifically with organisations

    @MappedSuperclass
    @SequenceGenerator(name = "sequenceGenerator", 
            initialValue = 1, allocationSize = 1)
    public class AbstractEntityId implements Serializable {

        private static final long serialVersionUID = 1L;

        @Id
        @GeneratedValue(generator = "sequenceGenerator")
        protected Long id;

        public AbstractEntityId() {}

        public Long getId() {
            return id;
        }
    }

    @Entity
    @Inheritance(strategy = InheritanceType.JOINED)
    @DiscriminatorColumn(name = "PARTY_TYPE", 
            discriminatorType = DiscriminatorType.STRING)
    public class Party extends AbstractEntityId {

        public Party() {}

    }

    @Entity
    @DiscriminatorValue("Person")
    public class Person extends Party {

        private String givenName;
        private String familyName;
        private String preferredName;
        @Temporal(TemporalType.DATE)
        private Date dateOfBirth;
        private String gender;

        public Person() {}

        // getter & setters etc.

    }

Hope this helps :)

Solution 3

Mark the superclass as

@MappedSuperclass

and remove the property from the child class.

Solution 4

Annotating your base class with @MappedSuperclass should do exactly what you want.

Share:
22,447
Kristofer
Author by

Kristofer

Updated on December 24, 2021

Comments

  • Kristofer
    Kristofer over 2 years

    I am creating entities that are the same for two different tables. In order do table mappings etc. different for the two entities but only have the rest of the code in one place - an abstract superclass. The best thing would be to be able to annotate generic stuff such as column names (since the will be identical) in the super class but that does not work because JPA annotations are not inherited by child classes. Here is an example:

    public abstract class MyAbstractEntity {
    
      @Column(name="PROPERTY") //This will not be inherited and is therefore useless here
      protected String property;
    
    
      public String getProperty() {
        return this.property;
      }
    
      //setters, hashCode, equals etc. methods
    }
    

    Which I would like to inherit and only specify the child-specific stuff, like annotations:

    @Entity
    @Table(name="MY_ENTITY_TABLE")
    public class MyEntity extends MyAbstractEntity {
    
      //This will not work since this field does not override the super class field, thus the setters and getters break.
      @Column(name="PROPERTY") 
      protected String property;
    
    }
    

    Any ideas or will I have to create fields, getters and setters in the child classes?

    Thanks, Kris