IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JPA Java Discussion :

JPA héritage complexe ?


Sujet :

JPA Java

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 20
    Par défaut JPA héritage complexe ?
    Bonjour,

    je cherche à faire qq qui me semble pourtant pas compliquer mais qui s'avère apparemment impossible en JPA.

    voila le contexte :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    @MappedSuperClass
    abstract class Mere {
       @OneToMany
       @MapKey(name="key")
       private Map<String, ClassA> classAs = new HashMap<String, ClassA>();
    }
     
    @Entity
    class Fille1 {
    }
     
    @Entity
    class Fille2 {
    }
     
    @Entity
    @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
    @DiscriminatorColumn(discriminatorType = DiscriminatorType.STRING)
    abstract class ClassA {
       @ManyToOne
       @JoinColumn(name = "Fille1_ID", referencedColumnName = "ID")
       private Fille1 fille1;
     
       @ManyToOne
       @JoinColumn(name = "Fille2_ID", referencedColumnName = "ID")
       private Fille2 fille2;
    }
    Mes tables sont Fille1(PK=ID), Fille2(PK=ID) et classa(PK=ID, FK_FILLE1, FK_FILLE2)

    Pour une raison inconnue ou un mapping erroné, si je persite une instance de Fille1 avec classAs empty, j'ai une InstanciationException sur une tentative d'instanciation de ClassA

    Pour commencer la discussion peut-on me valider le mapping ? Ensuite si y'a une solution je suis prenneur.

    D'avance merci

  2. #2
    Membre Expert
    Avatar de Patriarch24
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2003
    Messages
    1 047
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 047
    Par défaut
    Ton architecture n'est pas très claire, tu as des dépendances cycliques franchement tordues. Mais bon passons.
    Peux-tu nous donner la trace de l'exception ?

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 20
    Par défaut
    Citation Envoyé par Patriarch24 Voir le message
    Ton architecture n'est pas très claire, tu as des dépendances cycliques franchement tordues. Mais bon passons.
    Peux-tu nous donner la trace de l'exception ?
    L'architecture est pourtant tout ce qu'on peut faire de plus basique en matière d'héritage et d'association et n'a rien de tordu... la classe Mère possède une association bi-directionnelle 1..* sur la classe ClassA. Et c'est tout.
    Seulement, la classe mère étant annotée @MappedSuperClass, on ne peut pas mapper Mere directement dans ClassA comme @ManyToOne private Mere mere; puisque Mere ne fait référence à aucune entity. Sinon il n'y aurait pas de problème D'où mon association ClassA *..1 avec Fille1 et Fille2.

    Et la stack trace est :
    javax.persistence.RollbackException: Exception [EclipseLink-34] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.DescriptorException
    Exception Description: This class does not define a public default constructor, or the constructor raised an exception.
    Internal Exception: java.lang.InstantiationException
    Descriptor: RelationalDescriptor(com.blah.ClassA --> [DatabaseTable(classa)])
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:102)
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:63)
    at com.blah.SessionManager.save(SessionManager.java:...)

  4. #4
    Membre Expert
    Avatar de Patriarch24
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2003
    Messages
    1 047
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 047
    Par défaut
    Peut-être que ceci pourra t'aider.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 20
    Par défaut
    Merci pour le lien mais je l'avais déjà vu et ça ne résoud rien :/

    En revanche j'avance un peu et je pense que le problème ne vient pas de la relation mais plutôt de de la Map

    J'ai abandonné l'idée de factoriser ma Map dans la classe Mere pensant que le pb venait de là et j'ai deplacé le tout dans les classes filles et ça n'a rien donné... Du coup je modifie ma Map en List et là ! Magie ! plus de problème !! Insertion en base OK et tout le tintouin...

    Direction google pour voir si y'a pas un bug avec le mapping de Map...

  6. #6
    Membre Expert
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 968
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 968
    Par défaut
    Citation Envoyé par michok34 Voir le message
    L'architecture est pourtant tout ce qu'on peut faire de plus basique en matière d'héritage et d'association et n'a rien de tordu...
    C'est peut-être basique dans votre esprit mais ce que vous écrivez (ou ce que vous montrez ici) comme code est très tordu.

    Les @OneToMany sur une Map dans une abstract fonctionnent très bien (et même avec la clé étant un UserType…).

    Par contre une @OneToMany sur une Map dans une @MappedSuperclass ne peut pas fonctionner avec tous les types d'InheritanceType - et comme vous ne montrez pas ce que vous faites sur Fille/Mere …
    Un @OneToMany sur une Map a besoin d'une table intermédiaire, et des contraintes FK devront être exprimées sur les champs de cette table intermédiaire et il est évident qu'un même champ ne pourra pas être contraint 2 fois…
    De plus, rien ne garantit que le générateur de DDL va s'apercevoir correctement que la contrainte peut s'exprimer une seule fois, même si Fille1 et Fille2 sont en InheritanceType.SINGLE_TABLE.

    N'oubliez pas que ce vous décrivez en JPA doit être réalisable en SQL.

    NB
    Ne pas oublier @AssociationOverride(s) pour résoudre certains de ces problèmes.

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 20
    Par défaut
    En passant pour ceux que ça pourrait intéresser voici un article sur le mapping un peu complexe dans le même genre et la façon de changer l'archi...

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 20
    Par défaut
    @JeitEmgie
    Ceci est "UMLment" basique mais c'est impossible à persister en l'état.

    Mais si qqun a la solution, je prends !

    Et je ne suis pas entièrement d'accord, un OneToMany sur une Map n'a pas nécessairement besoin d'une table intermédiaire si on utilise l'attribut mappedBy. Dans ce cas, la contrainte de FK se situe dans la table N dans la relation 1-N.

    Mais peut importe, le problème est fixé est si c'est bien cela, ce n'est ni un problème de mappage, ni d'archi tordu ou pas, mais de syntaxe. @MapKey(name = "key") c'est bien sauf que "key" étant un mot reservé SQL... Bref en modifiant par @MapKey(name = "keyword"), problem solved !

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 20
    Par défaut
    Alors "key" n'était pas la source du problème puisque j'ai reproduit par la suite l'erreur mais en tout cas c'en était un quand même.

    Le passage de EclipseLink v2.0.1 en v2.1.2 résous définitivement le problème d'InstantiationException sur une classe abstraite.

    En revanche je lance le débat sur comment mappé la relation ci-dessus

  10. #10
    Membre Expert
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 968
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 968
    Par défaut
    Un test ici mais avec Hibernate et hbm2dll donne :

    création de 1 table pour chaque FILLE (donc 2)
    création d'une table pour CLASSEA
    création d'une table intersection par Fille x ClasseA (donc 2)

    donc 5 tables au total et 6 contraintes FK :
    2 dans chaque table intersection (x2 = 4) chaque fois vers FilleX et ClasseA
    1 dans la ClassA par relation vers Fille… (donc 2)

    Dans ce cas de mapping-ci, Hibernate choisit donc naturellement de créer des tables intersection même si dans le cas simple on peut effectivement s'en passer pour exprimer une relation bi-directionnelle avec une Map.

    Et fyi, après vérification, les raisons qui nous poussent ici à avoir des tables intersection pour nos Map sont encore différentes… nous sommes dans une situation unidirectionnelle et avec des UserType pour la key… - ce qui empêche d'utiliser le MapKey de JPA2, nous avons dû rester avec celui de Hibernate, et nous avons d'ailleurs signaler le problème au team Hibernate : leur MapKey a été marqué obsolète à tort car il offre des fonctionnalités non couvertes par le nouveau MapKey de JPA2.

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 20
    Par défaut
    The Bible

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. génération code et héritage complexe
    Par PadawanDuDelphi dans le forum XSL/XSLT/XPATH
    Réponses: 6
    Dernier message: 20/05/2014, 17h03
  2. Héritage complexe avec Annotations ?
    Par Le Singe dans le forum Hibernate
    Réponses: 1
    Dernier message: 16/10/2012, 20h22
  3. Mapping Objet-Relationel avec JPA :héritage
    Par ahmeddrira dans le forum Frameworks Web
    Réponses: 3
    Dernier message: 06/03/2012, 17h12
  4. Stratégies de mapping d'héritage avec Hibernate / JPA
    Par Ricky81 dans le forum Persistance des données
    Réponses: 10
    Dernier message: 21/06/2010, 11h58
  5. JPA héritage "en cascade"
    Par DrumCode dans le forum JPA
    Réponses: 2
    Dernier message: 14/10/2008, 11h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo