In our previous articles we have seen, one to one mapping, one to many mapping and many to many mapping, in this article we will see how to map a inheritance class structures with JPA. There are three major strategies for doing this.

1) Table per hierarchy
2) Table per concrete class
3) Table per subclass


In this particular article we will Table per hierarchy strategy to map inheritance structure, we have a abstract class Quiz with two implementations PracticeQuiz and GradeQuiz. Lets see how to mao them using table per hierarchy strategy.

JPA - Inheritance Strategy (Table per hierarchy)

In this particular article we will Table per hierarchy strategy to map inheritance structure, we have a abstract class Quiz with two implementations PracticeQuiz and GradeQuiz. Lets see how to mao them using table per hierarchy strategy.

1) Super class (Quiz.java)


package com.tbNext.hb.models;

import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
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;
import javax.persistence.Table;

@Entity
@Table(name = "QUIZ")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type")
@DiscriminatorValue("quiz")
public abstract class Quiz {

	@Id
	@Column(name = "ID")
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	@Column(name = "QUIZ_NAME")
	private String quizName;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getQuizName() {
		return quizName;
	}

	public void setQuizName(String quizName) {
		this.quizName = quizName;
	}
}

To implement inheritance strategies, we have to use @Inheritance annotation along with attributes specifing strategy. For a table per heirachy we uses SINGLE_TABLE.

We also need to define a @DiscriminatorColumn name this column will identify the type of entity in the table, and than we define a @DiscriminatorValue for each implementation. This value identifies and discriminate entities within the table.

2) Sub Class Implementation (PracticeQuiz.java)


package com.tbNext.hb.models;

import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@DiscriminatorValue("practiceQuiz")
public class PracticeQuiz extends Quiz{

	@Column(name = "MARKS")
	private double marks;

	@Column(name = "FEEDBACK")
	private String feedBack;
	

	public PracticeQuiz(double marks, String feedBack, String quizName) {
		super();
		this.marks = marks;
		this.feedBack = feedBack;
		super.setQuizName(quizName);
	}

	public double getMarks() {
		return marks;
	}

	public void setMarks(double marks) {
		this.marks = marks;
	}

	public String getFeedBack() {
		return feedBack;
	}

	public void setFeedBack(String feedBack) {
		this.feedBack = feedBack;
	}
}

3) Sub Class Implementation (GradeQuiz.java)


package com.tbNext.hb.models;

import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@DiscriminatorValue("gradeQuiz")
public class GradeQuiz extends Quiz {

	@Column(name = "GRADE")
	private double grade;

	@Column(name = "ATEMPT_NO")
	private int attemptNo;

	public GradeQuiz(double grade, int attemptNo,String quizName) {
		super();
		this.grade = grade;
		this.attemptNo = attemptNo;
		super.setQuizName(quizName);
	}

	public double getGrade() {
		return grade;
	}

	public void setGrade(double grade) {
		this.grade = grade;
	}

	public int getAttemptNo() {
		return attemptNo;
	}

	public void setAttemptNo(int attemptNo) {
		this.attemptNo = attemptNo;
	}
}


Implementation

Now lets implement the strategy, we will try to insert PracticeQuiz and GradeQuiz in the db. The generated table will contain all the columns from all the entities implementation. Only matching column values will be filled with one object persistance other non related columns will remain null.
package com.tbNext.java;

import javax.persistence.EntityManager;

import com.tbNext.hb.Utils.PersistenceManager;
import com.tbNext.hb.models.GradeQuiz;
import com.tbNext.hb.models.PracticeQuiz;
import com.tbNext.hb.models.Quiz;

/**
 * Hello world!
 *
 */
public class App {
	public static void main(String[] args) {
		// getting instance of EntityManagerFactory
		EntityManager em = PersistenceManager.INSTANCE.getEntityManager();

		// create practice quiz
		Quiz practiceQuiz = new PracticeQuiz(76, "excellent", "Mathematics");

		// create grade quiz
		Quiz gradeQuiz = new GradeQuiz(.7, 2, "Mathematics");


		// Adding entities to db
		em.getTransaction().begin();
		em.persist(practiceQuiz);
		em.persist(gradeQuiz);
		em.getTransaction().commit();

	}
}
Output: Here is expected output we can see only one tabel will all the columns is created for the whole hierarchy and only related columns are filled with values, remaining columns are null.

Hibernate: create table QUIZ (type varchar(31) not null, ID bigint not null auto_increment, QUIZ_NAME varchar(255), FEEDBACK varchar(255), MARKS double precision, ATEMPT_NO integer, GRADE double precision, primary key (ID)) ENGINE=InnoDB
Sep 13, 2015 6:11:17 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: HHH000230: Schema export complete
Hibernate: insert into QUIZ (QUIZ_NAME, FEEDBACK, MARKS, type) values (?, ?, ?, 'practiceQuiz')
Hibernate: insert into QUIZ (QUIZ_NAME, ATEMPT_NO, GRADE, type) values (?, ?, ?, 'gradeQuiz')


Following is the structure of generated table in database, only single table is created for the while hierarchy.

typeIDQUIZ_NAMEFEEDBACKMARKSATEMPT_NOGRADE
practiceQuiz1Mathematicsexcellent76NULLNULL
gradeQuiz1MathematicsNULLNULL20.7


This is it for this article, we have seen how to implement inheritance strategy in JPA using single table per hierarchy strategy. In upcoming articles we will see remaining two strategies and other useful stuff.
  • By Techburps.com
  • Oct 1, 2015
  • JPA