Spring Data JPA-派生削除メソッド

1. 前書き

Spring Data JPAでは、データベースからレコードを読み取り、更新、または削除するlink:/the-persistence-layer-with-spring-data-jpa [派生メソッド]を定義できます。 これは、データアクセス層からの定型コードを削減するため、非常に役立ちます。
このチュートリアルでは、*実用的なコード例を使用して、Spring Dataから派生した削除メソッド*の定義と使用に焦点を当てます。

2. 派生deleteByメソッド

まず、例を設定しましょう。 フルーツストアで使用可能なアイテムの名前と色を保存する_Fruit_エンティティを定義します。
@Entity
public class Fruit {
    @Id
    private long id;
    private String name;
    private String color;
    // standard getters and setters
}
次に、_JpaRepository_インターフェイスを拡張し、派生クラスをこのクラスに追加することにより、_Fruit_エンティティを操作するリポジトリを追加します。
*派生メソッドは、エンティティで定義されたVERB属性として定義できます。*許可される動詞のいくつかは、_findBy、deleteBy、_、および_removeBy_です。
__Fruit__sを_name_で削除するメソッドを派生させましょう:
@Repository
public interface FruitRepository extends JpaRepository<Fruit, Long> {
    Long deleteByName(String name);
}
この例では、_deleteByName_メソッドは削除されたレコードの数を返します。
同様に、次の形式の_delete_メソッドを派生させることもできます。
List<Fruit> deleteByColor(String color);
ここで、_deleteByColor_メソッドは、指定された色の果物をすべて削除し、削除されたレコードのリストを返します。
*派生した削除メソッドをテストしましょう。*最初に、_test-fruit-data.sql:_でデータを定義して、_Fruit_テーブルにいくつかのレコードを挿入します。
insert into fruit(id,name,color) values (1,'apple','red');
insert into fruit(id,name,color) values (2,'custard apple','green');
insert into fruit(id,name,color) values (3,'mango','yellow');
insert into fruit(id,name,color) values (4,'guava','green');
次に、すべての「緑」の果物を削除します。
@Transactional
@Test
@Sql(scripts = { "/test-fruit-data.sql" })
public void givenFruits_WhenDeletedByColor_ThenDeletedFruitsShouldReturn() {
     List<Fruit> fruits = fruitRepository.deleteByColor("green");

     assertEquals("number of fruits are not matching", 2, fruits.size());
     fruits.forEach(fruit -> assertEquals("It's not a green fruit", "green", fruit.getColor()));
}
*また、削除メソッドには_ @ Transactional_アノテーションを使用する必要があることに注意してください。*
次に、2番目の_deleteBy_メソッドに同様のテストケースを追加しましょう。
@Transactional
@Test
@Sql(scripts = { "/test-fruit-data.sql" })
public void givenFruits_WhenDeletedByName_ThenDeletedFruitCountShouldReturn() {

    Long deletedFruitCount = fruitRepository.deleteByName("apple");

    assertEquals("deleted fruit count is not matching", 1, deletedFruitCount.intValue());
}

3. 派生_removeBy_メソッド

  • removeBy verbを使用して、削除メソッドを導出することもできます。*

Long removeByName(String name);
List<Fruit> removeByColor(String color);
  • 2種類のメソッドの動作に違いはないことに注意してください。*

    最終的な_interface_は次のようになります。
@Repository
public interface FruitRepository extends JpaRepository<Fruit, Long> {

    Long deleteByName(String name);

    List<Fruit> deleteByColor(String color);

    Long removeByName(String name);

    List<Fruit> removeByColor(String color);
}
_removeBy_メソッドに同様の単体テストを追加しましょう。
@Transactional
@Test
@Sql(scripts = { "/test-fruit-data.sql" })
public void givenFruits_WhenRemovedByColor_ThenDeletedFruitsShouldReturn() {
    List<Fruit> fruits = fruitRepository.removeByColor("green");

    assertEquals("number of fruits are not matching", 2, fruits.size());
}
@Transactional
@Test
@Sql(scripts = { "/test-fruit-data.sql" })
public void givenFruits_WhenRemovedByName_ThenDeletedFruitCountShouldReturn() {
    Long deletedFruitCount = fruitRepository.removeByName("apple");

    assertEquals("deleted fruit count is not matching", 1, deletedFruitCount.intValue());
}

4. 派生削除メソッドと_ @ Query_

派生メソッドの名前が大きくなりすぎたり、関係のないエンティティ間でSQL JOINが関係するシナリオに遭遇する場合があります。
この場合、_ @ Query_および_https://www.baeldung.com/spring-data-jpa-modifying-annotation [@Modifying] _アノテーションを使用して、削除操作を実装することもできます。
カスタムクエリを使用して、派生削除メソッドの同等のコードを見てみましょう。
@Modifying
@Query("delete from Fruit f where f.name=:name or f.color=:color")
List<int> deleteFruits(@Param("name") String name, @Param("color") String color);
2つのソリューションは似ているように見え、同じ結果を達成しますが、アプローチが少し異なります。 * _ @ Query_メソッドは、データベースに対して単一のJPQLクエリを作成します。 比較すると、_deleteBy_メソッドは読み取りクエリを実行し、各アイテムを1つずつ削除します。*
また、_deleteBy_メソッドは削除されたレコードのリストを返すことができますが、カスタムクエリは削除されたレコードの数を返します。

5. 結論

この記事では、派生したSpring Dataの派生削除メソッドに注目しました。 この記事で使用されている完全なソースコードは、https://github.com/eugenp/tutorials/tree/master/persistence-modules/spring-data-jpa-2 [GitHub上]にあります。