-->
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.  [ 7 posts ] 
Author Message
 Post subject: composite-element pour une relation many-to-many
PostPosted: Wed Aug 03, 2005 4:03 am 
Newbie

Joined: Wed Aug 03, 2005 3:48 am
Posts: 7
Bonjour,

Je suis en train de lire le livre d'Anthony Patricio sur Hibernate3. Il est vraiment bien! Félicitations Anthony.
Je suis en train de jouer les exemples concernant les associations. J'ai une question concernant une relation many-to-many. Si l'on désire ajouter des informations dans la table d'association, on doit utiliser l'élément composite-element qui englobe désormais une relation many-to-one et une nouvelle classe doit utiliser pour représenter cet élément.
J'arrive bien à mettre en place tout cela. J'arrive bien à afficher les éléments de cette association.
Cependant (j'ai activé l'affichage du sql), quand la session est fermée et sans que j'ai modifié les éléments de la liste, je remarque qu'Hibernate fait un delete et un insert sur la table d'association. Est-ce normal et comment modifier ce comportement?
Merci par avance pour vos réponses.
Thierry


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 03, 2005 8:25 am 
Beginner
Beginner

Joined: Wed Jun 08, 2005 10:01 am
Posts: 22
Location: Italy
Hallo,
je te sugère d'envoyer le code d'example.
C'est plus vite pour les autres te comprendre et t'aider.

AuRevoir,
Nicola


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 03, 2005 2:42 pm 
Newbie

Joined: Wed Aug 03, 2005 3:48 am
Posts: 7
Salut Nicola,

Tu as raison. Voici le code exemple...

1°) Schema de la base de données:

create table TEAM (
TEAM_ID bigint generated by default as identity(start with 1),
COACH_ID bigint,
TEAM_NAME varchar(255),
NB_WON integer,
NB_LOST integer,
NB_PLAYED integer,
primary key (TEAM_ID)
);

create table PLAYER (
PLAYER_ID bigint generated by default as identity(start with 1),
PLAYER_NAME varchar(255),
PLAYER_NUMBER integer,
BIRTHDAY timestamp,
HEIGHT float,
WEIGHT float,
TEAM_ID bigint,
primary key (PLAYER_ID)
);

create table COACH_TEAM (
COACH_ID bigint not null,
TEAM_ID bigint not null,
YEAR integer not null,
PRIMARY KEY (COACH_ID,TEAM_ID)
);

create table COACH (
COACH_ID bigint generated by default as identity(start with 1),
COACH_NAME varchar(255),
PRIMARY KEY (COACH_ID)
);

[J'ai enlevé les contraintes d'intégrité]

2°) Mapping Hibernate utilisé pour la classe Team

<hibernate-mapping package="model">

<class name="Team" table="TEAM" lazy="true">
<id name="id" column="TEAM_ID">
<generator class="native"/>
</id>
<property name="name" column="TEAM_NAME"/>
<property name="nbWon" column="NB_WON"/>
<property name="nbLost" column="NB_LOST"/>
<property name="nbPlayed" column="NB_PLAYED"/>
<set name="coachs" table="COACH_TEAM" cascade="save-update" fetch="select">
<key column="TEAM_ID"/>
<many-to-many column="COACH_ID" class="Coach" fetch="select"/-->
<composite-element class="CoachTeam">
<parent name="team"/>
<property column="YEAR" name="year"/>
<many-to-one name="coach" column="COACH_ID" cascade="save-update" />
</composite-element>
</set>
<list name="players" inverse="true" cascade="save-update">
<key column="TEAM_ID" />
<list-index column="PLAYER_NUMBER"/>
<one-to-many class="Player" />
</list>
</class>

</hibernate-mapping>


3°) Code utilisé

Team team=(Team)session.load(Team.class,new Long(3));
System.out.println("team = "+team);

System.out.println("## team.getPlayers()");
List players=team.getPlayers();
for(Iterator i=players.iterator();i.hasNext();) {
Player player=(Player)i.next();
System.out.println("player = "+player);
}
System.out.println("## -----------------");

System.out.println("## team.getCoachs()");
Set coachs=team.getCoachs();
for(Iterator i=coachs.iterator();i.hasNext();) {
CoachTeam coachTeam=(CoachTeam)i.next();
Coach coach=coachTeam.getCoach();
int year=coachTeam.getYear();
System.out.println("year = "+year);
System.out.println("coach = "+coach);
}
System.out.println("## -----------------");


4°) Log d'Hibernate avec sql output activé:

Hibernate: select team0_.TEAM_ID as TEAM1_0_, team0_.TEAM_NAME as TEAM2_0_0_, team0_.NB_WON as NB3_0_0_, team0_.NB_LOST as NB4_0_0_, team0_.NB_PLAYED as NB5_0_0_ from TEAM team0_ where team0_.TEAM_ID=?
team = model.Team@81a197
## team.getPlayers()
Hibernate: select players0_.TEAM_ID as TEAM7_1_, players0_.PLAYER_ID as PLAYER1_1_, players0_.PLAYER_NUMBER as PLAYER3_1_, players0_.PLAYER_ID as PLAYER1_0_, players0_.PLAYER_NAME as PLAYER2_2_0_, players0_.PLAYER_NUMBER as PLAYER3_2_0_, players0_.BIRTHDAY as BIRTHDAY2_0_, players0_.HEIGHT as HEIGHT2_0_, players0_.WEIGHT as WEIGHT2_0_, players0_.TEAM_ID as TEAM7_2_0_ from PLAYER players0_ where players0_.TEAM_ID=?
player = model.Player@16917ee
## -----------------
## team.getCoachs()
Hibernate: select coachs0_.TEAM_ID as TEAM1_0_, coachs0_.YEAR as YEAR0_, coachs0_.COACH_ID as COACH3_0_ from COACH_TEAM coachs0_ where coachs0_.TEAM_ID=?
year = 1999
Hibernate: select coach0_.COACH_ID as COACH1_0_, coach0_.COACH_NAME as COACH2_3_0_ from COACH coach0_ where coach0_.COACH_ID=?
coach = model.Coach@1fe8ce8
## -----------------
Hibernate: delete from COACH_TEAM where TEAM_ID=? and YEAR=? and COACH_ID=?
Hibernate: insert into COACH_TEAM (TEAM_ID, YEAR, COACH_ID) values (?, ?, ?)


Merci par avance pour votre aide.
Thierry


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 04, 2005 4:15 am 
Beginner
Beginner

Joined: Wed Jun 08, 2005 10:01 am
Posts: 22
Location: Italy
Ciao,
l'ai lu ce que tu as envoyé, mais tout me semble correct.
A mon avis, il est mieux que tu envoyes les getters/setter de tes classes ou tout le code de test.

A bientot,
nic


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 11, 2005 3:13 pm 
Newbie

Joined: Wed Aug 03, 2005 3:48 am
Posts: 7
En fait, j'utilise Hibernate3 avec le support de Spring... J'ai exécuté
mon code sans l'aide du template de Spring (HibernateTemplate) et les
deux requêtes (delete, insert) ne sont plus exécutées.
J'ai fouillé un peu plus le code de Spring et j'ai remarqué que le template
fait systématiquement l'appel à flush après le code de traitement.
Si je rajoute l'appel à flush dans le code précédent (sans Spring), les
deux requêtes sont alors exécutées (idem avec une transaction).

Si je ne me trompe pas, flush ou commit permet de forcer la synchronisation entre les objets persistants et la base de données. Par contre, pourquoi, si aucune modification n'est fait sur une relation n-n, il supprime les enregistrements de la table de jointure et les insert.
J'ai remarqué que cela se produisait dans le cas d'une relation n-n où il y a
des propriétés dans la table de jointure et où il est nécessaire d'utiliser
un composite-element:

<set name="coachs" table="COACH_TEAM" fetch="select" cascade="save-update">
<key column="TEAM_ID"/>
<composite-element class="CoachTeam">
<parent name="team"/>
<property column="YEAR" name="year"/>
<many-to-one name="coach" column="COACH_ID" cascade="save-update" />
</composite-element>
</set>

Pour une relation n-n simple, cela ne se produit pas...
Est-ce que ce comportement est normal?
Merci par avance pour votre aide.

Thierry


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 12, 2005 2:15 am 
Expert
Expert

Joined: Thu Sep 04, 2003 8:23 am
Posts: 368
Avec Spring il y a un insert/delete parce que ton code s'insère dans une transaction

Ton delete/insert est lié à la fonctionnalité automatic dirty checking d'hibernate. Automatiquement à chaque flush de la session hibernate regarde s'il y a des objets modifiés. Dans ton cas hibernate considère que ton composite element a été modifié. Cela est souvent le cas lorsque les méthodes equals/hashCode ne sont pas codées correctement ou pas codées du tout dans cette classe.

Vérifie donc tout d'abord le codage de ces deux méthodes

_________________
Seb
(Please don't forget to give credits if you found this answer useful :)


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 12, 2005 3:16 am 
Newbie

Joined: Wed Aug 03, 2005 3:48 am
Posts: 7
Merci pour ta réponse!
Tu as tout à fait raison. C'était bien un problème lié aux méthodes equals/hashCode. Dés que je les ai ajoutées, cela a bien fonctionné!
Par contre, je n'ai pas placé mon code dans une transaction gérée par Spring mais, dans le support d'Hibernate3, un flush est fait à chaque appel d'une méthode de la classe HibernateTemplate.
Thierry


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 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.