Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate (JPA) inheritance mapping of abstract super classes

My data model represents legal entities, such as a Business or a Person. Both are tax-paying entities, and both have a TaxID, a collection of phone numbers, and a collection of mailing addresses.

I have a Java model with two concrete classes that extend an abstract class. The abstract class has properties and collections that are common to both concrete classes.

AbstractLegalEntity        ConcreteBusinessEntity    ConcretePersonEntity -------------------        ----------------------    -------------------- Set<Phone> phones          String name               String first Set<Address> addresses     BusinessType type         String last String taxId                                         String middle  Address                    Phone -------                    ----- AbsractLegalEntity owner   AbstractLegalEntity owner String street1             String number String street2            String city String state String zip 

I'm using Hibernate JPA Annotations on a MySQL database, with classes like this:

@MappedSuperclass public abstract class AbstractLegalEntity {     private Long id;  // Getter annotated with @Id @Generated     private Set<Phone> phones = new HashSet<Phone>();  // @OneToMany     private Set<Address> address = new HashSet<Address>();  // @OneToMany     private String taxId; }  @Entity public class ConcretePersonEntity extends AbstractLegalEntity {     private String first;     private String last;     private String middle; }  @Entity public class Phone {     private AbstractLegalEntity owner; // Getter annotated @ManyToOne @JoinColumn     private Long id;     private String number; } 

The problem is that Phone and Address objects need to refer to their owner, which is an AbstractLegalEntity. Hibernate complains:

@OneToOne or @ManyToOne on Phone references an unknown  entity: AbstractLegalEntity 

It seems like this would be a fairly common Java inheritance scenario, so I hope that Hibernate would support it. I've tried changing the mapping for AbstractLegalEntity based on a Hibernate forum question, no longer using @MappedSuperclass:

@Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 

However, now I get the following error. When reading up on this inheritance mapping type, it looks like I have to use SEQUENCE not IDENTITY, and MySQL doesn't support SEQUENCE.

Cannot use identity column key generation with <union-subclass>  mapping for: ConcreteBusinessEntity 

I'm making more progress toward getting things working when I use the following mapping.

@Entity @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(         name="entitytype",         discriminatorType=DiscriminatorType.STRING ) 

I'm thinking I should continue down this path. My concern is that I'm mapping it as an @Entity when I really don't ever want an instance of AbstractLegalEntity to ever exist. I'd like to know if this is the right approach. What is the correct approach I should be taking for this situation?

like image 939
Tauren Avatar asked Nov 24 '10 09:11

Tauren


People also ask

What inheritance mapping strategies are available in Hibernate?

Hibernate supports the three basic inheritance mapping strategies: table per class hierarchy. table per subclass. table per concrete class.

What are the three types of inheritance mapping strategies described in JPA?

Inheritance is the core concept of object oriented language, therefore we can use inheritance relationships or strategies between entities. JPA support three types of inheritance strategies such as SINGLE_TABLE, JOINED_TABLE, and TABLE_PER_CONCRETE_CLASS.

Which inheritance strategy is better in Hibernate?

Keep in mind when using default JPA/Hibernate annotations, Hibernate always fetch all of subclasses. If you have a single hierarchy, prefer To use Single Table Inheritance strategy.

Which inheritance strategy specifies that the superclass and subclass in a hierarchy are mapped to different individual tables?

A “join” strategy, whereby fields or properties that are specific to a subclass are mapped to a different table than the fields or properties that are common to the parent class.


1 Answers

Use:

    @Entity     @Inheritance(strategy = InheritanceType.JOINED)     AbstractLegalEntity 

In the database you will have one table for AbstractLegalEntity, and tables for classes, which extend AbstractLegalEntity class. You won't have instances of AbstractLegalEntity if it's abstract. Polymorphism can be used here.

When you use:

    @MappedSuperclass     AbstractLegalEntity          @Entity     ConcretePersonEntity extends AbstractLegalEntity 

This will create only one table in your database called ConcretePersonEntity, containing columns from both classes.

like image 80
milbr Avatar answered Sep 18 '22 12:09

milbr