105 votes

Impossible d'utiliser la génération de clés de colonne d'identité avec <union-subclass> ( TABLE_PER_CLASS )

com.something.SuperClass :

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class SuperClass implements Serializable {
    private static final long serialVersionUID = -695503064509648117L;

    long confirmationCode;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO) // Causes exception!!!
    public long getConfirmationCode() {
        return confirmationCode;
    }

    public void setConfirmationCode(long confirmationCode) {
        this.confirmationCode = confirmationCode;
    }
}

com.something.SubClass :

@Entity
public abstract class Subclass extends SuperClass {
    private static final long serialVersionUID = 8623159397061057722L;

    String name;

    @Column(nullable = false)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Ça me donne cette exception :

Caused by: org.hibernate.MappingException: Cannot use identity column key
generation with <union-subclass> mapping for: com.something.SuperClass

Quel est le moyen le plus efficace et le plus pratique pour moi de générer les identifiants ? Je ne veux pas changer ma stratégie d'héritage.

243voto

zoidbeck Points 2261

Le problème ici est que vous mélangez l'héritage "table-par-classe" et GenerationType.Auto . Considérons une colonne d'identité dans MsSQL. Elle est basée sur une colonne. Dans une stratégie "table par classe", vous utilisez une table par classe et chacune d'entre elles possède une identité.

Essayez :

@GeneratedValue(strategy = GenerationType.TABLE)

8voto

skiabox Points 843

Je me demande si c'est un problème spécifique à un dialecte de base de données, car en regardant un tutoriel youtube avec PostgreSQL comme base de données sous-jacente, j'ai vu que le créateur de la vidéo a exécuté avec succès une application avec la @GeneratedValue par défaut. Dans mon cas (la base de données sous-jacente est MySQL) j'ai dû modifier la stratégie @GeneratedValue en GenerationType.TABLE exactement comme le propose zoidbeck.

Voici la vidéo : https://www.youtube.com/watch?v=qIdM4KQOtH8

7voto

Gondy Points 83

D'accord avec la réponse de zoidbeck. Vous devez changer de stratégie pour :

@GeneratedValue(strategy = GenerationType.TABLE)

Mais ce n'est pas tout, vous devez créer une nouvelle table, qui contiendra la séquence de clés primaires de la table de votre résumé. Modifiez votre mapping en

@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "ConfirmationCodeGenerator")
@TableGenerator(table = "SEQUENCES", name = "ConfirmationCodeGenerator")
public long getConfirmationCode() {
   return confirmationCode;
}

Et une nouvelle table dans la base de données devrait ressembler à ce qui suit : enter image description here

Lorsque vous exécutez votre application, Hibernate va insérer une ligne où sequence_name sera le nom de l'entité ( SuperClass dans cet exemple) et sequence_next_hi_value sera automatiquement incrémentée et utilisée pour les nouveaux enregistrements de toutes les tables des sous-classes mises en œuvre.

2voto

Ryan Points 636

Dans notre cas, nous utilisons une base de données PostreSQL pour le développement et la production et une base de données hsqldb en mémoire pour les tests. Nous utilisons une séquence dans les deux cas pour générer un identifiant. Apparemment GenerationType.AUTO La valeur par défaut est SEQUENCE pour postgres, mais a échoué dans nos tests locaux (doit avoir une autre valeur par défaut pour hsqldb).

Donc la solution qui a fonctionné pour nous, c'est d'utiliser explicitement GenerationType.SEQUENCE .

2voto

leimbag Points 189

Vous pouvez utiliser @MappedSuperclass pour l'héritage

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X