Hibernate supports following strategies to support Inheritance mappings in database:
- Single Table or Table per class-hierarchy (InheritanceType.SINGLE_TABLE)
- Joined or Table per subclass (InheritanceType.JOINED)
- Table per class (InheritanceType.TABLE_PER_CLASS)
Single Table strategy(aka Table per class-hierarchy)
In this strategy, a single table is created for each class hierarchy.
So, if we have a base class “Book” and a child class “ComputerBook”, only one table will be created for both of them.
For this program, we are setting the “hbm2ddl.auto” property to “create”. So, it will create the table when we execute the program.
Book.java
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | package com.topjavatutorial; import javax.persistence.DiscriminatorColumn; import javax.persistence.DiscriminatorType; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; @Entity @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name="type", discriminatorType=DiscriminatorType.STRING) @DiscriminatorValue(value="B") public class Book { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } |
The Inheritance strategy needs to be defined in following manner :
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
Next, we need to define a discriminator that will be helpful to instantiate the appropriate type when retrieving a record from the database.
We have defined a DiscriminatorColumn “type” and provided a value for the base class using following annotations :
@DiscriminatorColumn(name=”type”, discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue(value=”B”)
In the subclass ComputerBook.java, let’s provide a DiscreminatorValue of “C”.
ComputerBook.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package com.topjavatutorial; import javax.persistence.Column; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; @Entity @DiscriminatorValue(value="C") public class ComputerBook extends Book { @Column String technology; public String getTechnology() { return technology; } public void setTechnology(String technology) { this.technology = technology; } } |
Now, lets save a record of each type (Book and ComputerBook) to the database.
HibernateInheritanceDemo.java
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 26 27 28 29 30 31 32 | package com.topjavatutorial; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; public class HibernateInheritanceDemo { public static void main(String[] args) { SessionFactory factory = HibernateUtil.getSessionFactory(); Session session = factory.openSession(); Transaction trn = session.getTransaction(); trn.begin(); Book book = new Book(); book.setName("The Alchemist"); session.save(book); ComputerBook book2 = new ComputerBook(); book2.setName("Head First Java"); book2.setTechnology("Java"); session.save(book2); trn.commit(); session.close(); } } |
Output :
Hibernate:
drop table if exists Book
Hibernate:
create table Book (
type varchar(31) not null,
id integer not null auto_increment,
name varchar(255),
technology varchar(255),
primary key (id)
)
Hibernate:
insert
into
Book
(name, type)
values
(?, ‘B’)
Hibernate:
insert
into
Book
(name, technology, type)
values
(?, ?, ‘C’)
The following book table shows the table structure after saving the two records :
Table : Book
Joined or Table per subclass Inheritance Strategy
In this inheritance strategy, Hibernate creates separate tables for each class.
Here we specify the change in strategy with annotation
@Inheritance(strategy = InheritanceType.JOINED)
.
Book.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package com.topjavatutorial; import javax.persistence.*; @Entity @Inheritance(strategy = InheritanceType.JOINED) public class Book { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private String name; //getters & setters } |
ComputerBook.java
The annotation @PrimaryKeyJoinColumn is optional, but you may add it to specify custom name for the join column.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | package com.topjavatutorial; import javax.persistence.*; @Entity @PrimaryKeyJoinColumn(name="book_id") public class ComputerBook extends Book { @Column String technology; public String getTechnology() { return technology; } public void setTechnology(String technology) { this.technology = technology; } } |
If we run the HibernateInheritanceDemo.java, here will be the output :
Hibernate:
create table Book (
id integer not null auto_increment,
name varchar(255),
primary key (id)
)
Hibernate:
create table ComputerBook (
technology varchar(255),
book_id integer not null,
primary key (book_id)
)
Hibernate:
alter table ComputerBook
add constraint FK_j4wlr25mpyef1t7s72kgurtcb
foreign key (book_id)
references Book (id)
Hibernate:
insert
into
Book
(name)
values
(?)
Hibernate:
insert
into
Book
(name)
values
(?)
Hibernate:
insert
into
ComputerBook
(technology, book_id)
values
(?, ?)
Table : Book
Table : ComputerBook
As you may observe from the above results, the common data is stored in the base table (book) and the child class specific data and foreign key to the parent table.
Table per class Inheritance strategy
In this strategy, hibernate creates a different table for each subclass and parent class.
The disadvantage of this approach is that duplicate columns are created in the subclass table.
Because of the close correspondence between the entity and its table, the
@DiscriminatorColumn
annotation is not applicable to this inheritance strategy.
Since this strategy does not support the IDENTITY and AUTO generator strategies, we have to use other generation strategy options or provide a primary key explicitly.
Book.java
The root of inheritance strategy is mapped with TABLE_PER_CLASS Strategy.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package com.topjavatutorial; import javax.persistence.*; @Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public class Book { @Id @GeneratedValue(strategy = GenerationType.TABLE) private int id; private String name; // getters and setters } |
ComputerBook.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package com.topjavatutorial; import javax.persistence.*; @Entity public class ComputerBook extends Book { @Column String technology; public String getTechnology() { return technology; } public void setTechnology(String technology) { this.technology = technology; } } |
Running the HibernateInheritanceDemo.java will produce following output :
Hibernate:
create table Book (
id integer not null,
name varchar(255),
primary key (id)
)
Hibernate:
create table ComputerBook (
id integer not null,
name varchar(255),
technology varchar(255),
primary key (id)
)
//sequence generation steps
Hibernate:
insert
into
Book
(name, id)
values
(?, ?)
Hibernate:
insert
into
ComputerBook
(name, technology, id)
values
(?, ?, ?)
How to choose between the different Inheritance strategies
Read performance is best with Single table strategy as data will be read from a single table only, no joins necessary. However, if additional columns are added, the table will grow horizontally with many columns that won’t be used for most records.
With Table per class approach, any change to the parent class will need change in each of the child tables.
Joined table is the least messy of the three as any change to the class hierarchy will affect only one table. But with this approach, the read performance will slower compared to Single table strategy because of the additional joins needed.
Keeping these factors in mind, for most scenarios, the Joined table strategy is favorable of the three inheritance strategies.
© 2017, https:. All rights reserved. On republishing this post, you must provide link to original post