(Recovered from my old Blog).
I had a relatively simple requirement, with a relatively simple solution – but it is worth recording for simple reference.
Suppose I have two Hibernate classes Cat and Dog, both of which derive from the abstract class Animal. Suppose further that both Cats and Dogs can have a child collection of the class Toy.
Since Set<Toy> is shared, we want to do all the hard work in the Animal class, rather than repeat it twice.
Finally, assume that for convenience sake – the underlying table structure is shared, with just a column to indicate whether the entry is a CAT or a DOG.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class Cat extends Animal { // Implementation } public class Dog extends Animal { // Implementation } public abstract class Animal { private Set<Toy> toySet; // Implementation } public class Toy { // Implementation } |
1 2 3 4 5 6 7 8 9 10 11 12 |
CREATE TABLE animal ( id BIGINT NOT NULL, animal_type VARCHAR(10) NOT NULL, name VARCHAR(30) NOT NULL, PRIMARY KEY(id) ) CREATE TABLE toy ( id BIGINT NOT NULL, toy_short_desc VARCHAR(50), PRIMARY KEY(id) ) |
All very simple so far.
If we want to annotate this class to fulfill the requirements above, we have to:
Declare Cat and Dog as @Entity, since these become the instantiated classes.
Important – Animal also needs to be an @Entity to allow for the @ManyToOne mapping in Toy. (Remember – we said we wanted the ToySet to be shared. If you don’t declare Animal as an @Entity we will get ‘unknown entity’ exceptions.
State that Animal is the top of tree with @Inheritance.
Tell Hibernate which column should be used to discriminate between classes when mapping with @DiscriminatorColumn.
So our classes become:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
@Entity @DiscriminatorValue(value = “CAT”) public class Cat extends Animal { // Implementation } @Entity @DiscriminatorValue(value = “DOG”) public class Dog extends Animal { // Implementation } @Entity @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name = “animal_type”) @Table(name = “animal”) public abstract class Animal { private Set<Toy> toySet; // Implementation } public class Toy { // Implementation including: // @ManyToOne(targetEntity = Animal.class) } |