Spring Data JPA - Métodos de Exclusão Derivados

Spring Data JPA - Métodos de Exclusão Derivados

1. Introdução

O Spring Data JPA nos permite definirderived methods que lêem, atualizam ou excluem registros do banco de dados. Isso é muito útil, pois reduz o código padrão da camada de acesso a dados.

Neste tutorial,we’ll focus on defining and using Spring Data derived delete methods com exemplos práticos de código.

2. Métodos derivados de deleteBy

Primeiro, vamos configurar nosso exemplo. Definiremos uma entidadeFruit para salvar o nome e a cor dos itens disponíveis em uma loja de frutas:

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

Em seguida, vamos adicionar nosso repositório para operar em entidadesFruit, estendendo a interfaceJpaRepository e adicionando nossos métodos derivados a esta classe.

Derived methods can be defined as VERB + attribute defined in an entity. Alguns dos verbos permitidos sãofindBy, deleteBy,eremoveBy.

Vamos derivar um método para excluirFruits por seusname:

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

Neste exemplo, o métododeleteByName retorna a contagem de registros excluídos.

Da mesma forma, também podemos derivar um métododelete da forma:

List deleteByColor(String color);

Aqui, o métododeleteByColor exclui todas as frutas com uma determinada cor e retorna uma lista de registros excluídos.

Let’s test the derived delete methods. Primeiro, vamos inserir alguns registros na tabelaFruit, definindo os dados emtest-fruit-data.sql:

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

Em seguida, excluiremos todas as frutas “verdes”:

@Transactional
@Test
@Sql(scripts = { "/test-fruit-data.sql" })
public void givenFruits_WhenDeletedByColor_ThenDeletedFruitsShouldReturn() {
     List 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()));
}

Além disso, observe que precisamos usar a anotação@Transactional para métodos de exclusão.

A seguir, vamos adicionar um caso de teste semelhante para o segundo métododeleteBy:

@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. Métodos derivados deremoveBy

Também podemos usar o verboremoveBy para derivar métodos de exclusão:

Long removeByName(String name);
List removeByColor(String color);

Observe que não há diferença no comportamento dos dois tipos de métodos.

Ointerface final será semelhante a:

@Repository
public interface FruitRepository extends JpaRepository {

    Long deleteByName(String name);

    List deleteByColor(String color);

    Long removeByName(String name);

    List removeByColor(String color);
}

Vamos adicionar testes de unidade semelhantes para os métodosremoveBy:

@Transactional
@Test
@Sql(scripts = { "/test-fruit-data.sql" })
public void givenFruits_WhenRemovedByColor_ThenDeletedFruitsShouldReturn() {
    List 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. Métodos excluídos derivados vs@Query

Podemos encontrar um cenário que torne o nome do método derivado muito grande ou que envolva um SQL JOIN entre entidades não relacionadas.

Nesse caso, também podemos usar as anotações@Querye@Modifying para implementar operações de exclusão.

Vejamos o código equivalente para nossos métodos de exclusão derivados, usando uma consulta personalizada:

@Modifying
@Query("delete from Fruit f where f.name=:name or f.color=:color")
List deleteFruits(@Param("name") String name, @Param("color") String color);

Embora as duas soluções pareçam semelhantes e alcancem o mesmo resultado, elas adotam uma abordagem ligeiramente diferente. The @Query method creates a single JPQL query against the database. By comparison, the deleteBy methods execute a read query, then delete each of the items one by one.

Além disso, o métododeleteBy pode retornar a lista de registros excluídos, enquanto a consulta personalizada retornará o número de registros excluídos.

5. Conclusão

Neste artigo, focamos nos métodos de exclusão derivados de Spring Data derivados. O código-fonte completo usado neste artigo pode ser encontradoover on GitHub.