Comment puis-je utiliser JPQL pour supprimer des entrées d'une table de jointure?

StackOverflow https://stackoverflow.com/questions/1071940

  •  21-08-2019
  •  | 
  •  

Question

J'ai un objet JPA qui a plusieurs-à-plusieurs comme ceci:

@Entity
public class Role {
    //...

    @ManyToMany(fetch=FetchType.EAGER)
    @JoinTable(
    name="RolePrivilege",
    joinColumns=
        @JoinColumn(name="role", referencedColumnName="ID"),
    inverseJoinColumns=
        @JoinColumn(name="privilege", referencedColumnName="ID")
    )
    private Set<Privilege> privs;
}

Il n'y a pas un objet JPA pour RolePrivilege, donc je ne suis pas sûr de savoir comment écrire une requête JPQL pour supprimer des entrées du champ privs d'un objet rôle. Par exemple, je l'ai essayé, mais ça ne marche pas. Il se plaint que Role.privs n'est pas mis en correspondance.

DELETE FROM Role.privs p WHERE p.id=:privId

Je ne sais pas quoi d'autre pour essayer. Je pourrais bien sûr il suffit d'écrire une requête native qui supprime de la table de jointure RolePrivilege. Mais, je suis inquiet que cela irait mal avec des objets d'interagir localement mises en cache qui ne serait pas mis à jour par la requête native.

Est-il même possible d'écrire JPQL pour supprimer les entrées d'une table de jointure comme ça? Sinon je peux charger tous les objets de rôle et supprimer les entrées de la collection privs de chacun et persistent chaque rôle. Mais il semble stupide de le faire que si une simple requête JPQL fera tout à la fois.

Était-ce utile?

La solution

La mise à jour JPQL et supprimer les déclarations doivent se référer à un nom d'entité, et non pas un nom de table, donc je pense que vous êtes hors de la chance avec l'approche que vous avez proposé.

En fonction de votre fournisseur de JPA, vous pouvez supprimer les entrées de la joinTable à l'aide d'une simple instruction SQL brute (devrait être 100% portable) et ensuite interagir avec votre programme API fournisseur de cache pour expulser les données. Par exemple, dans Hibernate, vous pouvez appeler evict () pour fermer toutes les collections « Role.privs » à partir du cache de niveau 2:

sessionFactory.evictCollection("Role.privs", roleId); //evict a particular collection of privs
sessionFactory.evictCollection("Role.privs"); //evict all privs collections

Malheureusement, je ne travaille pas avec les API assez JPA pour en être sûr ce qui est pris en charge exactement.

Autres conseils

Je cherchais également une approche de JPQL pour supprimer un grand nombre à plusieurs rapport (contenu dans une table se joindre). De toute évidence, il n'y a pas de concept de tables dans un ORM, donc nous ne pouvons pas utiliser effacements ... Mais je souhaite qu'il y ait un opérateur spécial pour ces cas. Quelque chose comme LINK et UNLINK. Peut-être une future fonctionnalité?

De toute façon, ce que je l'ai fait pour atteindre ce besoin a été de travailler avec les collections mises en œuvre dans les beans entités, celles qui tracent les nombreux à plusieurs relations.

Par exemple, si je suis un étudiant de classe qui a beaucoup à plusieurs relations avec des cours:

@ManyToMany
private Collection <Courses> collCourses;

Je construis dans l'entité un getter et setter pour cette collection. Ensuite, par exemple à partir d'un EJB, je récupère la collection en utilisant le getter, ajouter ou supprimer le cours désiré, et enfin, utiliser le setter pour attribuer la nouvelle collection. Et il est fait. Il fonctionne parfaitement.

Cependant, mon principal souci est la performance. Un ORM est censé garder une énorme cache de tous les objets (si je ne me trompe pas), mais même l'utiliser pour travailler plus vite, je me demande si tous et récupérer tous les éléments d'une collection est vraiment efficace ...

Parce que pour moi, il est le plus inefficace que la récupération des registres à partir d'une table et post-filtre les utiliser au lieu pur Java d'un langage de requête qui fonctionne directement ou undirectly avec le moteur DB interne (SQL, JPQL ...).

Java is an object-oriented language and the whole point of ORM is to hide details of join tables and such from you. Consequently even contemplating deletion from a join table without considering the consequences would be strange.

No you can't do it with JPQL, that is for entities.

Retrieve the entities at either end and clear out their collections. This will remove the join tables entries. Object-oriented.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top