2017-09-11 8 views
0

Je ne parviens pas à utiliser @OneToOne lorsque la clé primaire composite est la même dans les deux classes:"org.hibernate.TypeMismatchException: ID fourni du type incorrect" lors de l'utilisation de @OneToOne pour une relation bidirectionnelle

@Entity 
public class One implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @EmbeddedId 
    private OnePK onePK; 
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "one") 
    private Two two; 
    //... constructors, getters and setters 
} 

@Entity 
public class Two implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @EmbeddedId 
    private TwoPK twoPK; 
    @JoinColumns({ 
     @JoinColumn(name = "P_ID", referencedColumnName = "P_ID", insertable = false, updatable = false), 
     @JoinColumn(name = "L_ID", referencedColumnName = "L_ID", insertable = false, updatable = false)}) 
    @OneToOne(optional = false) 
    private One one; 
    //... constructors, getters and setters 
} 

@Embeddable 
public class OnePK implements Serializable { 
    @Basic(optional = false) 
    @Column(name = "P_ID") 
    private BigInteger dId; 
    @Basic(optional = false) 
    @Column(name = "L_ID") 
    private BigInteger lId; 
    //... constructors, getters and setters 
} 

@Embeddable 
public class TwoPK implements Serializable { 
    @Basic(optional = false) 
    @Column(name = "P_ID") 
    private BigInteger dId; 
    @Basic(optional = false) 
    @Column(name = "L_ID") 
    private BigInteger lId; 
    //... constructors, getters and setters 
} 

Lorsque j'utilise le code source ci-dessus est, je reçois:

12:56:04,021 WARNING [org.apache.cxf.phase.PhaseInterceptorChain] (default task-83) Application { http://services.webservices .*****.******.com/}ObjectManagerService#{ http://services.webservices .*****.******.com/}getAllObjects has thrown exception, unwinding now: org.apache.cxf.interceptor.Fault: java.lang.IllegalArgumentException: org.hibernate.TypeMismatchException: Provided id of the wrong type for class com.******.*****..********.Two. Expected: class com.******.*****..********.TwoPK, got class com.******.*****.**.********.OnePK at org.apache.cxf.service.invoker.AbstractInvoker.createFault(AbstractInvoker.java:162) at org.apache.cxf.jaxws.AbstractJAXWSMethodInvoker.createFault(AbstractJAXWSMethodInvoker.java:267) at

Lorsque j'utilise la même classe (OnePK) comme la clé primaire des deux classes (un et deux), je reçois:

11:44:35,735 WARNING [org.apache.cxf.phase.PhaseInterceptorChain] (default task-83) Interceptor for { http://services.webservices .*****.******.com/}ObjectManagerService#{ http://services.webservices .*****.******.com/}getAllObjects has thrown exception, unwinding now: org.apache.cxf.interceptor.Fault: Marshalling Error: A cycle is detected in the object graph. This will cause infinitely deep XML : One[ onePK=OnePK[ dId=3151, lId=426 ] ] -> Two[ twoPK=OnePK[ dId=3151, lId=426 ] ] -> One[ onePK=OnePK[ dId=3151, lId=426 ] ] at org.apache.cxf.jaxb.JAXBEncoderDecoder.marshall(JAXBEncoderDecoder.java:266) at org.apache.cxf.jaxb.io.DataWriterImpl.write(DataWriterImpl.java:238) at org.apache.cxf.interceptor.AbstractOutDatabindingInterceptor.writeParts(AbstractOutDatabindingInterceptor.java:118) at

L'utilisation de @PrimaryKeyJoinColumns n'a pas aidé, j'ai utilisé this answer et this tutorial, j'ai eu les mêmes messages d'erreur. L'utilisation de @MapsId n'a pas aidé, j'ai "org.hibernate.exception.GenericJDBCException: impossible de préparer une instruction". Peut-être que la cause première est this unfixed bug of Hibernate. La seule solution de contournement que j'ai trouvée consiste à supprimer la première occurrence de @OneToOne et le champ "two" dans la classe "One" mais l'instance de Two contenue dans une instance de One n'est plus supprimée lorsque je supprime cette instance de One, c'est pourquoi j'ai utilisé CascadeType.ALL.

Ce code source JPA est généré automatiquement par Netbeans 8. Je suis un peu à court d'options. Y a-t-il un moyen de le faire fonctionner correctement? Est-ce vraiment une limitation d'Hibernate? Existe-t-il une autre implémentation de JPA traitant correctement ce cas?

Répondre

0

Au début, j'ai augmenté le délai de connexion TTL dans Oracle UCP en appelant this method afin de se débarrasser du GenericJDBCException. Certaines demandes prenaient trop de temps à s'exécuter alors que le temps nécessaire pour garder une connexion en cours d'utilisation était trop faible.

Deuxièmement, j'ai utilisé la même classe nommée OnePK comme clé primaire des classes un et deux.

Troisièmement, j'ai ajouté @XmlTransient dans la classe Two avant la méthode getOne() afin de fixer le cycle dans la sérialisation XML.Quatrièmement, j'ai modifié mes gestionnaires pour qu'ils appellent Two.setOne (final One one) afin d'exposer des objets complets (instances de Two) pour le code source appelant la couche de persistance sans utiliser les services Web. Enfin, j'ai corrigé quelques cas similaires mais avec des clés primaires simples composées d'une seule colonne en utilisant @MapsId.

0

Je pense que le problème vient de l'attribut name utilisé dans votre cartographie @JoinColumn, dans votre classe Two, où la valeur utilisée pour name est le même que referencedColumnName.

En fait Two classe a déjà P_ID et L_ID attributs intégrés de sa TwoPk classe, donc quand vous utiliserez les mêmes noms name = "P_ID" et name = "L_ID", vous ne pouvez pas la carte à la fois classe parce que ces attributs sont déjà dans ce Entity vous devriez donc spécifier des noms différents:

@JoinColumns({ 
    @JoinColumn(name = "OneP_ID", referencedColumnName = "P_ID", insertable = false, updatable = false), 
    @JoinColumn(name = "OneL_ID", referencedColumnName = "L_ID", insertable = false, updatable = false)}) 
@OneToOne(optional = false) 
private One one; 

note:

Si vous utilisez deux différents cours pour PKs , Pourquoi vous utilisez les mêmes noms d'attributs dans les deux classes, il serait mieux si vous les identifiaient avec différents noms dans OnePk et TwoPk comme:

Respectivement oneDId et oneLId dans votre classe OnePk et twoDId et twoLId dans votre classe TwoPk, cela rendra les choses meilleures et plus faciles à lire, à identifier et à cartographier.

+0

Ok, je vais essayer. Merci. – gouessej

+0

En fait, je ne peux pas changer ces noms dans le code source Java car je ne suis pas autorisé à les changer dans les tables SQL, ils doivent correspondre: s – gouessej

+0

Bien, vous pouvez leur donner différents noms en Java et utiliser le même nom l'annotation '@ Column', mais de toute façon ce n'est pas le point ici, a changé la configuration' @ JoinColumns'? –