Inheritance Type (With Hibernate)
You can read about inheritance type on many sites, but one thing that I’ve always looked for is a graphical example.
There are three main types of inheritance:
- SINGLE_TABLE
- JOINED
- TABLE_PER_CLASS
All of the following is assuming you are using Hibernate.
SINGLE_TABLE
The first I shall describe is SINGLE_TABLE. For this, there is exactly one table. The base entity contains the primary key (as shown in class A). A table is created with the base entities name, E.g. A. All the columns from entity A and all tables that extend A, simply add their columns to table A.
In the following example, there are three classes, A, B and C. B and C extend A.
A.java
package uk.co.vsf.MyApp.database.beans;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class A
{
@Id
private Integer id;
private String name;
private Double decimalValue;
private String stringValue;
public A()
{
}
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public Double getDecimalValue()
{
return decimalValue;
}
public void setDecimalValue(Double decimalValue)
{
this.decimalValue = decimalValue;
}
public String getStringValue()
{
return stringValue;
}
public void setStringValue(String stringValue)
{
this.stringValue = stringValue;
}
}
B.java
package uk.co.vsf.MyApp.database.beans;
import javax.persistence.Entity;
@Entity
public class B extends A
{
private String bString;
private Double bDouble;
private Integer bInteger;
public B()
{
}
public String getbString()
{
return bString;
}
public void setbString(String bString)
{
this.bString = bString;
}
public Double getbDouble()
{
return bDouble;
}
public void setbDouble(Double bDouble)
{
this.bDouble = bDouble;
}
public Integer getbInteger()
{
return bInteger;
}
public void setbInteger(Integer bInteger)
{
this.bInteger = bInteger;
}
}
C.java
package uk.co.vsf.MyApp.database.beans;
import javax.persistence.Entity;
@Entity
public class C extends A
{
private String cString;
private Double cDouble;
private Integer cInteger;
public C()
{
}
public void setcString(String cString)
{
this.cString = cString;
}
public String getcString()
{
return cString;
}
public void setcDouble(Double cDouble)
{
this.cDouble = cDouble;
}
public Double getcDouble()
{
return cDouble;
}
public void setcInteger(Integer cInteger)
{
this.cInteger = cInteger;
}
public Integer getcInteger()
{
return cInteger;
}
}
And this is the resultant table:
So what happens when you select on object C? It will create a query which will limit to Dtype = ‘C’. So there is one big advantage which is that there is no joining required, but the biggest issue is that the more classes that extend the base entity, the more columns will be added to the table.
JOINED
Joined creates a table for each entity, including the base entity and effectively creates the exact structure that has been declared in the Java classes. For example with the Java classes above, there will be three tables. Table A will contain the common code which is in the base entity. Two further tables will be created, B and C. They will contain their extra columns, but will also have a key named after the Id column in table A. That key is used to join from the base table to the extending tables.
Since all the classes remain the same, the only line that needs to be altered is in A.java. Change SINGLE_TABLE to JOINED as seen below:
A.java
@Inheritance(strategy = InheritanceType.JOINED)
And this is the resultant tables:
So what happens when you select C? It will join to table C in order to create the full object. This can be a great way to model the objects into the database, but when there are more than about four entities that extend the base entity, be aware of performance issues!
TABLE_PER_CLASS
Table per class does effectively what it says on the tin, there is a table per class created. So in our example classes there will be A, B and C. Unlike JOINED, all columns needed will be in all tables.
Since all the classes remain the same, the only line that needs to be altered is in A.java. Change JOINED to TABLE_PER_CLASS as seen below:
A.java
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
And this is the resultant tables:
So what happens when you select C? It shouldn’t need to join (although I have yet to test it). This approach is better than JOINED in that it doesn’t need to join when querying, but has the downside that data columns are not necessarily normalised.
Please enable the Disqus feature in order to add comments