Extrait de livre de conseils d’Hibernate: comment mapper une hiérarchie d’héritage en une seule table

1. Introduction

L’héritage est l’un des concepts clés de Java. Il n’est donc pas surprenant que la plupart des modèles de domaine l’utilisent. Malheureusement, ce concept n’existe pas dans les bases de données relationnelles et vous devez trouver un moyen de mapper la hiérarchie de l’héritage à un modèle de table relationnel.

JPA et Hibernate prennent en charge différentes stratégies, qui mappent la hiérarchie d’héritage à divers modèles de table. Jetons un coup d’œil au chapitre de mon nouveau livre Hibernate Tips - Plus de 70 solutions aux problèmes courants de Hibernate dans lequel j’explique la stratégie SingleTable . Il mappe toutes les classes de la hiérarchie d’héritage à la même table de base de données.

J’explique les autres stratégies de cartographie d’héritage d’Hibernate dans mon livre Hibernate Tips . C’est un livre de recettes avec plus de 70 recettes prêtes à l’emploi pour des sujets tels que les mappages de base et avancés, la journalisation, la prise en charge de Java 8, la mise en cache et les requêtes définies de manière statique et dynamique. Vous pouvez get le cette semaine sur Amazon à un prix de lancement spécial de seulement 2,99 $.


2. Hibernate Tips - Comment mapper une hiérarchie d’héritage à une table

2.1. Problème

Ma base de données contient une table, que je veux mapper à une hiérarchie d’héritage d’entités. Comment définir un tel mapping?

2.2. Solution

JPA et Hibernate prennent en charge différentes stratégies d’héritage qui vous permettent de mapper les entités sur différentes structures de table. La stratégie SingleTable est l’une d’entre elles et mappe une hiérarchie d’héritage d’entités à une seule table de base de données.

Jetons un coup d’œil au modèle d’entité avant d’expliquer les détails de la stratégie SingleTable . Authors peut écrire différents types de Publications , comme Books et BlogPosts . La classe Publication est la super classe des classes Book et BlogPost .

La stratégie SingleTable mappe les trois entités de la hiérarchie d’héritage à la table publication .

Si vous souhaitez utiliser cette stratégie d’héritage, vous devez annoter la superclasse avec une annotation @ Inheritance et fournir le InheritanceType.SINGLE TABLE comme valeur de l’attribut strategy__.

Vous pouvez également annoter la superclasse avec une annotation @ DiscriminatorColumn pour définir le nom de la valeur de discriminateur. Hibernate utilise cette valeur pour déterminer l’entité à laquelle il doit mapper un enregistrement de base de données. Si vous ne définissez pas de colonne discriminante, comme dans l’extrait de code suivant, Hibernate et toutes les autres implémentations JPA utilisent la colonne DTYPE .

@Entity
@Inheritance(strategy = InheritanceType.SINGLE__TABLE)
public abstract class Publication {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", updatable = false, nullable = false)
    private Long id;

    @Version
    private int version;

    private String title;

    private LocalDate publishingDate;

    @ManyToMany
    @JoinTable(
      name="PublicationAuthor",
      joinColumns={@JoinColumn(name="publicationId", referencedColumnName="id")},
      inverseJoinColumns={@JoinColumn(name="authorId", referencedColumnName="id")})
    private Set<Author> authors = new HashSet<Author>();

    ...
}

Les sous-classes doivent étendre la super-classe et vous devez les annoter avec une annotation @ Entity .

La spécification JPA recommande également de l’annoter avec une annotation @ DiscriminatorValue pour définir la valeur de discriminateur pour cette classe d’entité. Si vous ne fournissez pas cette annotation, votre implémentation JPA génère une valeur discriminante.

Mais la spécification JPA ne définit pas comment générer la valeur de discriminateur et votre application peut ne pas être portable pour les autres implémentations JPA. Hibernate utilise le nom d’entité simple comme discriminateur.

@Entity
@DiscriminatorValue("Book")
public class Book extends Publication {

    private int numPages;

    ...
}

La stratégie SingleTable ne nécessite pas que Hibernate génère des requêtes complexes si vous souhaitez sélectionner une entité spécifique, exécuter une requête polymorphe ou traverser une association polymorphe.

Author a = em.find(Author.class, 1L);
List<Publication> publications = a.getPublications();

Toutes les entités sont stockées dans la même table et Hibernate peut les sélectionner à partir de là sans clause JOIN supplémentaire.

15:41:28,379 DEBUG[org.hibernate.SQL]-
    select
        author0__.id as id1__0__0__,
        author0__.firstName as firstNam2__0__0__,
        author0__.lastName as lastName3__0__0__,
        author0__.version as version4__0__0__
    from
        Author author0__
    where
        author0__.id=?
15:41:28,384 DEBUG[org.hibernate.SQL]-
    select
        publicatio0__.authorId as authorId2__2__0__,
        publicatio0__.publicationId as publicat1__2__0__,
        publicatio1__.id as id2__1__1__,
        publicatio1__.publishingDate as publishi3__1__1__,
        publicatio1__.title as title4__1__1__,
        publicatio1__.version as version5__1__1__,
        publicatio1__.numPages as numPages6__1__1__,
        publicatio1__.url as url7__1__1__,
        publicatio1__.DTYPE as DTYPE1__1__1__
    from
        PublicationAuthor publicatio0__
    inner join
        Publication publicatio1__
            on publicatio0__.publicationId=publicatio1__.id
    where
        publicatio0__.authorId=?

2.3. Code source

Vous pouvez trouver un lien de téléchargement pour un projet avec des scénarios de test exécutables pour ce conseil Hibernate dans la page book .

2.4. Apprendre encore plus

Vous pouvez également mapper les entités de la hiérarchie d’héritage sur plusieurs tables de base de données. Je vous montre comment faire cela dans le chapitre "Comment mapper une hiérarchie d’héritage à plusieurs tables".

3. Résumé

Comme vous l’avez vu dans ce conseil Hibernate, JPA et Hibernate offrent une option simple pour mapper une hiérarchie d’héritage à une table de base de données unique.

Vous devez simplement annoter la super-classe avec @ Inheritance (strategy = InheritanceType.SINGLE TABLE) et annoter les sous-classes avec @ DiscriminatorValue («Book») __.