11
votes

JPA @onetoOne jette une erreur lorsqu'il est mappé sur une abstraite @enttity avec des sous-classes

J'ai un problème lorsqu'une entité est mappée sur une autre entité qui a une mise en œuvre directe sur ses sous-classes. Voir l'exemple de mappage ci-dessous: XXX PRE>

MAINTENANT, c'est ce que j'ai sur ma table de base de données: p>

emplacement-table: id = 1, personne_id = 1 Personne-table: ID = 1, personne_type = "m" p>

Lorsque je récupère l'emplacement à l'aide de l'entité gestionnaire, Hibernate jette une exception disant que je ne peux pas instancier une classe abstraite ou une interface. P>

javax.persistence.PersistenceException: org.hibernate.InstantiationException: Cannot instantiate abstract class or interface: Person
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:630)
at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:195)
at ......
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98)
at org.unitils.UnitilsJUnit4TestClassRunner$TestListenerInvokingMethodRoadie.runTestMethod(UnitilsJUnit4TestClassRunner.java:174)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
at org.unitils.UnitilsJUnit4TestClassRunner$TestListenerInvokingMethodRoadie.runBeforesThenTestThenAfters(UnitilsJUnit4TestClassRunner.java:156)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
at org.unitils.UnitilsJUnit4TestClassRunner.invokeTestMethod(UnitilsJUnit4TestClassRunner.java:95)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.unitils.UnitilsJUnit4TestClassRunner.access$000(UnitilsJUnit4TestClassRunner.java:44)
at org.unitils.UnitilsJUnit4TestClassRunner$1.run(UnitilsJUnit4TestClassRunner.java:62)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.unitils.UnitilsJUnit4TestClassRunner.run(UnitilsJUnit4TestClassRunner.java:68)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)


6 commentaires

Quel est le type de données de votre colonne discriminator dans la DB?


Pouvez-vous montrer la structure complète?


Avez-vous essayé @mapsuperclass au lieu de @entity sur personne?


Cet article sur le forum peut également aider aussi bien que cela soit à partir de 2007. Essentiellement, Il suggère d'ajouter une valeur discriminatrice factice à la classe de base abstraite.


@Martin - Je veux stocker ces entités sur la même table et je suppose @MePapsuPlassclass ne peut pas être cartographié sur une relation d'entité. @Un par un


J'ai essayé votre exemple avec Eclipselink tel quel et je ne reçois aucune exception. Peut-être que c'est un problème avec la façon dont vous avez initialement initialisé les données? Y a-t-il une entrée sans valeur dans la colonne discriminator de la table de la personne?


7 Réponses :


0
votes

Comme indiqué dans mon commentaire ci-dessus, j'ai essayé la même chose avec Eclipselink et ça fonctionne.

Après avoir créé des données de test, j'ai effacé la valeur discriminatrice d'une entrée de personne dans la DB et je reçois maintenant une exception similaire lors de la tentative de chargement de l'emplacement associé. Eclipselink's Message est un peu plus descriptif: xxx

Le mappage semble fonctionner, de sorte que si les données ne sont "corrompues" (que ce n'est pas dans votre cas comme vous l'avez dit. ), c'est probablement un bug ou au moins un comportement différent dans l'hibernate.


0 commentaires

2
votes

de Tutoriel Java EE 6 - Intérité de l'entité :

n'importe quelle cartographie ou relation Annotations dans les superclasses de non-entité sont ignorés.

Vous semblez donc être correct que vous devez annoter la classe personne avec @entity pour l'associer à un emplacement via @Enetoone .

du @mapsuperclass Javadoc

une classe désignée avec le L'annotation mapperclass peut être mappé de la même manière qu'une entité Sauf que les mappages s'appliqueront seulement à ses sous-classes depuis aucune table existe pour la superclasse mappée lui-même.

Vous ne pouviez donc pas utiliser @mapapsuperclass sur personne, puis mappez-le avec le @onetoone , car il n'y aurait pas de table de personne.

semble que les annotations JPA que vous utilisez sont correctes. Avez-vous essayé la suggestion de @Martin Klinke d'une valeur nominale discriminator pour la classe la classe


1 commentaires

Cela a résolu mon problème, j'ai oublié @enttity sur la sous-classe et j'ai reçu la même erreur jusqu'à ce que je l'ai ajouté à la classe enfant.



1
votes

J'ai trouvé ce genre de problème de problème lui-même si les classes d'entité implémentent sérialisable .


0 commentaires

0
votes

Je rencontre un code similaire à cela, avec quelques différences. Premièrement, je place la classe abstraite derrière une interface. Deuxièmement, je définis explicitement la cépitée de la cartographie @Enetoone. Un exemple serait: xxx

ici j'ai renommé classe abstraite de votre personne à "abstractperson" pour la clarté. A pris un peu de jeu pour le faire fonctionner, j'espère que cela résout votre problème.


0 commentaires

0
votes

Essayez d'ajouter @Forcediscriminator à la personne. Sans cette annotation Hibernate tente souvent d'instancier la classe mère, en ignorant le discriminateur qui devrait lui dire quelle classe enfant à instanecter.


0 commentaires

1
votes

J'ai eu un message d'erreur similaire avec la structure suivante: xxx

avec une instance d'enfant concrete xxx

et une classe qui a Un champ référençant la classe abstraite: xxx

Les modifications suivantes résolvent le problème pour moi:

  1. modifier le @onetoone à @onetoone (cascade = cascadetype.all)
  2. changer le @generatedValue à @generatedValue (stratégie = générationtype.table)

    MISE À JOUR: J'ai également trouvé que je n'établissais pas l'objet Realperson avant de le relier à la somlasse. Alors maintenant, j'ai d'abord enregistrer l'instance en premier, l'attribut cascade n'est plus requis


0 commentaires

4
votes

Cela m'a fait le tour pour moi, en utilisant Hibernate comme fournisseur de persistance.

@OneToOne(cascade = {CascadeType.PERSIST,CascadeType.MERGE}) 


0 commentaires