2010-05-17 3 views
7

Lorsque j'essaie de créer un entityManager.remove (instance), le fournisseur JPA sous-jacent émet une opération de suppression distincte sur chaque entité GroupUser. Je pense que ce n'est pas correct du point de vue des performances, car si un groupe compte 1000 utilisateurs, 1001 appels seront émis pour supprimer le groupe entier et l'entité itr groupuser. Cela aurait-il plus de sens d'écrire une requête nommée pour supprimer toutes les entrées de la table groupuser (par exemple supprimer de group_user où group_id =?), Donc je devrais faire seulement 2 appels pour supprimer le groupe.L'opération de suppression d'entitymanager de JPA n'est pas performante

@Entity 
@Table(name = "tbl_group") 

public class Group { 

    @OneToMany(mappedBy = "group", cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
    @Cascade(value = DELETE_ORPHAN) 
    private Set<GroupUser> groupUsers = new HashSet<GroupUser>(0); 

Répondre

8

La réponse simple est oui. Si vous voulez supprimer un Group et que vous savez qu'il y a des tonnes d'enregistrements dans la table GroupUser, il est préférable de créer une requête de suppression qui fera tout en un lot au lieu d'un et un.

Si vous n'avez pas de cascade sur la base de données sous-jacente, (ou même si c'est le cas), il est conseillé de le faire dans le bon ordre.

Donc, supprimez d'abord le GroupUser.
En supposant que vous ayez l'objet Groupe que vous souhaitez supprimer.

int numberDeleted = entityManager.createQuery("DELETE FROM GroupUser gu WHERE gu.group.id=:id").setParameter("id",group.getId()).executeUpdate(); 

Le retour int montre le nombre d'enregistrements où supprimés.

Maintenant, vous pouvez enfin supprimer Group

entityManager.remove(group); 
entityManager.flush(); 

MISE À JOUR

On dirait @OnDelete sur le @OneToMany fait le tour

+0

Il est étrange que je ne suis pas en mesure de compter sur l'option cascade = DELETE selon la spécification JPA, car il supprime toutes les instances GroupUser 1 par 1. Cela implique que je dois écrire du code personnalisé pour optimiser la suppression des entrées. – Sam

+2

@Samuel. J'ai posé une question très similaire l'autre jour. Vous pouvez le trouver ici: http://stackoverflow.com/questions/2856460/hibernate-doesnt-generate-cascade Et le conseil d'utiliser @OnDelete au lieu de cascade pourrait signifier qu'il ne supprime pas les instances 1 par 1 Vous pourriez essayer. Je ne l'ai pas encore essayé cependant. –

+0

@Shervin - @OnDelete fonctionne comme un charme, en quelque sorte manqué de l'utiliser. Je suggère que vous ajoutiez un soutien pour cela aussi pour toutes les annotations @OneToMany. – Sam

2

Depuis le GroupUser peut avoir des cascades aussi, je ne pense pas qu'il y ait un moyen de mise en veille prolongée dire pour les lots supprimer via la configuration.

Mais si vous êtes certain qu'il n'y a pas cascade=DELETE sur GroupUser, ne hésitez pas à émettre un HQL/requête JPA-QL:

DELETE FROM GroupUser WHERE group=:group 

S'il y a des cascades, les manipuler avec une requête aussi bien.

+0

GroupUser n'a pas toutes les entrées cascadables. Son étrange que je ne suis pas capable de compter sur l'option cascade = DELETE selon la spécification JPA, puisque le fournisseur ORM sous-jacent supprime toutes les instances GroupUser 1-by-1. Cela implique que je dois écrire du code personnalisé pour optimiser la suppression des entrées. – Sam

Questions connexes