brabster
brabster

Reputation: 43560

Can I annotate a member inherited from a superclass?

If I have a class such as:

class Person {
  private String name;
  ...constructor, getters, setters, equals, hashcode, tostring...
}

Can I subclass and apply annotations to the name field in the subclass, for example to apply persistence annotations, without re-implementing the rest of the class?

@Entity
class Employee extends Person {
    @Column(...)
    private String name;
}

Upvotes: 17

Views: 10614

Answers (4)

user5063151
user5063151

Reputation:

Late answer, but I think overriding the getter method is a solid approach.

This can be a superclass for all tables which has an id field. If you serialize this object into JSON the id will always appear.

@MappedSuperclass
class ModelEntity {

    @Id
    @Column(
        name      = "id",
        updatable = false,
        nullable  = false
    )
    @GeneratedValue(strategy=GenerationType.AUTO)
    public Long id
}

But let's say you have the following objects (tables) Person and Occupation where Person has a one to many relationship with Occupation.

@Entity
@Table(name = "occupation")
Occupation extends ModelEntity {

    @Column
    String company

    @Column 
    String position
}

@Entity
@Table(name = "person")
Person extends ModelEntity {

    @Column
    String name

    @OneToMany
    Occupation occupation
}

Provided that id is present in all of the classes that extend ModelEntity if you were to serialize a Person object, you would get something like:

{
    "id" : 1,
    "name" : "Jordan",

    "occupation" : {
        "id" : 1,
        "company" : "WalMart",
        "position" : "Engineer"
    }

}

If you did not want the id to show up in the Occupation object, but you did want it to show up in the Person object, you can implement a getId() method at the Occupation class level, and apply desired annotations:

@Transient
public Long getId() {

    return id;   
}

Now your JSON would appear as follows: even though they both have an id column in the actual database:

{
    "id" : 1,
    "name" : "Jordan",

    "occupation" : {
        "company" : "WalMart",
        "position" : "Engineer"
    }

}

Upvotes: 1

tbsalling
tbsalling

Reputation: 4545

No - you will get two different fields. The annotated name field in Employee will be hiding the name field in the Person class. Person.name will not be annotated.

Upvotes: 0

Evgeniy Dorofeev
Evgeniy Dorofeev

Reputation: 136012

That wont work since the fields in super class will not be affected, but you can try this

@Entity
class Employee extends Person {
  @Column(name="xxx")
  @Override
  public void setName(String name) {
     super.setName(name);
  }
  ...

Upvotes: 18

Bohemian
Bohemian

Reputation: 425033

No, you can't.

What you are proposing is field shadowing - you can't override a field.

The field name in the subclass has nothing whatsoever to do with the field name in the super class, other than it shares the same name of "name" and thus to distinguish the field in the super class, one must refer to it as super.name in the subclass.

Doing this is generally considered a "bug" (or a potential bug anyway), and best practices are to not shadow fields, because it is so easy to refer to the wrong field without knowing it.

Upvotes: 15

Related Questions