web-dev-qa-db-ja.com

Spring Data JPAが例外をスローするネイティブクエリを削除する

UserエンティティとRoleエンティティがあります。関係は次のように定義されます。

@OneToMany
@JoinTable(name="USER_ROLES", inverseJoinColumns=@JoinColumn(name="ROLE_ID"))
private List<Role> roles = null; 

次に、ロールを削除するとき、そのロールを持つすべてのユーザーからロールを削除する必要があります。通常は、このロールを持つすべてのユーザーを検索し、リストからロールを削除して、ユーザーを保存することで、このようなことを行います。ただし、100万人を超えるユーザーがいる可能性がある場合は、アプリ内のこれほど多くのエンティティをループしたくありません。したがって、ネイティブクエリを使用して、USER_ROLES結合テーブルから行を削除したいと考えています。これを私のリポジトリに追加してみました:

@Query(value="DELETE FROM user_roles WHERE role_id = ?1", nativeQuery=true)
public void deleteRoleFromUsersWithRole(Long roleId);

ただし、これを行うと、ログに次のように表示されます。

[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 = ?")

No results were returned by the query.の意味がわかりません。レコードはデータベースから削除されますが、この例外により、すべてが破壊されます。

誰かが私がここで間違っていることを教えてもらえますか?

21
dnc253

@Queryアノテーションが付けられたメソッドは、データベースから読み取るためにクエリを実行します。データベースを更新しません。これを行うには、 ドキュメント が示すように、@Modifyingアノテーションをメソッドに追加する必要があります。

上記のすべてのセクションでは、特定のエンティティまたはエンティティのコレクションにアクセスするクエリを宣言する方法について説明しました。もちろん、「Spring Dataリポジトリのカスタム実装」で説明されている機能を使用して、カスタム変更動作を追加できます。このアプローチは包括的なカスタム機能に適しているため、クエリメソッドに@Modifyingアノテーションを付けることで、実際にパラメーターバインディングのみが必要な変更クエリの実行を実現できます。

例2.13。クエリの操作を宣言する

@Modifying
@Query("update User u set u.firstname = ?1 where u.lastname = ?2")
int setFixedFirstnameFor(String firstname, String lastname);

これにより、メソッドに注釈が付けられたクエリが、選択クエリではなく更新クエリとしてトリガーされます。

45
JB Nizet

この2つの注釈を使用する

import org.springframework.data.jpa.repository.Modifying;
import org.springframework.transaction.annotation.Transactional;

@Modifying
@Transactional
4
Achraf Farouky