Removendo “abstract Service/Repository ” proprietários com Spring Data

Geralmente em projetos JavaEE/Spring criamos classes para abstrair métodos comuns de acesso ao banco de dados, como no exemplo demonstrado na figura a seguir, com o objetivo de ganharmos a centralização dessas implementações para uma melhor reusabilidade, no entanto, por serem classes proprietárias no sistema há o risco de alterações indevidas ou de bugs com grande impactos em todo projeto, com isso, o projeto Spring Data trás algumas facilidades em conjunto com alguns padrões de projetos para utilizarmos em nossos projetos.

No código a baixo é demonstrado um exemplo de uma classe proprietária com o objetivo de abstrair os principais métodos de manipulação de banco de dados e restringir o acesso ao entityManager.

public abstract class AbstractService<T extends Model, ID extends Serializable> {
    ...

    @PersistenceContext
    private EntityManager entityManager;

    public T findById(Long id) {
        return this.entityManager.find(type, id);
    }

    @Transactional
    public void remove(T object) {
        this.entityManager.remove(this.entityManager.getReference(this.type, object.getId()));
    }

    @Transactional
    public void save(T object) {
        if (object.getId() == null) {
            this.entityManager.persist(object);
        } else {
            this.entityManager.merge(object);
        }
    }
...
}

No entanto, essa implementação não é necessária quando utilizado Spring Data, pois na interface JpaRepository disponibiliza uma série de métodos com operações padrões de acesso ao banco via JPA, basta implementar essa interface utilizando o padrão Repository do Spring, como demonstrado no exemplo a seguir.

Para utilizar o Spring Data, adicionar a dependência spring-data-jpa.

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-jpa</artifactId>
    <version>1.10.8.RELEASE</version>
</dependency>

Após adicionado a dependência do Spring Data é preciso criar uma interface para extender os recursos do JpaRespository, pois essa interface disponibiliza métodos como findAll, save, saveAndFlush, deleteInBatch, entre outros.

import org.springframework.data.jpa.repository.JpaRepository;

public interface PessoaRepository extends JpaRepository&amp;amp;amp;lt;Pessoa, Long&amp;amp;amp;gt; {

Ao extender a interface JpaRepository são passados via parâmetro a classe e o tipo do id da entidade gerenciado pelo repositório. No caso do exemplo, é definido o PessoaRepository para gerenciar a entidade Pessoa que possui ID do tipo Long.

Mais detalhes de como usar o JpaRespository pode ser visto na doc do Spring Data.

Após criado a interface PessoaRepository, é preciso habilitar os repositórios JPA no contexto do Spring, isso é feito através da anotação @EnableJpaRepositories.

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackageClasses = {PessoaRepository.class})
@ComponentScan(basePackageClasses = {PessoaService.class})
public class AppConfig {

Após habilitado os repositórios no contexto do Spring, é apenas injetar a interface na classe desejada para ter acesso aos métodos proporcionados pelo Spring Data.

@Service
public class PessoaService {

    @Autowired
    private PessoaRepository pessoaRepository;

    public List&amp;amp;amp;lt;Pessoa&amp;amp;amp;gt; findAll() {
        return pessoaRepository.findAll();
    }

    public void save(Pessoa pessoa) {
        return pessoaRepository.save(pessoa);
    }

    public void findById(Long id) {
        return pessoaRepository.findOne(id);
    }

    public void delete(Long id) {
        return pessoaRepository.delete(id);
    }
}

Nesse post foi possível ver apenas uma das facilidades que o Spring Data proporciona para nossos projetos, além da interface JpaRepository há outras como  CrudRepository e PagingAndSortingRepository, integração com QueryDsl, como exemplo a  interface QueryDslPredicateExecutor, integração com base de dados NoSQL, entre outros.

Complemento:

Segue um commit exemplificando a migração de um abstract service para a utilização de JpaRepository do Spring Data: https://github.com/emmanuelneri/springmvc-angularjs/commit/5402edfba70cc35f858727dd5c166ada6064cb58

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s