web-dev-qa-db-ja.com

Spring Data:「delete by」はサポートされていますか?

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

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

よろしくお願いします。

84
curious1

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

@Modifyingアノテーションが助けになります。ただし、カスタムSQLの動作を提供する必要があります。

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

更新:

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

public interface UserRepository extends CrudRepository<User, Long> {

    Long countByFirstName(String firstName);

    @Transactional
    Long deleteByFirstName(String firstName);

    @Transactional
    List<User> removeByFirstName(String firstName);

}
169
Andrey Atapin

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

Long removeByLastname(String lastname);

List<User> deleteByLastname(String lastname);
68

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

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

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

もちろん、このようなメソッドを追加しようとすると、実際には機能しないことがわかり、完全なスタックトレースが取得されます。

Spring Data JPAのバージョン1.5.0.RELEASEを見て使用していたことに注意してください

6
geoand

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

  • 最初に、delete query where句を使用してselectクエリを実行することにより、データ(IDやその他の列など)を収集します。

  • 次に、最初のクエリのresultSetを取得した後、すべてのIDに対して2番目の削除クエリが実行されます(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
Suneet Khurana

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

0
Andrey Ofim