2009-08-06 6 views
-1

J'ai des classes (UserSet et User) qui ont une relation many-to-many (c'est-à-dire que chaque utilisateur peut appartenir à certains UserSets). Dans la base de données, il y a une table UserSet, une table utilisateur et une table 'entre-deux' (UsersToUserSets). Maintenant, si je veux supprimer un utilisateur d'un UserSet en faisantHibernate: mauvaise performance lors de la suppression d'un élément de la relation plusieurs-à-plusieurs

userSet.getUsers().remove(user); 
session.flush() 

Hibernate récupère tout d'abord tous utilisateurs appartenant à UserSet et supprime alors un utilisateur et met à jour la table « inbetween ».

Comme il peut y avoir des milliers d'utilisateurs appartenant à un UserSet, cela est très mauvais pour la performance. Est-il possible d'éviter que tous les utilisateurs soient récupérés?

Les parties intéressantes des fichiers de mappage ressemblent à ceci:

<class name="...UserSet"> 
... 
    <set name="users" table="T_UM_USERS2USER_SETS"> 
     <key column="FK_USER_SET_ID" /> 
     <many-to-many column="FK_USER_ID" 
      class="...User" /> 
    </set> 
... 
</class> 

<class name="...User"> 
... 
    <set name="userSets" table="T_UM_USERS2USER_SETS" inverse="true"> 
     <key column="FK_USER_ID" /> 
     <many-to-many column="FK_USER_SET_ID" class="...UserSet" /> 
    </set> 
</class> 

Répondre

1

Tous les utilisateurs pour un UserSet particulier sont extraites parce que vous appelez userSet.getUsers().remove(user). L'exécution de toute opération sur une collection paresseuse entraîne la récupération de la collection. Ce que vous pouvez faire est:

1) Si la cardinalité userSets est inférieure à celle des utilisateurs (par exemple, un utilisateur donné n'appartient qu'à quelques userSets), vous pouvez changer la fin inverse de cette relation et appeler user.getUserSets().remove(userSet) - Je suppose ici vous souhaitez supprimer uniquement l'association et non l'entité réelle.

OU

2) Vous pouvez définir une requête SQL nommée pour supprimer la ligne d'association de T_UM_USERS2USER_SETS table et l'exécuter.

+0

Merci, votre première suggestion a fait l'affaire. J'avais déjà essayé le second, et bien que cela ait fonctionné en soi, il y a eu plusieurs problèmes dans d'autres parties du programme (ie dans la même session, les collections n'avaient pas le même état que la base de données, etc.) . – Ridcully

Questions connexes