0% found this document useful (0 votes)
19 views

Hibernate+Inheritance

Uploaded by

Mohamamd
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
19 views

Hibernate+Inheritance

Uploaded by

Mohamamd
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 23

Hibernate Inheritance – MappedSuperclass

Using the MappedSuperclass strategy, inheritance is only evident in the class, but not
the entity model.
Let's start by creating a Person class which will represent a parent class:
@MappedSuperclass
public class Person {

@Id
private long personId;
private String name;

// constructor, getters, setters


}
Notice that this class no longer has an @Entity annotation, as it won't be persisted
in the database by itself.
Next, let's add an Employee sub-class:

@Entity
public class MyEmployee extends Person {
private String company;
// constructor, getters, setters
}
In the database, this will correspond to one “MyEmployee” table with three columns
for the declared and inherited fields of the sub-class.
If we're using this strategy, ancestors cannot contain associations with other entities.

Hibernate Inheritance – Single Table


Hibernate Inheritance
In this inheritance strategy, only one table is created for all the classes involved in the
hierarchy with an additional column known as a discriminator column. The discriminator
column helps in differentiating between the two subclasses. A SINGLE_TABLE strategy is
the default strategy.
Following are the annotations used in this strategy:
1. @Inheritance– It defines the inheritance strategy used in the application. This annotation is
specified on the entity class that is the root of all the entity classes.
• @DiscriminatorColumn- It specifies the discriminator column for SINGLE_TABLE and
JOINED inheritance strategies.
• @DiscriminatorValue- Discriminator values are the values of the
@DiscriminatorColumn. This annotation is used to specify the values of the discriminator
column for the given type entity.
Syntax of SINGLE_TABLE Inheritance

2
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
3

If @Inheritance annotation is not specified or no strategy is specified, it will consider


SINGLE_TABLE strategy by default.
Example of SINGLE_TABLE Inheritance
In this example, we are taking three classes; i.e., Payment.java,
Card.java, and Cheque.java.
The class- hierarchy is given below:-

1. Create all POJO classes.


In this step, we are going to create all the persistent classes, i.e., Payment.java, Card.java,
and Cheque.java.
Payment.java
1

2
import javax.persistence.Column;
3 import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
4 import javax.persistence.Entity;
import javax.persistence.Id;
5 import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
6
import javax.persistence.Table;
7 @Entity
@Table(name="payment")
8 @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "paymtmode", discriminatorType =
9 DiscriminatorType.STRING, length = 10)
public class Payment {
10 @Id
@Column(name="payid")
11 private int id;
12 @Column(name="amount")
private int amount;
13 public int getId() {
return id;
14 }
public void setId(int id) {
15 this.id = id;
}
16 public int getAmount() {
return amount;
17
}
18 public void setAmount(int amount) {
this.amount = amount;
19 }
}

Card.java

2 import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
3 import javax.persistence.Entity;
@Entity
4 @DiscriminatorValue(value="card")
public class Card extends Payment{
5 @Column(name="cardnum")
private int cardno;
6 @Column(name="crdtype")
private String card_type;
7
public int getCardno() {
8 return cardno;
}
9 public void setCardno(int cardno) {
this.cardno = cardno;
10 }
public String getCard_type() {
11 return card_type;
}
12
public void setCard_type(String card_type) {
13 this.card_type = card_type;
}
14 }

15

Cheque.java

2 import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
3 import javax.persistence.Entity;
@Entity
4
@DiscriminatorValue(value="cheque")
5 public class Cheque extends Payment {
@Column(name="chqnum")
6 private int chequeno;
@Column(name="chqtype")
7 private String cheque_type;
public int getChequeno() {
8 return chequeno;
}
9
public void setChequeno(int chequeno) {
10 this.chequeno = chequeno;
}
11 public String getCheque_type() {
return cheque_type;
12 }
public void setCheque_type(String cheque_type) {
13 this.cheque_type = cheque_type;
}
14
}

• Create the Configuration file.


The configuration file contains the information of mapping classes and database. We will
map all the persistent classes in the configuration file (hibernate.cfg.xml).
hibernate.cfg.xml

2 <?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/
3
Hibernate Configuration DTD 3.0//EN"
4 "http://hibernate.sourceforge.net/hibernate-
configuration-3.0.dtd">
5 <hibernate-configuration>
<session-factory>
6 <property name="hibernate.dialect">org.hibernate.dialect
.MySQL5Dialect</property>
7 <property name="hibernate.connection.driver_class">
com.mysql.jdbc.Driver</property>
8 <property name="hibernate.connection.url">jdbc:mysql://
9 localhost:3306/example</property>
<property name="hibernate.connection.username">root</property>
10 <property name="hibernate.connection.password">root</property>
<property name="hbm2ddl.auto">update</property>
11
<mapping class="com.app.InheritMappp.Pay"></mapping>
12 <mapping class="com.app.InheritMappp.Card"></mapping>
<mapping class="com.app.InheritMappp.Cheque"></mapping>
13 </session-factory>
</hibernate-configuration>

• Create the main class that stores the object of Persistent object
In this step, we are going to create a main class (which contains the main method) that
stores the object of the persistent class.
App.java
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class App


{
public static void main( String[] args )
{
Configuration cfg= new Configuration();
cfg.configure("hibernate.cfg.xml");
SessionFactory s= cfg.buildSessionFactory();
Session session=s.openSession();
session.beginTransaction();

Pay p=new Pay();


p.setAmount(5100);

Card c= new Card();


c.setAmount(1000);
c.setCardno(33558882);
c.setCard_type("VISA");

Cheque chq=new Cheque();


chq.setAmount(11100);
chq.setChequeno(010036);
chq.setCheque_type("ORDER");

session.save(p);
session.save(c);
session.save(chq);

session.getTransaction().commit();

System.out.println( "successfully added" );


}
}

1
import org.hibernate.Session;
2 import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
3
public class App
4 {
public static void main( String[] args )
5
{
6 Configuration cfg= new Configuration();
cfg.configure("hibernate.cfg.xml");
7 SessionFactory s= cfg.buildSessionFactory();
Session session=s.openSession();
8 session.beginTransaction();
9 Pay p=new Pay();
p.setAmount(5100);
10

11 Card c= new Card();


c.setAmount(1000);
12 c.setCardno(33558882);
c.setCard_type("VISA");
13
Cheque chq=new Cheque();
14 chq.setAmount(11100);
chq.setChequeno(010036);
15 chq.setCheque_type("ORDER");
16
session.save(p);
17 session.save(c);
session.save(chq);
18

19 session.getTransaction().commit();
20 System.out.println( "successfully added" );
}
21
}
22

23

• OUTPUT
• DATABASE TABLE

DISADVANTAGES
The main disadvantages of this strategy are:
• Most of the values are null in the table; hence, we cannot apply not null constraint.
• In this strategy, the table cannot be normalized, which means we cannot expand this table
into new tables or columns.
To overcome these disadvantages, we use TABLE_PER_CLASS strategy.

Hibernate Inheritance Table Per Class


In this inheritance strategy, table per class is generated. It means a separate table is
generated for each POJO class involved in the hierarchy. Unlike
the SINGLE_TABLE strategy, there are no nullable values present in the tables. So, to
overcome the disadvantages of the SINGLE_TABLE strategy, we use
TABLE_PER_CLASS.
Syntax of TABLE_PER_CLASS Inheritance

2 @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
3

Here, Inheritance Type defines the inheritance strategy we are using.

Example of TABLE_PER_CLASS Inheritance

In this example, we are going to take three classes; i.e., Payment.java,


Card.java, and Cheque.java.
The class hierarchy is given below:-

1) Create all POJO Classes


In this step, we are going to create all the POJO classes, i.e., Payment.java, Card.java,
and Cheque.java.
Payment.java

2
import javax.persistence.Column;
3 import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
4 import javax.persistence.GenerationType;
import javax.persistence.Id;
5 import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
6 import javax.persistence.Table;
@Entity
7 @Table(name="p1")
8 @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Payment {
9 @Id
@GeneratedValue(strategy=GenerationType.AUTO)
10 @Column(name="payid")
private int id;
11
@Column(name="amount")
12 private int amount;
public int getId() {
13 return id;
}
14 public void setId(int id) {
this.id = id;
15 }
public int getAmount() {
16
return amount;
17 }
public void setAmount(int amount) {
18 this.amount = amount;
}
}

2 import javax.persistence.Column;
import javax.persistence.Entity;
3 import javax.persistence.Table;
@Entity
4 @Table(name="c1")
public class Card extends Payment {
5 @Column(name="cardnum")
private int cardno;
6 @Column(name="cardtype")
private String card_type;
7
public int getCardno() {
8 return cardno;
}
9 public void setCardno(int cardno) {
this.cardno = cardno;
10 }
public String getCard_type() {
11 return card_type;
}
12 public void setCard_type(String card_type) {
this.card_type = card_type;
13 }
}
14

15

16

Cheque.java

8
import javax.persistence.Column;
9 import javax.persistence.Entity;
import javax.persistence.Table;
10 @Entity
@Table(name="ch1")
11 public class Cheque extends Payment {
@Column(name="chequeno")
12
private int chequeno;
13 @Column(name="chequetype")
private String cheque_type;
14 public int getChequeno() {
return chequeno;
15 }
public void setChequeno(int chequeno) {
16 this.chequeno = chequeno;
}
17 public String getCheque_type() {
return cheque_type;
18
}
19 public void setCheque_type(String cheque_type) {
this.cheque_type = cheque_type;
20 }
}
21

22
23

24

25

2) Create the Configuration file.


The configuration file contains the information of mapping classes and database. We are
going to map all the POJO classes in the configuration file (hibernate.cfg.xml).
hibernate.cfg.xml

2
<?xml version='1.0' encoding='UTF-8'?>
3 <!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 5.3//EN"
4 "http://hibernate.sourceforge.net/hibernate-configuration-5.3.dtd">

5 <hibernate-configuration>
<session-factory>
6
<property name="hibernate.hbm2ddl.auto">update</property>
7 <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect
</property>
8 <property name="hibernate.connection.url">jdbc:mysql://
localhost:3306/example</property>
9 <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver
</property>
10 <property name="connection.username">root</property>
<property name="connection.password">root</property>
11
<mapping class="com.app.Concrete_Map2.Payment"></mapping>
12
<mapping class="com.app.Concrete_Map2.Card"></mapping>
13 <mapping class="com.app.Concrete_Map2.Cheque"></mapping>

14 </session-factory>
</hibernate-configuration>

3) Create the main class that stores the object of POJO object
In this step, we are going to create the main class (which contains the main method) that
stores the object of the POJO class.
App.java
1

2
import org.hibernate.Session;
3 import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
4

5 public class App


{
6 public static void main( String[] args )
{
7 Configuration cfg= new Configuration();
cfg.configure("hibernate.cfg.xml");
8 SessionFactory s= cfg.buildSessionFactory();
ssion session=s.openSession();
9 session.beginTransaction();
10
Payment pay=new Payment();
11 pay.setAmount(19800);

12 Card card= new Card();


card.setCardno(540213);
13 card.setCard_type("MASTER");
card.setAmount(8956);
14
Cheque cheque= new Cheque();
15
cheque.setChequeno(45630);
16 cheque.setCheque_type("ORDER");
cheque.setAmount(13654);
17
session.save(pay);
18 session.save(card);
session.save(cheque);
19
session.getTransaction().commit();
20 System.out.println("Successfull!!");
21 }
}

4. OUTPUT
5. DATABASE TABLES
payment table

card table

cheque table

Disadvantages of TABLE_PER_CLASS inheritance strategy

Following are the problems in TABLE_PER_CLASS inheritance strategy:


• The data belongs to the superclass is scattered across many subclasses. Hence, the
repeated column (amount) is present in the subclasses.
• Any changes made to the superclass will affect the tables of subclasses.
Although this strategy is better than the SINGLE_TABLE inheritance strategy, it also has a
few disadvantages. To overcome these disadvantages, we use JOINED_TABLE inheritance
strategy.

Hibernate Inheritance Joined Table


In this inheritance strategy, mapping of the child class fields is done with the common fields
of the parent class in a separate table. In other words, the common entities between the
child classes and the parent class are mapped in the separate database table. To overcome
the disadvantages of TABLE_PER_CLASS strategy, we are using JOINED table strategy.
Hence, there is no repeated column present in the subclass tables.
Syntax of JOINED Table Inheritance

2
@Inheritance(strategy=InheritanceType.JOINED)
3

Here, InheritanceType defines the inheritance strategy we are using.


Example of JOINED table inheritance
Let’s understand this strategy by an example. Here, we are taking three classes that
are Payment.java, Card.java, and Cheque.java.
The class hierarchy is given below:-

1) Create all POJO Classes


In this step, we are going to create all the POJO classes, i.e., Payment.java, Card.java, and
Cheque.java.
Payment.java

2 import javax.persistence.Column;
import javax.persistence.Entity;
3 import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
4 import javax.persistence.Id;
import javax.persistence.Inheritance;
5 import javax.persistence.InheritanceType;
import javax.persistence.Table;
6
@Entity
7
@Table(name="pp")
8 @Inheritance(strategy=InheritanceType.JOINED)
public class Payment {
9
@Id
10 @GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="payid")
11 private int id;
12
@Column(name="amount")
13 private double amount;

14 public int getId() {


return id;
15 }
public void setId(int id) {
16 this.id = id;
}
17 public double getAmount() {
18 return amount;
}
19 public void setAmount(double amount) {
this.amount = amount;
20 }
}
21

Card.java

2 import javax.persistence.Column;
import javax.persistence.Entity;
3 import javax.persistence.Table;
4
@Entity
5 @Table(name="ccd")

6 public class Card extends Payment {


7 @Column(name="cardnum")
private int cardno;
8
@Column(name="cardtype")
9 private String card_type;

10 public int getCardno() {


return cardno;
11 }
public void setCardno(int cardno) {
12 this.cardno = cardno;
}
13
public String getCard_type() {
14 return card_type;
}
15 public void setCard_type(String card_type) {
this.card_type = card_type;
16 }
}

Cheque.java

1
import javax.persistence.Column;
2 import javax.persistence.Entity;
import javax.persistence.Table;
3

4 @Entity
@Table(name="ch")
5
public class Cheque extends Payment {
6
@Column(name="chqno")
7 private int chqno;
@Column(name="chqtype")
8 private String chq_type;
9
public int getChqno() {
return chqno;
10 }
public void setChqno(int chqno) {
11 this.chqno = chqno;
}
12 public String getChq_type() {
return chq_type;
13
}
14 public void setChq_type(String chq_type) {
this.chq_type = chq_type;
15 }
}
16

2) Create the configuration file.


The configuration file contains the information of mapping classes and database. We are
going to map all the POJO classes in the configuration file (hibernate.cfg.xml).
hibernate.cfg.xml

2 <?xml version='1.0' encoding='UTF-8'?>


<!DOCTYPE hibernate-configuration PUBLIC
3 "-//Hibernate/Hibernate Configuration DTD 5.3//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-5.3.dtd">
4
<hibernate-configuration>
5
<session-factory>
6 <property name="hibernate.hbm2ddl.auto">update</property>
<property name="hibernate.dialect">org.hibernate.dialect
7 .MySQL5Dialect</property>
<propertyname="hibernate.connection.url">jdbc:mysql://
8 localhost:3306/jyotika</property>
<property name="hibernate.connection.driver_class">
9 com.mysql.jdbc.Driver</property>
<property name="connection.username">root</property>
10 <property name="connection.password">root</property>
11
<mapping class="com.app.Joined.Payment"></mapping>
12 <mapping class="com.app.Joined.Card"></mapping>
<mapping class="com.app.Joined.Cheque"></mapping>
13
</session-factory>
14 </hibernate-configuration>

15

3) Create the main class that stores the object of POJO object
In this step, we are going to create the main class (which contains the main method) that
stores the object of the POJO class.
App.java

2 import org.hibernate.Session;
import org.hibernate.SessionFactory;
3 import org.hibernate.cfg.Configuration;
4 public class App
{
5
public static void main( String[] args )
6 {
Configuration cfg= new Configuration();
7 cfg.configure("hibernate.cfg.xml");
SessionFactory s= cfg.buildSessionFactory();
8 Session sess= s.openSession();
sess.beginTransaction();
9
Payment payment= new Payment();
10 payment.setAmount(6900);
11

12 Card card= new Card();


card.setCardno(645325);
13 card.setCard_type("Visa");
card.setAmount(1500);
14
Cheque cheque=new Cheque();
15 cheque.setAmount(1600);
cheque.setChqno(102265);
16
cheque.setChq_type("Order");
17
sess.save(payment);
18 sess.save(card);
sess.save(cheque);
19 sess.getTransaction().commit();

20 System.out.println("successfully inserted");
}
21 } tem.out.println("successfully inserted");
}
22
}

OUTPUT

4. DATABASE TABLES
payment table

card table

cheque table

Following are the advantages of this strategy:


• Repeated columns are not present in the database tables.
• Nullable values are not present in the table.
Polymorphic Queries
Querying a base class will retrieve all the sub-class entities as well.
Let's see this behavior in action with a JUnit test:
@Test
public void givenSubclasses_whenQuerySuperclass_thenOk() {
Book book = new Book(1, "1984", "George Orwell");
session.save(book);
Pen pen = new Pen(2, "my pen", "blue");
session.save(pen);

assertThat(session.createQuery("from MyProduct")
.getResultList()).hasSize(2);
}
In this example, we've created two Book and Pen objects, then queried their super-
class MyProduct to verify that we'll retrieve two objects.

Hibernate can also query interfaces or base classes which are not entities but are
extended or implemented by entity classes. Let's see a JUnit test using
our @MappedSuperclass example:
@Test
public void givenSubclasses_whenQueryMappedSuperclass_thenOk() {
MyEmployee emp = new MyEmployee(1, "john", "baeldung");
session.save(emp);

assertThat(session.createQuery(
"from com.baeldung.hibernate.pojo.inheritance.Person")
.getResultList())
.hasSize(1);
}
Note that this also works for any super-class or interface, whether it's
a @MappedSuperclass or not. The difference from a usual HQL query is that we have
to use the fully qualified name since they are not Hibernate-managed entities.
If we don't want a sub-class to be returned by this type of query, then we only need to
add the Hibernate @Polymorphism annotation to its definition, with type EXPLICIT:
@Entity
@Polymorphism(type = PolymorphismType.EXPLICIT)
public class Bag implements Item { ...}
In this case, when querying for Items, the Bag records won't be returned.
Choosing a Strategy
Choosing the right inheritance strategy is not an easy task. As so often, you have to
decide which advantages you need and which drawback you can accept for your
application. Here are a few recommendations:

• If you require the best performance and need to use polymorphic queries
and relationships, you should choose the single table strategy. But be aware,
that you can’t use not null constraints on subclass attributes which increase
the risk of data inconsistencies.
• If data consistency is more important than performance and you need
polymorphic queries and relationships, the joined strategy is probably your
best option.
• If you don’t need polymorphic queries or relationships, the table per class
strategy is most likely the best fit. It allows you to use constraints to ensure
data consistency and provides an option of polymorphic queries. But keep in
mind, that polymorphic queries are very complex for this table structure and
that you should avoid them.

How to map an entity to multiple tables


The @Table annotation defines the primary table to which the entity attributes get
mapped by default. The @SecondaryTable annotation specifies the second database
table to which the entity gets mapped.
@Entity
@Table(name = "author")
@SecondaryTable(name = "author_details")
public class Author {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(updatable = false, nullable = false)
private Long id;

@Version
private int version;

private String firstName;

private String lastName;


@Column(table = "author_details")
private String pseudonym;

@Column(table = "author_details")
private Category category;

...
}

That’s all you need to do to map the 2 database tables to the Author entity. Every time
you persist or update an Author entity, Hibernate writes the values of
the id, firstName, lastName, and version attributes to the author table, and the values
of the id, pseudonym, and category attributes to the author_details table.
And when you read an Author entity, Hibernate gets the attribute values from the
same 2 tables.

You might also like