-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 
Author Message
 Post subject: Différents mappings d'une relation 1..*
PostPosted: Sat Dec 03, 2005 8:04 pm 
Newbie

Joined: Sat Dec 03, 2005 7:31 pm
Posts: 12
Location: Toulouse, France
Bonjour,

J'ai dans mon application plusieurs relations de type 1..*, chose courante.
Notons les classes : [A] 1______________* [B]

Ma base de données contient donc une table A(idA), et une table B(idB, idA_Pere), avec une contrainte not null sur IdA_Pere.

Si j'ai bien compris la doc d'Hibernate 3 (en anglais), il semblerait qu'il soit conseillé de mapper le père (A) dans l'entité B. Ce qui donne dans B.hbm :
Code:
<many-to-one name="papaA" column="idA_Pere" unique="true" not-null="true">


Du coup, si je veux pouvoir récupérer tous mes fils depuis A, il me faut faire un mapping bidirectionnel. Donc dans A.hbm :
Code:
<set name="filsB" table="B">
    <key column="idA_Pere">
    <one-to-many class="B">
</set>



Ma problématique vient surtout de l'ajout d'un nouveau fils (B) rattaché à son père (A), puisque la clé étrangère est not null.

Deux approches sont envisageables (on suppose que A existe déjà) :

1. Je crée mon instance de B à laquelle j'attache mon instance père de A, puis je fais un save de cette instance.

=> Cette approche-ci fonctionne, mais n'est pas très élégante pour la mise à jour de la liste des fils dans A (il faut faire des load systématiques).

2. Je crée mon instance de B sans y rattacher de père (on ne le mappe pas). J'ajoute cette instance dans la collection des fils de A, puis je fais un save de A.

=> Cette approche semble ne pas fonctionner. En effet, je récupère une exception pas très claire :
Quote:
org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1


Il semblerait qu'Hibernate ne soit pas capable de créer l'instance de B à partir du fait qu'elle existe dans la collection des fils de A. Ou peut-être que mon mapping n'est pas correct.

J'ai longuement lu la documentation, les forums, etc. La documentation semble nous pousser à utiliser l'approche n°1. Pourtant, je pense que l'approche 2 est beaucoup plus simple sur le plan sémantique et algorithmique.


Je conclurai donc ce post sur 2 questions simples :
1) Hibernate ne serait-il donc pas capable de traiter l'approche numéro 2 ?
2) Quelle solution de mapping est donc la plus adaptée à ce genre de situation ?

Merci d'avance pour votre aide.

Cordialement,
Frédéric MONJO,
Chef du projet IceScrum.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 05, 2005 4:33 am 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
http://www.hibernate.org/hib_docs/v3/re ... irectional

_________________
Anthony,
Get value thanks to your skills: http://www.redhat.com/certification


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 05, 2005 10:35 am 
Newbie

Joined: Sat Dec 03, 2005 7:31 pm
Posts: 12
Location: Toulouse, France
Bonjour,

Merci beaucoup de m'avoir répondu, mais j'avais déjà lu et relu effectivement la documentation (presque au complet). Je vais donc utiliser une association bidirectionnelle, faute de mieux.

Je réitère quand même ma première question : hibernate n'est-il pas capable de créer un instance de B dès son ajout dans la collection du père A ?

Merci encore.

_________________
IceScrum project : Scrum projects management tool


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 05, 2005 10:54 am 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
cascade= persist,save,save-update,merge

_________________
Anthony,
Get value thanks to your skills: http://www.redhat.com/certification


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 05, 2005 12:30 pm 
Newbie

Joined: Sat Dec 03, 2005 7:31 pm
Posts: 12
Location: Toulouse, France
Merci de cette réponse rapide.

En fait j'ai mieux ciblé le problème, et je vais être plus précis dans son exposé. Voici ma démarche :

1) Mon instance père de A existe déjà en base et est chargée en mémoire.
2) Je crée une nouvelle instance de B, et je l'ajoute à la collection des fils de A
3) Je sauvegarde A

En regardant de plus près les requêtes exécutées par Hibernate, il s'avère qu'il fait un UPDATE sur le fils B, et non un INSERT INTO.

De ce fait, je reçois l'exception suivante :
Code:
Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1


Je pense que le problème vient ici du fait que l'instance père existe déjà. Par conséquent la cascade répercute l'update du père, et non la création du fils.

J'ai trouvé deux solutions possibles :

1) J'affecte la référence du père A dans le fils B, puis je fais un save(B). Mais dans ce cas, la collection d'instances de B dans le père n'est plus à jour du point de vue Objet.

2) Dans la méthode du père A pour ajouter un fils B, je commence par mettre à jour la référence du père dans le fils avec this, puis j'ajoute le fils à la collection. Dans ce cas save(A) fonctionne, puis qu'il lance

N'y a-t-il pas une solution de niveau mapping pour qu'Hibernate fasse cela automatiquement ?

_________________
IceScrum project : Scrum projects management tool


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 07, 2005 5:15 am 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
mapping de B?

de manière générale, tu gagneras du temps et en feras gagner aux personnes qui pourraient t'aider, si tu détailles davantage ton problème... qu'en penses tu?

_________________
Anthony,
Get value thanks to your skills: http://www.redhat.com/certification


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 07, 2005 6:24 am 
Newbie

Joined: Sat Dec 03, 2005 7:31 pm
Posts: 12
Location: Toulouse, France
Excusez-moi, mais je pense que vous n'avez pas bien lu mon dernier post. Je ne vois pas comment je pourrais mieux l'expliquer. Peut-être ne l'avez-vous pas bien compris, dans ce cas demandez-moi des détails complémentaires sur un point précis.

Je vous rappelle la structure de ce post :

1: Démarche qui a posé le problème
2: Exception levée
3: Tentative d'explication de cette exception
4: Solutions essayées (2)
5: Y a-t-il une meilleure solution ne passant que par du mapping ?

Encore un fois, je ne vois pas où je pourrais être plus précis...

Merci.

_________________
IceScrum project : Scrum projects management tool


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 07, 2005 6:30 am 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
a défaut d'infos, notamment sur la stratégie de gestion d'id de l'entité B, ainsi que sur la méthode de la session que tu invoques, je ne peux pas t'aider.

Bon courage.

_________________
Anthony,
Get value thanks to your skills: http://www.redhat.com/certification


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 07, 2005 7:17 am 
Newbie

Joined: Sat Dec 03, 2005 7:31 pm
Posts: 12
Location: Toulouse, France
Ok. Je pensais que balancer 100 lignes de sources devait être contraignant à analyser, et j'ai donc tenté d'expliquer avec un niveau d'abstraction au-dessus du source pour faciliter la lecture.

Mes deux entités ont un attribut id qui est généré en mode "increment".
J'appelle la méthode session.save(A).

Comme je l'ai dit, mon entité A existe déjà au moment où j'appelle cette méthode. Aussi l'instance de B nouvellement créée (et non encore sauvée dans la base) que j'attache dans la collection des fils de A n'est pas insérée (INSERT INTO généré), mais mise à jour (UPDATE). Or la mise à jour sur un identifiant non existant ne retourne rien, et provoque l'exception que j'ai déjà citée.

Je demandais donc si Hibernate ne savait pas traiter ce cas automatiquement, et si je suis donc obligé d'affecter le père dans B avant de faire mon session.save(A).

Maintenant, si cela ne vous paraît toujours pas assez clair, je peux aussi vous donner le source de mes entités et de mes mappings.

_________________
IceScrum project : Scrum projects management tool


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.