DEV Community

Uiratan Cavalcante
Uiratan Cavalcante

Posted on

Spring Data Repositories

No Spring Data, um repository é uma interface que abstrai a camada de persistência e permite interagir com o banco de dados de maneira simples e declarativa. Ele segue o padrão Repository do Domain-Driven Design (DDD), permitindo que você se concentre mais na lógica de negócios do que nos detalhes de acesso a dados. O Spring Data oferece diversas implementações de repositories que facilitam a criação de operações CRUD (Create, Read, Update, Delete) e consultas complexas.

Tipos de Repositories no Spring Data

  1. CrudRepository

    • Responsabilidade: Fornece operações CRUD básicas.
    • Métodos comuns:
      • save(S entity): Persiste uma entidade.
      • findById(ID id): Recupera uma entidade pelo ID.
      • findAll(): Recupera todas as entidades.
      • deleteById(ID id): Exclui uma entidade pelo ID.
    • Exemplo:
     import org.springframework.data.repository.CrudRepository;
    
     public interface AutorRepository extends CrudRepository<Autor, Long> {
     }
    
  2. JpaRepository

    • Responsabilidade: Extende CrudRepository e adiciona funcionalidades específicas do JPA, como paginação e ordenação.
    • Métodos adicionais:
      • findAll(Pageable pageable): Recupera uma página de resultados.
      • findAll(Sort sort): Recupera todos os resultados com ordenação.
      • flush(): Atualiza o estado da sessão JPA.
    • Exemplo:
     import org.springframework.data.jpa.repository.JpaRepository;
    
     public interface AutorRepository extends JpaRepository<Autor, Long> {
     }
    
  3. PagingAndSortingRepository

    • Responsabilidade: Oferece funcionalidades de paginação e ordenação, mas sem as funcionalidades avançadas do JPA.
    • Exemplo:
     import org.springframework.data.repository.PagingAndSortingRepository;
    
     public interface AutorRepository extends PagingAndSortingRepository<Autor, Long> {
     }
    
  4. Query Methods

    • O Spring Data permite criar consultas personalizadas a partir do nome do método, sem precisar escrever SQL ou JPQL.
    • Exemplo:
     public interface AutorRepository extends JpaRepository<Autor, Long> {
         List<Autor> findByNome(String nome);
         List<Autor> findByDescricaoContaining(String descricao);
     }
    

Neste exemplo, o Spring Data cria as consultas baseadas nos nomes dos métodos (findByNome, findByDescricaoContaining), que são traduzidas para consultas JPQL de maneira automática.

  1. @Query

    • Para consultas mais complexas ou específicas, você pode usar a anotação @Query para escrever JPQL ou SQL nativo diretamente no repositório.
    • Exemplo:
     @Query("SELECT a FROM Autor a WHERE a.nome = ?1")
     List<Autor> findByNomeAutor(String nome);
    

Também é possível utilizar SQL nativo:

   @Query(value = "SELECT * FROM autor WHERE nome = ?1", nativeQuery = true)
   List<Autor> findByNomeAutorNative(String nome);
Enter fullscreen mode Exit fullscreen mode

Consulta Dinâmica com Querydsl

Para consultas dinâmicas e mais complexas, você pode usar o Querydsl integrado ao Spring Data. Isso permite gerar consultas de forma programática e flexível, com base em critérios que você define dinamicamente.

  • Exemplo:
  import com.querydsl.core.types.dsl.StringPath;
  import com.querydsl.core.types.dsl.NumberPath;
  import com.querydsl.jpa.impl.JPAQuery;

  QAutor autor = QAutor.autor;
  JPAQuery<Autor> query = new JPAQuery<>(entityManager);
  List<Autor> autores = query.select(autor)
                             .from(autor)
                             .where(autor.nome.eq("Nome"))
                             .fetch();
Enter fullscreen mode Exit fullscreen mode

Suporte a Transações

O Spring Data garante que as transações sejam feitas de forma segura e eficiente. As transações podem ser controladas diretamente dentro do repository ou no serviço (com o uso de @Transactional).

Exemplo de uso de @Transactional:

import org.springframework.transaction.annotation.Transactional;

@Service
public class AutorService {

    private final AutorRepository autorRepository;

    public AutorService(AutorRepository autorRepository) {
        this.autorRepository = autorRepository;
    }

    @Transactional
    public Autor criarAutor(Autor autor) {
        return autorRepository.save(autor);
    }
}
Enter fullscreen mode Exit fullscreen mode

Exemplo Completo

Aqui está um exemplo básico de um repositório para o gerenciamento de Autores em um sistema:

  1. Entidade Autor:
   @Entity
   public class Autor {

       @Id
       @GeneratedValue(strategy = GenerationType.IDENTITY)
       private Long id;

       @NotBlank
       private String nome;

       @Email
       private String email;

       @Size(max = 400)
       private String descricao;

       // getters e setters
   }
Enter fullscreen mode Exit fullscreen mode
  1. Repository:
   public interface AutorRepository extends JpaRepository<Autor, Long> {

       List<Autor> findByNome(String nome);

       List<Autor> findByDescricaoContaining(String descricao);
   }
Enter fullscreen mode Exit fullscreen mode
  1. Serviço:
   @Service
   public class AutorService {

       private final AutorRepository autorRepository;

       public AutorService(AutorRepository autorRepository) {
           this.autorRepository = autorRepository;
       }

       public Autor cadastrarAutor(Autor autor) {
           return autorRepository.save(autor);
       }

       public List<Autor> buscarAutoresPorNome(String nome) {
           return autorRepository.findByNome(nome);
       }

       public List<Autor> buscarAutoresPorDescricao(String descricao) {
           return autorRepository.findByDescricaoContaining(descricao);
       }
   }
Enter fullscreen mode Exit fullscreen mode

A tabela abaixo apresenta uma comparação dos tipos de Repositories no Spring Data:

Repositório Descrição Métodos Principais Exemplo de Uso
CrudRepository Fornece operações CRUD básicas. Ideal para operações simples. save(S entity), findById(ID id), findAll(), deleteById(ID id) public interface AutorRepository extends CrudRepository<Autor, Long> {}
JpaRepository Extende CrudRepository e adiciona funcionalidades do JPA (paginamento, etc.). save(S entity), findById(ID id), findAll(), findAll(Pageable pageable), flush() public interface AutorRepository extends JpaRepository<Autor, Long> {}
PagingAndSortingRepository Foca em paginação e ordenação, mas sem funcionalidades JPA. findAll(Pageable pageable), findAll(Sort sort) public interface AutorRepository extends PagingAndSortingRepository<Autor, Long> {}
@Query (Consulta Personalizada) Permite escrever consultas personalizadas com JPQL ou SQL nativo. Consultas definidas com a anotação @Query @Query("SELECT a FROM Autor a WHERE a.nome = ?1") List<Autor> findByNomeAutor(String nome);
Querydsl Permite criar consultas dinâmicas e complexas programaticamente. Usado com a API Querydsl, com objetos Q-classes para construir consultas QAutor autor = QAutor.autor; JPAQuery<Autor> query = new JPAQuery<>(entityManager); query.select(autor).from(autor).where(autor.nome.eq("Nome")).fetch();

Essa tabela resume bem as diferenças entre os tipos de repositórios, ajudando a escolher o mais adequado dependendo das necessidades da aplicação.


Considerações Finais

  • O Spring Data abstrai muitos detalhes do JPA e oferece uma maneira fácil de manipular dados de forma rápida.
  • Você pode adicionar consultas personalizadas usando métodos ou anotações.
  • Repositories são facilmente testáveis com Mocking e também oferecem suporte a paginamento e ordenação.

Top comments (0)