1. 소개

Spring Data JPA를 사용 하면 데이터베이스에서 레코드를 읽거나 업데이트하거나 삭제 하는 파생 메서드 를 정의할 수 있습니다. 이는 데이터 액세스 계층에서 상용구 코드를 줄여주므로 매우 유용합니다.

이 예제에서는 실제 코드 예제와 함께 Spring 데이터 파생 삭제 메소드를 정의하고 사용하는 데 중점을 둘 것 입니다.

2. 파생된 deleteBy 메서드

먼저 예제를 설정해 보겠습니다. 과일 가게에서 사용할 수 있는 항목의 이름과 색상을 저장하기 위해 과일 엔터티를 정의합니다 .

@Entity
public class Fruit {
    @Id
    private long id;
    private String name;
    private String color;
    // standard getters and setters
}

다음으로 JpaRepository 인터페이스를 확장하고 파생된 메서드를 이 클래스에 추가하여 과일 엔터티에서 작동하도록 리포지토리를 추가합니다.

파생 메소드는 엔터티에 정의된 VERB + 속성으로 정의할 수 있습니다. 허용되는 동사 중 일부는 findBy, deleteByremoveBy 입니다.

이름 으로 Fruits 를 삭제하는 방법을 도출해 봅시다 .

@Repository
public interface FruitRepository extends JpaRepository<Fruit, Long> {
    Long deleteByName(String name);
}

이 예에서 deleteByName 메서드는 삭제된 레코드의 수를 반환합니다.

마찬가지로 다음 형식의 삭제 메서드를 파생시킬 수도 있습니다.

List<Fruit> deleteByColor(String color);

여기에서 deleteByColor 메서드는 지정된 색상의 모든 과일을 삭제하고 삭제된 레코드 List을 반환합니다.

파생된 삭제 메서드를 테스트해 보겠습니다. 먼저 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 어노테이션 을 사용해야 합니다 .

다음으로 두 번째 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);

두 메서드 유형의 동작에는 차이가 없습니다.

최종 인터페이스 는 다음과 같습니다.

@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@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);

두 솔루션이 유사해 보이고 동일한 결과를 달성하지만 약간 다른 접근 방식을 사용합니다. @Query 메서드 는 데이터베이스에 대해 단일 JPQL 쿼리를 생성합니다. 이에 비해 deleteBy 메서드는 읽기 쿼리를 실행한 다음 각 항목을 하나씩 삭제합니다.

또한 deleteBy 메서드는 삭제된 레코드 List을 반환할 수 있으며 사용자 지정 쿼리는 삭제된 레코드 수를 반환합니다.

5. 결론

이 기사에서는 파생된 Spring Data 파생된 삭제 메소드에 중점을 두었습니다. 이 기사에 사용된 전체 소스 코드는 GitHub 에서 찾을 수 있습니다 .

Persistence footer banner