web-dev-qa-db-fra.com

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;
    }
}

me donne cette exception:

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

Quelle est la manière la meilleure et la plus pratique pour moi de générer les identifiants? Je ne veux pas changer ma stratégie d'héritage.

86
user14070

Le problème ici est que vous mélangez l'héritage "table par classe" et GenerationType.Auto. Considérez une colonne d'identité dans MsSQL. Il est basé sur des colonnes. Dans une stratégie "table par classe", vous utilisez une table par classe et chacune a un ID.

Essayer:

@GeneratedValue(strategy = GenerationType.TABLE)

208
zoidbeck

Je me demande s'il s'agit d'un problème spécifique au dialecte de la base de données, car en regardant un didacticiel youtube avec PostgreSQL comme base de données sous-jacente, j'ai vu que le créateur de la vidéo exécutait 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

8
skiabox

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, ce qui contiendra la séquence de clés primaires de la table de votre résumé. Modifiez votre mappage 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 à ceci: enter image description here

Lorsque vous avez exécuté votre application, Hibernate insère une ligne où sequence_name sera le nom de l'entité (SuperClass dans cet exemple) et sequence_next_hi_value La valeur sera automatiquement incrémentée et utilisée pour les nouveaux enregistrements de toutes les tables de sous-classes d'implémentation.

2
Gondy

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 par défaut à SEQUENCE pour postgres, mais a échoué dans nos tests locaux (doit par défaut être autre chose pour hsqldb).

Donc, la solution qui a fonctionné pour nous, utilisez explicitement GenerationType.SEQUENCE.

2
Ryan Walls

vous pouvez utiliser @MappedSuperclass pour l'héritage

1
leimbag

Il existe une conformité au standard SQL entre MySQL et PostgreSQL.PostgreSQL Postgres comprend un bon sous-ensemble de SQL92/99 ainsi que certaines fonctionnalités orientées objet de ces sous-ensembles. Postgres est capable de gérer des routines et des règles complexes en tant que requêtes SQL déclaratives, sous-requêtes, vues, prise en charge multi-utilisateurs, transactions, optimisation de requêtes, héritage et tableaux. Ne prend pas en charge la sélection de données dans différentes bases de données.

MySQL MySQL utilise SQL92 comme base. Fonctionne sur d'innombrables plateformes. Mysql peut construire des requêtes qui peuvent joindre des tables de différentes bases de données. Prend en charge les jointures externes gauche et droite en utilisant à la fois ANSI et la syntaxe ODBC. À partir de MySQL 4.1 à partir de cette version, MySQL gérera les sous-requêtes. Vues prises en charge à partir de la version 5.

Pour une description détaillée, veuillez visiter. http://www-css.fnal.gov/dsg/external/freeware/pgsql-vs-mysql.html

0
Coderac