JPA + Hibernate Inheritance - @MappedSuperclass Example

By Arvind Rai, February 20, 2023
On this page, we will lean using JPA @MappedSuperclass annotation in Hibernate inheritance application.
1. The @MappedSuperclass annotation is annotated at a class level in which we configure mappings of columns that may be common for some database tables.
2. When @MappedSuperclass class is inherited by a class, all mapping information of this class, are applied to its subclass.
3. The @MappedSuperclass class does not represent a separate table. It only designates a class whose mapping information is applied to the entities that inherit from it.
4. The mappings of @MappedSuperclass class are configured in the same way as the mappings of @Entity class. The difference is that @Entity represents a table but @MappedSuperclass represents no table.
5. The mapping information of @MappedSuperclass class can be overridden by @Entity class using @AssociationOverride and @AttributeOverride annotations or corresponding XML elements.

Using @MappedSuperclass Annotation

Create a class with some common fields of some database tables and annotate that class with @MappedSuperclass annotation.
@MappedSuperclass
public class Person {
	@Id
	@Column(name = "id")
	private Integer id;
	@Column(name = "name")
	private String name;
	@Column(name = "age")
	private Integer age;
	@Column(name = "gender")
	private String gender;	
	@ManyToOne(cascade = CascadeType.ALL)
	@JoinColumn(name = "coll_id")
	private College college;
        -------
} 
The fields of above Person class can be common fields of classes like Student and Teacher. We can notice that Person class is not representing any table.
Now create Student class extending Person class. All the mappings of Person class will be available in Student.
@Entity
@Table(name = "student")
public class Student extends Person {
  @Column(name = "course")
  private String course;
  ------
} 

Using @AssociationOverride Annotation

The @AssociationOverride annotation is used to override a mapping for an entity relationship.
In the Person class, @JoinColumn is joining using coll_id column.
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "coll_id")
private College college; 
Suppose we need to change the join column name from coll_id to college_id for an entity. Then we need to use @AssociationOverride annotation as following.
@Entity
@AssociationOverride(
   name="college", 
   joinColumns=@JoinColumn(name="college_id")
)
@Table(name = "teacher")
public class Teacher extends Person {
  ------
} 

Using @AttributeOverride Annotation

The @AttributeOverride annotation is used to override the mapping of a basic property or field, or Id property or field.
In the Person class, name property is mapped with name column. In Teacher entity, the table teacher has different name column i.e. teacher_name. We can override name attribute from Person class to map with teacher_name using @AttributeOverride annotation as following.
@Entity
@AttributeOverride(
   name = "name", 
   column =  @Column(name = "teacher_name")
)
@Table(name = "teacher")
public class Teacher extends Person {
  ------
} 

Complete Example

1. Technologies Used
1. Java 19
2. Hibernate 6
3. Jakarta Persistence API 3
4. MySQL 5.5

2. MySQL Database
CREATE TABLE `college` (
	`coll_id` INT(5) NOT NULL,
	`name` VARCHAR(100) NULL DEFAULT NULL,
	`location` VARCHAR(50) NULL DEFAULT NULL,
	PRIMARY KEY (`coll_id`)
)

CREATE TABLE `student` (
	`id` INT(5) NOT NULL,
	`name` VARCHAR(50) NOT NULL,
	`age` INT(3) NOT NULL,
	`gender` VARCHAR(10) NOT NULL,
	`course` VARCHAR(20) NOT NULL,
	`coll_id` INT(5) NOT NULL,
	PRIMARY KEY (`id`)
)

CREATE TABLE `teacher` (
	`id` INT(5) NOT NULL,
	`teacher_name` VARCHAR(50) NOT NULL,
	`age` INT(3) NOT NULL,
	`gender` VARCHAR(10) NOT NULL,
	`subject` VARCHAR(50) NOT NULL,
	`college_id` INT(5) NOT NULL,
	PRIMARY KEY (`id`)
) 
3. pom.xml
<dependencies>
	<dependency>
		<groupId>org.hibernate</groupId>
		<artifactId>hibernate-core</artifactId>
		<version>6.1.6.Final</version>
	</dependency>
	<dependency>
		<groupId>org.hibernate</groupId>
		<artifactId>hibernate-entitymanager</artifactId>
		<version>6.0.0.Alpha7</version>
	</dependency>		
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>8.0.32</version>
	</dependency>
</dependencies> 
4. persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence
          https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
	version="3.0">
	<persistence-unit name="com.concretepage">
		<description>Procedure Demo</description>
		<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
		<properties>
			<property name="hibernate.dialect"
				value="org.hibernate.dialect.MySQLDialect" />
			<property name="jakarta.persistence.jdbc.driver"
				value="com.mysql.cj.jdbc.Driver" />
			<property name="jakarta.persistence.jdbc.url"
				value="jdbc:mysql://localhost/concretepage" />
			<property name="jakarta.persistence.jdbc.user" value="root" />
			<property name="jakarta.persistence.jdbc.password"
				value="cp" />
		</properties>
	</persistence-unit>
</persistence> 
5. Java Code
HibernateUtil.java
package com.concretepage.util;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;

public class HibernateUtil {
 	private static final EntityManagerFactory emFactory;
	static {
		   emFactory = Persistence.createEntityManagerFactory("com.concretepage");
	}
	public static EntityManager getEntityManager(){
		return emFactory.createEntityManager();
	}
}
College.java
package com.concretepage.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

@Entity
@Table(name = "college")
public class College {
    @Id
    @Column(name = "coll_id")
    private Integer collId;
    @Column(name = "name")
    private String name;
    @Column(name = "location")
    private String location;
    public College(Integer collId, String name, String location) {
      this.collId = collId;
      this.name = name;
      this.location = location;
    }
    // Setters and Getters
} 
Person.java
package com.concretepage.entity;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.MappedSuperclass;

@MappedSuperclass
public class Person {
	@Id
	@Column(name = "id")
	private Integer id;
	@Column(name = "name")
	private String name;
	@Column(name = "age")
	private Integer age;
	@Column(name = "gender")
	private String gender;	
	@ManyToOne(cascade = CascadeType.ALL)
	@JoinColumn(name = "coll_id")
	private College college;	
	public Person(Integer id, String name, Integer age, String gender, College college) {
	  this.id = id;
	  this.name = name;
	  this.age = age;
	  this.gender = gender;
	  this.college = college;
	}
        // Setters and Getters 
} 
Student.java
package com.concretepage.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;

@Entity
@Table(name = "student")
public class Student extends Person {
  @Column(name = "course")
  private String course;

  public Student(Integer id, String name, Integer age, String gender, College college, String course) {
	super(id, name, age, gender, college);
	this.course = course;
  }
  // Setters and Getters
}  
Teacher.java
package com.concretepage.entity;
import jakarta.persistence.AssociationOverride;
import jakarta.persistence.AttributeOverride;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.Table;

@Entity
@AssociationOverride(name="college", joinColumns=@JoinColumn(name="college_id"))
@AttributeOverride(name = "name", column =  @Column(name = "teacher_name"))
@Table(name = "teacher")
public class Teacher extends Person {
  @Column(name = "subject")
  private String subject;

  public Teacher(Integer id, String name, Integer age, String gender, College college, String subject) {
	super(id, name, age, gender, college);
	this.subject = subject;
  }
  // Setters and Getters
} 
Main.java
package com.concretepage;
import com.concretepage.entity.College;
import com.concretepage.entity.Student;
import com.concretepage.entity.Teacher;
import com.concretepage.util.HibernateUtil;
import jakarta.persistence.EntityManager;

public class Main {
  public static void main(String[] args) {
	EntityManager entityManager = HibernateUtil.getEntityManager();
	entityManager.getTransaction().begin();
	
	College college = new College(11, "ABC College", "Port Blair");
	Student student = new Student(101, "Mohan", 25, "Male", college, "B.Tech");
	Teacher teacher = new Teacher(301, "Sohan", 25, "Male", college, "Match");	
	
	entityManager.persist(student);
	entityManager.persist(teacher);

	entityManager.getTransaction().commit();
	entityManager.close();
  }
} 
Find the data inserted into database.
JPA + Hibernate Inheritance - @MappedSuperclass Example

References

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI







©2024 concretepage.com | Privacy Policy | Contact Us