1. 序章

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です。

Fruitnameで削除するメソッドを導き出しましょう。

@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テーブルにいくつかのレコードを挿入します。 X159X]

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()));
}

また、deleteメソッドには@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 動詞を使用して、削除メソッドを派生させることもできます。

Long removeByName(String name);
List<Fruit> removeByColor(String color);

2つのタイプのメソッドの動作に違いはないことに注意してください。

最終的なインターフェイスは次のようになります。

@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

派生メソッドの名前が大きくなりすぎたり、無関係なエンティティ間のSQLJOINが含まれたりするシナリオに遭遇する可能性があります。

この場合、@Queryおよび@Modifyingアノテーションを使用して、削除操作を実装することもできます。

カスタムクエリを使用して、派生したdeleteメソッドの同等のコードを見てみましょう。

@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. 結論

この記事では、派生したSpringDataから派生したdeleteメソッドに焦点を当てました。 この記事で使用されている完全なソースコードは、GitHubにあります。