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?
Hibernate supports the three basic inheritance mapping strategies: table per class hierarchy. table per subclass. table per concrete class.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With