Hibernate inheritance table per subclass with different foreign key names
In one of the projects we were supposed to implement an inheritance in the db. The project based on Spring and Hibernate so we could pick one of the three inheritance methods. We decided to pick the inheritance of table for subclass. The problem as been discussed in many ways but it is not common that the names of the foreign keys are not equal to the name of the primary key.
This is a diagram of a database that will be used in our example. As far as logic goes - we have an abstraction called ABSENCE that can be either a recursive absence (REC_ABSENCE) or a month recursive absence (MONTH_REC_ABSENCE).
The recursive absence and the month recursive absence are differing from the absence in terms of data being held more than in terms of the behavior.
Of course from the logical point of view, this example can have little sense but it is just an example so don't focus on the business side.
Absence.java
package pl.grzejszczak.marcin.entity;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Version;
/**
* Absence generated by hbm2java
*/
@Entity
@Table(name = "ABSENCE")
@Inheritance(strategy = InheritanceType.JOINED)
public class Absence implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = -4572952141587410338L;
private int id;
private int version;
private Date startDate;
private Date endDate;
public Absence() {
}
@Id
@Column(name = "ID", unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
@Version
@Column(name = "VERSION", nullable = false)
public int getVersion() {
return this.version;
}
public void setVersion(int version) {
this.version = version;
}
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "START_DATE", nullable = false, length = 23)
public Date getStartDate() {
return this.startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "END_DATE", length = 23)
public Date getEndDate() {
return this.endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
}
RecursiveAbsence.java
Note that you do not have to explicitly create an id field. You define it by means of an annotation @PrimaryKeyJoinColumn with providing the name of the id column for the given entity (REC_ABSENCE_ID) and the name of the column for the id it is referencing (ID in the ABSENCE table).
package pl.grzejszczak.marcin.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
/**
*
* Hibernate mapping strategy: Inheritance mapping: joined subclasses (table per
* subclass)
*
*/
@Entity
@Table(name = "REC_ABSENCE")
@PrimaryKeyJoinColumn(name = "REC_ABSENCE_ID", referencedColumnName = "ID")
public class RecursiveAbsence extends Absence implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private boolean isMonthly;
private boolean isWeekly;
public RecursiveAbsence() {
}
@Column(name = "isMONTHLY", nullable = false, precision = 1, scale = 0)
public boolean getIsMonthly() {
return this.isMonthly;
}
public void setIsMonthly(boolean isMonthly) {
this.isMonthly = isMonthly;
}
@Column(name = "isWEEKLY", nullable = false, precision = 1, scale = 0)
public boolean getIsWeekly() {
return this.isWeekly;
}
public void setIsWeekly(boolean isWeekly) {
this.isWeekly = isWeekly;
}
}
MonthRecursiveAbsence.java
Issue with the referencing of the column name as in the previous example.
package pl.grzejszczak.marcin.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import javax.persistence.Transient;
@Entity
@Table(name = "MONTH_REC_ABSENCE")
@PrimaryKeyJoinColumn(name = "MONTH_ABSENCE_ID", referencedColumnName = "ID")
public class MonthRecursiveAbsence extends Absence implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 7844275381822579686L;
private Integer monthId;
public MonthRecursiveAbsence() {
}
@Transient
public MonthDefinitionEnum getMonth() {
return MonthDefinitionEnum.getByKey(monthId);
}
@Column(name = "MONTH_ID")
public Integer getMonthId() {
return monthId;
}
public void setMonthId(Integer monthId) {
this.monthId = monthId;
}
}