Mapped Super Class

This mapping is the annotation approach to map inherited fields. Full source code is provided in the package: de.laliluna.inheritance.mappedsuperclass

images/mapping/inheritance-mapped-superclass.png

This example has the same class hierarchy compared to former examples. This mapping is not a typical inheritance mapping. The parent class itself is not mapped and cannot be used in queries or relations. This approach is useful, if you want to include properties of the parent class in the subclass tables, but do not want to use the parent class directly. It could be abstract as well.

Mouse parent class. 

import javax.persistence.Entity;
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.MappedSuperclass;
...... snip .......
@MappedSuperclass
public class Mouse implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "mouse_seq")
    private Integer id;
    private String name;

The sub classes do not have any inheritance specific annotations.

KitchenMouse sub class. 

@Entity
public class KitchenMouse extends Mouse{

    private String favouriteCheese;
......

LibraryMouse sub class. 

@Entity
public class LibraryMouse extends Mouse{

    private String favouriteBook;
.....

As already mentioned, another class can not have a relation to the parent class Mouse.

House. 

import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
....... snip .....
@Entity
public class House implements Serializable {
   @Id
   @GeneratedValue
   private Integer id;
   private String name;

   @ManyToMany(cascade=CascadeType.ALL)
   @JoinTable(name = "house_kitchenmouse",
   joinColumns = { @JoinColumn(name = "house_id") },
   inverseJoinColumns = {@JoinColumn(name = "kitchenmouse_id") })
   private Set<KitchenMouse> kitchenMice = new HashSet<KitchenMouse>();

   @ManyToMany(cascade=CascadeType.ALL)
   @JoinTable(name = "house_librarymouse",
      joinColumns = { @JoinColumn(name = "mouse_id") },
      inverseJoinColumns = { @JoinColumn(name = "librarymouse_id") })
   private Set<LibraryMouse> libraryMice = new HashSet<LibraryMouse>();

The query behaviour is the same as a normal 1:n mapping. If you do not need to access the parent class, than this is the fastest choice for inheritance mapping. You have to set the GeneratedValue in the parent class. The Generator itself has to be defined in the sub classes. I consider this a funny behaviour of Hibernate. I expected to define both in the parent class.

Samples of use. 

/* create and set relation */
House house = new House("Edwin");
LibraryMouse libraryMouse = new LibraryMouse();
libraryMouse.setName("sensitive");
house.getLibraryMice().add(libraryMouse);
KitchenMouse kitchenMouse = new KitchenMouse();
kitchenMouse.setName("Mouse from Amsterdam");
house.getKitchenMice().add(kitchenMouse);
session.save(kitchenMouse);
session.save(libraryMouse);
session.save(house);

/* select houses having kitchen mice */
List list = session.createQuery(
      "select h from House h where size(h.kitchenMice) > 0").list();

/* select all houses with a kitchenMice having gouda as favourite cheese */
List list = session.createQuery(
      "select h from House h left join h.kitchenMice  k "+
   "where  k.favouriteCheese = :cheese)")
    .setParameter("cheese", "Gauda").list();