No artigo, descreverei o uso de Spring Data.
O Spring Data é um mecanismo conveniente adicional para interagir com entidades de banco de dados, organizando-as em um repositório, recuperando dados, alterando, em alguns casos, para isso, será suficiente declarar uma interface e método nele, sem implementação.
Conteúdo:
- Repositório Spring
- Métodos de solicitação do nome do método
- Configuração e instalação
- Processamento de parâmetros especiais
- Implementações de repositório personalizado
- Repositório base personalizado
- Métodos de consulta - Consulta
1. Repositório de Mola
O conceito básico no Spring Data é o repositório. Essas são várias interfaces que usam o JPA Entity para interagir com ele. Então, por exemplo, uma interface
public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID>
fornece operações básicas para pesquisar, salvar e excluir dados (operações CRUD)
T save(T entity); Optional findById(ID primaryKey); void delete(T entity);
e outras operações.
Existem outras abstrações, como PagingAndSortingRepository.
I.e. se a lista fornecida pela interface for suficiente para interagir com a entidade, você poderá expandir diretamente a interface base para sua entidade, complementá-la com seus métodos de consulta e executar operações. Agora vou mostrar brevemente as etapas necessárias para o caso mais simples (sem ser distraído até agora pela configuração, ORM, banco de dados).
1. Crie uma entidade
@Entity @Table(name = "EMPLOYEES") public class Employees { private Long employeeId; private String firstName; private String lastName; private String email;
2. Herdado de uma das interfaces Spring Data, por exemplo, de CrudRepository
@Repository public interface CustomizedEmployeesCrudRepository extends CrudRepository<Employees, Long>
3. Use no cliente (serviço) uma nova interface para operações de dados
@Service public class EmployeesDataService { @Autowired private CustomizedEmployeesCrudRepository employeesCrudRepository; @Transactional public void testEmployeesCrudRepository() { Optional<Employees> employeesOptional = employeesCrudRepository.findById(127L);
Aqui eu usei o método
findById pronto. I.e. tão rapidamente e facilmente, sem implementação, obtemos uma lista pronta de operações do CrudRepository:
S save(S var1); Iterable<S> saveAll(Iterable<S> var1); Optional<T> findById(ID var1); boolean existsById(ID var1); Iterable<T> findAll(); Iterable<T> findAllById(Iterable<ID> var1); long count(); void deleteById(ID var1); void delete(T var1); void deleteAll(Iterable<? extends T> var1); void deleteAll();
É claro que essa lista provavelmente não é suficiente para interagir com a entidade e aqui você pode expandir sua interface com métodos de consulta adicionais.
2. Métodos de consulta a partir do nome do método
Solicitações para a entidade podem ser criadas diretamente a partir do nome do método. Para fazer isso, a localização ... Por, leia ... Por, consulta ... Por, conte ... Por e obtenha ... Por prefixos são usados, além do prefixo do método, ele começa a analisar o restante. A frase introdutória pode conter expressões adicionais, por exemplo, Distinto. Em seguida, o primeiro por atua como um separador para indicar o início dos critérios reais. Você pode definir condições para propriedades da entidade e combiná-las usando And e Or. Exemplos
@Repository public interface CustomizedEmployeesCrudRepository extends CrudRepository<Employees, Long> {
A documentação define a lista inteira e as regras para escrever o método. O resultado pode ser uma entidade T, opcional, lista, fluxo. Em um ambiente de desenvolvimento, como o Idea, há uma dica para escrever métodos de consulta.

Basta definir um método dessa maneira, sem implementação, e o Spring preparará uma solicitação para a entidade.
@SpringBootTest public class DemoSpringDataApplicationTests { @Autowired private CustomizedEmployeesCrudRepository employeesCrudRepository; @Test @Transactional public void testFindByFirstNameAndLastName() { Optional<Employees> employeesOptional = employeesCrudRepository.findByFirstNameAndLastName("Alex", "Ivanov");
3. Configuração e instalação
Todo o projeto está disponível no github
github DemoSpringDataAqui, apenas tocarei em alguns recursos.
Os beans TransactionManager, dataSource e entityManagerFactory são definidos em context.xml. É importante indicar nele também
<jpa:repositories base-package="com.example.demoSpringData.repositories"/>
caminho onde os repositórios são definidos.
O EntityManagerFactory está configurado para funcionar com o Hibernate ORM e, por sua vez, é com o banco de dados Oracle XE, aqui outras opções são possíveis, no context.xml tudo isso é visível. O arquivo pom possui todas as dependências.
4. Processamento especial de parâmetros
Nos métodos de consulta, em seus parâmetros, você pode usar parâmetros especiais Pageable, Classificar e restrições Top e First.
Por exemplo, assim, você pode pegar a segunda página (índice com -0), o tamanho de três elementos e classificada por firstName; depois de especificar o parâmetro Pageable no método do repositório, os critérios do nome do método também serão usados - “Pesquisar por Nome, começando com%„
@Repository public interface CustomizedEmployeesCrudRepository extends CrudRepository<Employees, Long> { List<Employees> findByFirstNameStartsWith(String firstNameStartsWith, Pageable page);
5. Implementações customizadas para o repositório
Suponha que você precise de um método no repositório que não possa ser descrito pelo nome do método, então você pode implementá-lo usando sua própria interface e sua classe de implementação. No exemplo abaixo, adicionarei ao repositório um método para obter funcionários com remuneração máxima.
Declarar interface
public interface CustomizedEmployees<T> { List<T> getEmployeesMaxSalary(); }
Implementa a interface. Usando o HQL (SQL), recebo funcionários com remuneração máxima, outras implementações são possíveis.
public class CustomizedEmployeesImpl implements CustomizedEmployees { @PersistenceContext private EntityManager em; @Override public List getEmployeesMaxSalary() { return em.createQuery("from Employees where salary = (select max(salary) from Employees )", Employees.class) .getResultList(); } }
E também expandindo Crud Repository Employees com CustomizedEmployees.
@Repository public interface CustomizedEmployeesCrudRepository extends CrudRepository<Employees, Long>, CustomizedEmployees<Employees>
Há uma característica importante aqui. A interface de implementação da classe deve terminar (postfix) no
Impl ou na configuração em que você precisa colocar seu postfix
<repositories base-package="com.repository" repository-impl-postfix="MyPostfix" />
Verificando a operação deste método através do repositório
public class DemoSpringDataApplicationTests { @Autowired private CustomizedEmployeesCrudRepository employeesCrudRepository; @Test @Transactional public void testMaxSalaryEmployees() { List<Employees> employees = employeesCrudRepository.getEmployeesMaxSalary(); employees.stream() .forEach(e -> System.out.println(e.getFirstName() + " " + e.getLastName() + " " + e.getSalary())); }
Outro caso, quando é necessário alterar o comportamento de um método existente na interface do Spring, por exemplo, excluir no CrudRepository, preciso que, em vez de excluir do banco de dados, seja definido um sinal de exclusão. A técnica é exatamente a mesma. Abaixo está um exemplo:
public interface CustomizedEmployees<T> { void delete(T entity);
Agora, se você chamar
delete em employeeCrudRepository, o objeto será marcado apenas como excluído.
6. Repositório da Base do Usuário
No exemplo anterior, mostrei como redefinir o repositório de exclusão de uma entidade no Crud, mas se você precisar fazer isso para todas as entidades do projeto, faça com que sua própria interface não seja tão boa para cada um ... então, nos dados do Spring, você pode configurar seu repositório base. Para fazer isso:
Uma interface é declarada e nela um método para substituição (ou comum a todas as entidades do projeto). Aqui, para todas as minhas entidades, apresentei minha interface
BaseEntity (isso não é necessário), para a conveniência de chamar métodos comuns, seus métodos coincidem com os métodos da entidade.
public interface BaseEntity { Boolean getDeleted(); void setDeleted(Boolean deleted); }
Na configuração, você precisa especificar este repositório base, será comum a todos os repositórios do projeto
<jpa:repositories base-package="com.example.demoSpringData.repositories" base-class="com.example.demoSpringData.BaseRepositoryImpl"/>
Agora o Repositório de funcionários (e outros) deve ser expandido a partir do BaseRepository e já o usará no cliente.
public interface EmployeesBaseRepository extends BaseRepository <Employees, Long> {
Verificando EmployeesBaseRepository
public class DemoSpringDataApplicationTests { @Resource private EmployeesBaseRepository employeesBaseRepository; @Test @Transactional @Commit public void testBaseRepository() { Employees employees = new Employees(); employees.setLastName("Ivanov");
Agora, como antes, o objeto será marcado como excluído e isso será realizado para todas as entidades que estendem a interface BaseRepository. No exemplo, o método de pesquisa -
Consulta por Exemplo (QBE) foi aplicado, não o descreverei aqui, o exemplo mostra o que faz, simples e conveniente.
Escrevi anteriormente que, se você precisar de um método específico ou de sua implementação, que não possa ser descrito usando o nome do método, isso poderá ser feito por meio de alguma interface Personalizada (CustomizedEmployees) e faça uma implementação de cálculo. E você pode seguir o outro caminho, indicando a consulta (HQL ou SQL), como calcular essa função.
Para o meu exemplo com getEmployeesMaxSalary, essa opção de implementação é ainda mais simples. Vou complicar com o parâmetro de entrada de salário. I.e. basta declarar o método de cálculo e solicitar na interface.
@Repository public interface CustomizedEmployeesCrudRepository extends CrudRepository<Employees, Long>, CustomizedEmployees<Employees> { @Query("select e from Employees e where e.salary > :salary") List<Employees> findEmployeesWithMoreThanSalary(@Param("salary") Long salary, Sort sort);
Verificando
@Test @Transactional public void testFindEmployeesWithMoreThanSalary() { List<Employees> employees = employeesCrudRepository.findEmployeesWithMoreThanSalary(10000L, Sort.by("lastName"));
Mencionarei apenas que pode haver solicitações de modificação. Para isso, uma anotação adicional
@Modification é adicionada a elas
@Modifying @Query("update Employees e set e.firstName = ?1 where e.employeeId = ?2") int setFirstnameFor(String firstName, String employeeId);
Outro dos grandes recursos das anotações de
consulta é a substituição do tipo de domínio da entidade na consulta usando o modelo
# {# entityName} , por meio de expressões SpEL.
Assim, por exemplo, no meu exemplo hipotético, quando precisar ter o sinal "excluído" para todas as entidades, farei uma interface básica com um método para obter uma lista de objetos com o sinal "excluído" ou "ativo"
@NoRepositoryBean public interface ParentEntityRepository<T> extends Repository<T, Long> { @Query("select t from #{#entityName} t where t.deleted = ?1") List<T> findMarked(Boolean deleted); }
Além disso, todos os repositórios de entidades podem ser estendidos a partir dele. As interfaces que não são repositórios, mas estão localizadas na pasta de configuração "pacote básico", anote @NoRepositoryBean.
Repositório de funcionários
@Repository public interface EmployeesEntityRepository extends ParentEntityRepository <Employees> { }
Agora, quando a solicitação for executada, o nome da entidade
T será substituído no corpo da solicitação por um repositório específico que estenderá o ParentEntityRepository, neste caso, Employees.
Verifique
@SpringBootTest public class DemoSpringDataApplicationTests { @Autowired private EmployeesEntityRepository employeesEntityRepository; @Test @Transactional public void testEntityName() { List<Employees> employeesMarked = employeesEntityRepository.findMarked(true);
Materiais
Spring Data JPA - Documentação de ReferênciaProjeto no github .