Spring Data:「削除者」はサポートされていますか?


99

データベースアクセスにSpring JPAを使用しています。メソッドの実装を記述する必要がない、findByNameやcountByNameなどの例を見つけることができます。ある条件に基づいてレコードのグループを削除する例を見つけたいと思っています。

Spring JPAはdeleteByNameのような削除をサポートしていますか?どんなポインタでも大歓迎です。

よろしくお願いいたします。

回答:


184

非推奨の回答(Spring Data JPA <= 1.6.x)

@Modifying救助への注釈。ただし、カスタムSQL動作を提供する必要があります。

public interface UserRepository extends JpaRepository<User, Long> {
    @Modifying
    @Query("delete from User u where u.firstName = ?1")
    void deleteUsersByFirstName(String firstName);
}

更新:

Spring Data JPA(> = 1.7.x)の最新バージョンではdelete、のクエリ派生、removeおよびcount操作にアクセスできます。

public interface UserRepository extends CrudRepository<User, Long> {

    Long countByFirstName(String firstName);

    Long deleteByFirstName(String firstName);

    List<User> removeByFirstName(String firstName);

}

2
@AndreyAtapin Downvoteそれはもはや良い答えではないので。多分それを削除しますか?stackoverflowsの欠陥の1つは、問題のライブラリに関連付けられているバージョン変更/バグ修正の処理です。
ベンジョージ

1
@webgeek、私はでこの問題を解決するために使用しましたDELETE FROM x WHERE id = ?1 or parent_id = ?1。ところで、型がないことを確認してくださいparent__id(意図的にダブルローダッシュはありますか?)。なぜネイティブクエリオプションを使用するのですか?
Andrey Atapin

4
でも、私は成功し、削除するために持っている、@Transactionalアノテーションはqueryメソッドの上に必要とされている1.7.4を使う
gokhansari

40
通常、アプリケーションでは、@サービスクラス/メソッドがあり、それらはリポジトリを呼び出します。また、トランザクションはユースケースベースであるため、@サービスのパブリックメソッドは@ Transactionalとマークされているメソッドでなければなりません。ユースケースは、完全にコミットまたはロールバックする必要があることを意味します。個々のリポジトリメソッドではありません。そのため、リポジトリメソッドでは@ Transactionalを使用しないでください。しかし、リポジトリを使用するServiceメソッドについては。
user1567291 2017

1
@Transactionalをrepoで作成することは、repoを複数回呼び出す場合にそれぞれがdiffトランザクションを持つため、1つのクエリ内でロールバックすることを意味します。サービスレベルで提供する場合、関数全体がエラーでロールバックされます。
P Satish Patro、

78

指定されたメソッド名を使用した削除クエリの派生は、Spring Data JPAのバージョン1.6.0.RC1以降でサポートされています。キーワードremovedeleteがサポートされています。戻り値として、削除されたエンティティの数またはリストから選択できます。

Long removeByLastname(String lastname);

List<User> deleteByLastname(String lastname);

7

Spring Data JPAのソースコード、特にPartTreeJpaQueryクラスを見てみると、インスタンス化しようとしていることがわかりますPartTree。そのクラス内では、次の正規表現

private static final Pattern PREFIX_TEMPLATE = Pattern.compile("^(find|read|get|count|query)(\\p{Lu}.*?)??By")

何が許可され、何が許可されないかを示す必要があります。

もちろん、そのようなメソッドを追加しようとすると、実際にはそれが機能せず、完全なスタックトレースが得られます。

1.5.0.RELEASESpring Data JPAのバージョンを見て使用していたことに注意する必要があります


6

2つの方法:-

1つ目のカスタムクエリ

@Modifying
@Query("delete from User where firstName = :firstName")
void deleteUsersByFirstName(@Param("firstName") String firstName);

メソッドによる2番目の1つのJPAクエリ

List<User> deleteByLastname(String lastname);

メソッドによるクエリを実行すると(2番目の方法)、最初にget呼び出しが行われます。

select * from user where last_name = :firstName

次に、リストにロードします。次に、削除IDを1つずつ呼び出します。

delete from user where id = 18
delete from user where id = 19

最初にオブジェクトのリストをフェッチし、次にforループでIDを1つずつ削除します

しかし、最初のオプション(カスタムクエリ)、

単一のクエリであり、値が存在する場所はどこでも削除されます。

このリンクにもアクセスhttps://www.baeldung.com/spring-data-jpa-deleteby


1
情報をありがとう!
curious1

2

Spring JPAによって直接提供される事前定義の削除メソッドを使用する場合、フレームワークによって以下の2つのクエリが実行されます。

  • 最初に、select queryとdelete query where句を実行して、データ(IDや他の列など)を収集します。

  • 次に、最初のクエリのresultSetを取得した後、2番目の削除クエリがすべてのIDに対して実行されます(1つずつ)

    注:単一のMYSQL削除クエリに対して多くのクエリが実行されるため、これはアプリケーションに対して最適化された方法ではありません。

以下のカスタマイズされたメソッドを使用して実行される削除クエリは1つだけなので、これは削除クエリコードの別の最適化された方法です。



@NamedNativeQueries({

@NamedNativeQuery(name = "Abc.deleteByCreatedTimeBetween",
            query = "DELETE FROM abc WHERE create_time BETWEEN ?1 AND ?2")
    ,

    @NamedNativeQuery(name = "Abc.getByMaxId",
            query = "SELECT max(id) from abc")
})

@Entity
public class Abc implements Serializable {

}

@Repository
public interface AbcRepository extends CrudRepository {

    int getByMaxId();

    @Transactional
    @Modifying
    void deleteByCreatedTimeBetween(String startDate, String endDate);
}

1

バッチ削除に派生クエリを使用するときは注意してください。それはあなたが期待するものではありません:DeleteExecution


こんにちは。RBAR(苦悶する行)を指摘している場合、それを回答に追加できますか?(そして私は賛成します)。あなたがここで指摘していることをちょっと推測しています。
granadaCoder

0

はい、deleteByメソッドがサポートされています。これを使用するには、メソッドに@Transactionalアノテーションを付ける必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.