J'ai une entité User
et une entité Role
. La relation est définie comme ceci:
@OneToMany
@JoinTable(name="USER_ROLES", inverseJoinColumns=@JoinColumn(name="ROLE_ID"))
private List<Role> roles = null;
Maintenant, lorsque je supprime un rôle, je dois supprimer le rôle de tous les utilisateurs qui ont ce rôle. Normalement, vous feriez quelque chose comme ça en recherchant tous les utilisateurs avec ce rôle, en supprimant le rôle de la liste et en enregistrant l'utilisateur. Cependant, quand il pourrait y avoir plus d'un million d'utilisateurs, je ne veux pas faire de boucle sur autant d'entités dans l'application. Je souhaite donc utiliser une requête native pour supprimer des lignes du USER_ROLES
rejoindre la table. J'ai essayé d'ajouter ceci à mon référentiel:
@Query(value="DELETE FROM user_roles WHERE role_id = ?1", nativeQuery=true)
public void deleteRoleFromUsersWithRole(Long roleId);
Cependant, lorsque je fais cela, je vois ce qui suit dans les journaux:
[EL Fine]: sql: 2013-11-02 14:27:14.418--ClientSession(707349235)--Connection(2096606500)--Thread(Thread[http-bio-8080-exec-4,5,main])--DELETE FROM user_roles WHERE role_id = ?
bind => [1000110139999999953]
[EL Fine]: sql: 2013-11-02 14:27:14.478--ClientSession(707349235)--Thread(Thread[http-bio-8080-exec-4,5,main])--SELECT 1
[EL Warning]: 2013-11-02 14:27:14.482--UnitOfWork(1795045370)--Thread(Thread[http-bio-8080-exec-4,5,main])--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.4.1.v20121003-ad44345): org.Eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: No results were returned by the query.
Error Code: 0
Call: DELETE FROM user_roles WHERE role_id = ?
bind => [1000110139999999953]
Query: DataReadQuery(sql="DELETE FROM user_roles WHERE role_id = ?")
Je ne comprends pas ce que No results were returned by the query.
Est en train de dire. L'enregistrement est supprimé de la base de données, mais cette exception fait tout exploser.
Quelqu'un peut-il me dire ce que je fais mal ici?
Une méthode annotée avec @Query exécute une requête afin de lire à partir de la base de données. Ne pas mettre à jour la base de données. Pour ce faire, comme la documentation l'a indiqué, vous devez ajouter le @Modifying
annotation à la méthode:
Toutes les sections ci-dessus décrivent comment déclarer des requêtes pour accéder à une entité ou à une collection d'entités donnée. Bien sûr, vous pouvez ajouter un comportement de modification personnalisé en utilisant les fonctionnalités décrites dans la Section 1.3, "Implémentations personnalisées pour les référentiels Spring Data". Comme cette approche est réalisable pour des fonctionnalités personnalisées complètes, vous pouvez réaliser l'exécution de requêtes de modification qui n'ont en fait besoin que de la liaison de paramètres en annotant la méthode de requête avec @Modifying:
Exemple 2.13. Déclaration de manipulation des requêtes
@Modifying
@Query("update User u set u.firstname = ?1 where u.lastname = ?2")
int setFixedFirstnameFor(String firstname, String lastname);
Cela déclenchera la requête annotée à la méthode comme mise à jour de la requête au lieu d'une sélection.
utiliser ces deux annotations
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.transaction.annotation.Transactional;
@Modifying
@Transactional