JavaBeat

  • Home
  • Java
    • Java 7
    • Java 8
    • Java EE
    • Servlets
  • Spring Framework
    • Spring Tutorials
    • Spring 4 Tutorials
    • Spring Boot
  • JSF Tutorials
  • Most Popular
    • Binary Search Tree Traversal
    • Spring Batch Tutorial
    • AngularJS + Spring MVC
    • Spring Data JPA Tutorial
    • Packaging and Deploying Node.js
  • About Us
    • Join Us (JBC)
  • Privacy
  • Contact Us

EclipseLink / JPA Annotations – @MappedSuperclass

March 2, 2014 by Amr Mohammed Leave a Comment

This tutorial will explain the using of @MappedSuperclass, that could be considered as an alternative choice for sharing a persistent entity state and mapping information. An entity may inherit from a super class that provides a persistent entity state and mapping information as we’ve seen previously in the @Inheritance tutorials. Unlike using of @Inheritance, the @MappedSuperclass doesn’t involve in any persistent activity and it doesn’t involve in any operations that managed by the EntityManager. The main purpose of using a @MappedSuperclass is to define a common states and mapping information that could be shared by multiple entity classes.

A @MappedSuperclass annotated class is not persisted itself, but the sub-classes are persistent. So, this annotation is used for an abstract class or a non-persistent class. The equivalent XML element is mapped-superclass in the persistent configuration file.

Some of the characteristics of @MappedSuperclass is:

  • Normally class is abstract, but it never be a persistence instance
  • Mapped superclasses can not define a table, but can define mapping for attributes.
  • This annotation doesn’t have any attributes.

Classes Design

Let’s see the classes design that would be formed the field MappedSuperclass annotation could provide a help inside it. See figure 1.1.

MappedSuperclassDesign

Figure 1.1

The License class is an abstract class contains one attribute named licenseId. Set of classes have a chance to inherit from License abstract class, but because of we are not aware of the number of classes that may inherit it we’ve denoted for any future coming classes with (AnyClass extends License).

We are supposed to have a new class called DriverLicense as an extended class and you will see it in the next section.

License.java

[code lang=”java”]
package net.javabeat.eclipselink.data;

import javax.persistence.Id;
import javax.persistence.MappedSuperclass;

@MappedSuperclass
public abstract class License {

@Id protected int licenseId;

public int getLicenseId() {
return licenseId;
}

public void setLicenseId(int licenseId) {
this.licenseId = licenseId;
}
}
[/code]

DriverLicense.java

[code lang=”java”]
package net.javabeat.eclipselink.data;

import java.util.Date;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity // Annotate the DriverLicense as an Entity that must be persisted by the JPA
@Table(name="driverlicenses") // The Table name that the instance of DriverLicense should be persisted there
public class DriverLicense extends License{
// DriverLicense Inherited  protected int
private String driverLicenseName;
@Temporal(TemporalType.DATE) // The temporal is mandatory when we are coming to deal with Date
private Date driverLicenseExpiryDate;
@Temporal(TemporalType.DATE)
private Date driverLicenseIssueDate;

@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="employeeId")
private Employee employee;

public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
public String getDriverLicenseName() {
return driverLicenseName;
}
public void setDriverLicenseName(String driverLicenseName) {
this.driverLicenseName = driverLicenseName;
}
public Date getDriverLicenseExpiryDate() {
return driverLicenseExpiryDate;
}
public void setDriverLicenseExpiryDate(Date driverLicenseExpiryDate) {
this.driverLicenseExpiryDate = driverLicenseExpiryDate;
}
public Date getDriverLicenseIssueDate() {
return driverLicenseIssueDate;
}
public void setDriverLicenseIssueDate(Date driverLicenseIssueDate) {
this.driverLicenseIssueDate = driverLicenseIssueDate;
}
}
[/code]

Database Design

The License class annotated with MappedSuperclass, so no need for creating any database table for it, meanwhile and at the other side, any entities that inherit from License class and not annotated using MappedSuperclass need a database mapping table. See Figure 1.2 that shows you the final view for the database tables.

MappedSuperclassDatabaseDesign

Figure 1.2

Notes:

  • The License class doesn’t consider as a persisted entity, cause it’s annotated as a MappedSuperclass.
  • The DriverLicense class considered as an entity, cause it’s annotated as @Entity and it’s mapped into DriverLicense table.
  • The DriverLicense inherit a licenseId attribute from the License MappedSuperclass.
  • The DriverLicense can override any inherited attributes or associations using @AttributeOverride and @AssociationOverride.
  • The DriverLicense associate the Employee with an OneToMany unidirectional association.
  • The DriverLicense table should hold all attributes that are defined by the entity and its MappedSuperclass (licenseId).

Persistence Configuration

The persistence.xml should mention the mapped sueprclass and its sub classes. If you’ve omit the License mapped superclass you are almost getting a compiler error tells you (The License is managed but is not listed in the persistence.xml file). Even if the License will not be part of any EntityManager’s operation, but it should be declared there for making the mapping sharing possible.

[code lang=”xml”]

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="EclipseLink-JPA-Installation" transaction-type="RESOURCE_LOCAL">
<!– The entities mentioned here covers previous examples –>
<class>net.javabeat.eclipselink.data.Employee</class>
<class>net.javabeat.eclipselink.data.Developer</class>
<class>net.javabeat.eclipselink.data.Address</class>
<class>net.javabeat.eclipselink.data.Phone</class>
<class>net.javabeat.eclipselink.data.Project</class>
<class>net.javabeat.eclipselink.data.GlobalProject</class>
<class>net.javabeat.eclipselink.data.LocalProject</class>
<!– License & DriverLicense are required classes for this example –>
<class>net.javabeat.eclipselink.data.License</class>
<class>net.javabeat.eclipselink.data.DriverLicense</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/JavaBeat"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.password" value="root"/>
<property name="eclipselink.logging.level" value="FINEST"/>
</properties>
</persistence-unit>
</persistence>

[/code]

Executable Application

Look at the Java code that runs a JPA persistence for persisting a DriverLicense associated with an Employee.

[code lang=”java”]
package net.javabeat.eclipselink;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import net.javabeat.eclipselink.data.Address;
import net.javabeat.eclipselink.data.Developer;
import net.javabeat.eclipselink.data.DriverLicense;
import net.javabeat.eclipselink.data.Employee;
import net.javabeat.eclipselink.data.GlobalProject;
import net.javabeat.eclipselink.data.LocalProject;
import net.javabeat.eclipselink.data.Phone;
import net.javabeat.eclipselink.data.Project;

public class JPAImpl {
static EntityManagerFactory factory = null;
static EntityManager em = null;
static {
factory = Persistence.createEntityManagerFactory("EclipseLink-JPA-Installation");
em = factory.createEntityManager();
}
public static void main(String [] args){
// Begin a Transaction
em.getTransaction().begin();
// Create Employee
createEmployee();
// Commit
em.getTransaction().commit();

// Begin another Transaction
em.getTransaction().begin();
// Find the Employee
Employee employee = em.find(Employee.class, 2);
// Create a Driver License
createDriverLicense(employee);
// Commit
em.getTransaction().commit();

}

public static void createDriverLicense(Employee employee){
DriverLicense license = new DriverLicense(); // Create a driver license
license.setLicenseId(1);// Set license id
license.setDriverLicenseName("All Vehicles License"); // Set License Name
license.setDriverLicenseIssueDate(new Date()); // Anonymous date
license.setDriverLicenseExpiryDate(new Date()); // Anonymous date
license.setEmployee(employee);
em.persist(license);
}

public static void createEmployee(){
// Create an address entity
Address address = new Address();
address.setAddressId(2);
address.setAddressCountry("United Kingdom");
address.setAddressCity("London");
// Create an employee entity
Employee employee = new Employee();
employee.setEmployeeId(2);
employee.setEmployeeName("John Smith");
// Associate the address with the employee
employee.setAddress(address);
// Create a Phone entity
Phone firstPhone = new Phone();
firstPhone.setPhoneId(3);
firstPhone.setPhoneNumber("+221 4050 615");
firstPhone.setEmployee(employee);
// Create a new phone entity
Phone secondPhone = new Phone();
secondPhone.setPhoneId(4);
secondPhone.setPhoneNumber("+221 4050 619");
// Use the old employee entity
secondPhone.setEmployee(employee);
// Create a list of phone
List<Phone> phones = new ArrayList<Phone>();
phones.add(firstPhone);
phones.add(secondPhone);

// Create a Project entity
Project project = new Project();
project.setProjectId(2);
project.setProjectName("Nasa Project");

// Create a list of projects
List<Project> projects = new ArrayList<Project>();

// add the project into the list
projects.add(project);

// Set the project into employee
employee.setProjects(projects);
// Set the phones into your employee
employee.setPhones(phones);

// Persist the employee

em.persist(employee);
}
}
[/code]

Summary

This tutorial introduced a new annotation for sharing a mapping information rather using @Inheritance. @MappedSuperclass used to annotate a class whose instance won’t be persisted or participate in any persisting operation, while its sub classes will do. In the previous examples we’ve seen a License class that annotated with an @MappedSuperclass, even if it has no abstract non-access modifier, it’s will not considered in a any future persisting operation. However, all sub classes that inherit from the License and doesn’t marked as @MappedSuperclass will participate in the persisting operations such DriverLicense. Remember that – The main goal of @MappedSuperclass is to share the mapping information with the sub classes.

Filed Under: Java EE Tagged With: Annotation, EclipseLink, JPA

Follow Us

  • Facebook
  • Pinterest

As a participant in the Amazon Services LLC Associates Program, this site may earn from qualifying purchases. We may also earn commissions on purchases from other retail websites.

JavaBeat

FEATURED TUTORIALS

Answered: Using Java to Convert Int to String

What is new in Java 6.0 Collections API?

The Java 6.0 Compiler API

Copyright © by JavaBeat · All rights reserved