- visão geral
- :
- Derived Query Methods in Spring Data JPA Repositories
- Spring Data JPA @Modificar Anotação
- Consulta Select
- 2.1. JPQL
- 2.2. Native
- Definir a Ordem em uma Consulta
- 3.1. A classificação para JPA Fornecido e Métodos Derivados
- 3.2. JPQL
- 3.3. Native
- paginação
- 4.1. JPQL
- 4.2. Native
- 4.3. A solução acima para consultas Nativas Funciona bem para as versões de dados de Primavera da JPA 2.0.4 e mais tarde.
- Parâmetros de consulta indexados
- 5.1. JPQL
- 5.2. Native
- parâmetros nomeados
- 6.1. JPQL
- 6.2. Nativo
- 7. Parâmetro de coleta
- actualizar as consultas com @modificando
- 8.1. JPQL
- 8.2. Native
- 8.3. Insere
- Consulta Dinâmica
- 9.1. Exemplo de uma Consulta Dinâmica
- 9.2. Repositórios personalizados e a API de critérios da JPA
- 9.3. Extending the Existing Repository
- 9.4. Usando o repositório
- Conclusion
visão geral
dados de Primavera fornece muitas formas de definir uma consulta que podemos executar. Uma delas é a anotação @Query.
neste tutorial, vamos demonstrar como usar a anotação @Query na JPA de dados de Primavera para executar tanto as consultas JPQL e SQL nativas.
também mostraremos como construir uma consulta dinâmica quando a anotação de @Query não for suficiente.
:
Derived Query Methods in Spring Data JPA Repositories
Spring Data JPA @Modificar Anotação
Consulta Select
para definir SQL para executar uma fonte de Dados do repositório, método, você pode anotar o método com @Consulta de anotação de seu valor de atributo contém a JPQL ou SQL para executar.
a anotação @Query tem precedência sobre as consultas nomeadas, que são anotadas com @NamedQuery ou definidas em um orm.ficheiro xml.
é uma boa abordagem colocar uma definição de consulta um pouco acima do método dentro do repositório ao invés de dentro do nosso modelo de domínio como consultas chamadas. O repositório é responsável pela persistência, então é um lugar melhor para armazenar essas definições.
2.1. JPQL
por padrão, a definição de consulta usa JPQL.
vamos ver um método simples de repositório que devolve as Entidades de utilizador activas da base de dados:
@Query("SELECT u FROM User u WHERE u.status = 1")Collection<User> findAllActiveUsers();
2.2. Native
We can use also native SQL to definite our query. Tudo o que temos a fazer é definir o valor da nativeQuery atributo como true e definir a consulta SQL nativa no atributo de valor da nota:
@Query( value = "SELECT * FROM USERS u WHERE u.status = 1", nativeQuery = true)Collection<User> findAllActiveUsersNative();
Definir a Ordem em uma Consulta
podemos passar um parâmetro adicional do tipo de Classificação de uma fonte de Dados de declaração de método que tem a Consulta @anotação. Será traduzido para a ordem por cláusula que é passada para a base de dados.
3.1. A classificação para JPA Fornecido e Métodos Derivados
Para os métodos que ficar fora da caixa, tais como findAll(Espécie) ou aqueles gerados pela análise de assinaturas de método, só podemos usar o objeto de propriedades para definir a nossa classificação:
userRepository.findAll(Sort.by(Sort.Direction.ASC, "name"));
Agora, imagine que queremos classificar o comprimento de um nome de propriedade:
userRepository.findAll(Sort.by("LENGTH(name)"));
Quando executamos o código acima, nós vamos receber uma exceção:
org.quadro de primavera.dado.mapeamento.Propertyreferenceexcepção: não foi encontrado nenhum comprimento de propriedade(nome) para o utilizador do tipo!
3.2. JPQL
Quando usamos JPQL para uma consulta de definição e, em seguida, Primavera de Dados pode lidar com a classificação, sem qualquer problema — tudo o que temos a fazer é adicionar um parâmetro de método de tipo de Classificação:
@Query(value = "SELECT u FROM User u")List<User> findAllUsers(Sort sort);
podemos chamar este método e passar um Tipo de parâmetro, que irá ordenar o resultado com o nome da propriedade do objeto de Usuário:
userRepository.findAllUsers(Sort.by("name"));
E porque usamos a Consulta @anotação, podemos usar o mesmo método para obter a lista ordenada dos Usuários pelo comprimento de seus nomes:
userRepository.findAllUsers(JpaSort.unsafe("LENGTH(name)"));
É fundamental que usar JpaSort.inseguro () para criar uma instância de ordenação de objectos.
quando usamos:
Sort.by("LENGTH(name)");
então vamos receber exatamente a mesma exceção que vimos acima para o método findAll ().
quando os dados da Primavera descobrem a ordem de ordenação insegura para um método que usa a anotação @Query, então ele apenas adiciona a cláusula de ordenação à consulta — ele salta verificando se a propriedade a Ordenar por pertence ao modelo de domínio.
3.3. Native
When the @Query annotation uses native SQL, then it’s not possible to define a Sort.Se o fizermos, vamos receber uma excepção .:
org.quadro de primavera.dado.app.repositorio.consulta.InvalidJpaQueryMethodException: Cannot use native queries with dynamic sorting and/or pagination
As the exception says, the sort isn’t supported for native queries. A mensagem de erro nos dá uma dica de que a paginação também causará uma exceção.No entanto, há um workaround que permite paginação, e vamos cobri-lo na próxima seção.
paginação
paginação nos permite retornar apenas um subconjunto de um resultado inteiro em uma página. Isto é útil, por exemplo, ao navegar através de várias páginas de dados em uma página web.Outra vantagem da paginação é que a quantidade de dados enviados do servidor para o cliente é minimizada. Ao enviar pedaços menores de dados, geralmente podemos ver uma melhoria no desempenho.
4.1. JPQL
Usando a paginação na definição de consulta JPQL é simples:
@Query(value = "SELECT u FROM User u ORDER BY id")Page<User> findAllUsersWithPagination(Pageable pageable);
podemos passar um PageRequest parâmetro para obter uma página de dados.
paginação também é suportada para consultas nativas, mas requer um pouco de trabalho adicional.
4.2. Native
we can enable pagination for native queries by declaring an additional attribute countQuery.
isto define o SQL a executar para contar o número de linhas em todo o resultado:
@Query( value = "SELECT * FROM Users ORDER BY id", countQuery = "SELECT count(*) FROM Users", nativeQuery = true)Page<User> findAllUsersWithPagination(Pageable pageable);
4.3. A solução acima para consultas Nativas Funciona bem para as versões de dados de Primavera da JPA 2.0.4 e mais tarde.
antes dessa versão, quando tentarmos executar tal consulta, receberemos a mesma exceção que descrevemos na seção anterior sobre ordenação.Podemos superar isso adicionando um parâmetro adicional para paginação dentro da nossa consulta:
@Query( value = "SELECT * FROM Users ORDER BY id \n-- #pageable\n", countQuery = "SELECT count(*) FROM Users", nativeQuery = true)Page<User> findAllUsersWithPagination(Pageable pageable);
no exemplo acima, adicionamos “\n – #pageable\n ” como substituto para o parâmetro paginação. Isto diz à JPA de dados de primavera como processar a consulta e injectar o parâmetro pageable. Esta solução funciona para a base de dados H2.
nós cobrimos como criar consultas selecionadas simples através de JPQL e SQL nativo. Em seguida, vamos mostrar como definir parâmetros adicionais.
Parâmetros de consulta indexados
existem duas maneiras possíveis de passar os parâmetros do método para a nossa consulta: parâmetros indexados e nomeados.Nesta secção, vamos cobrir os parâmetros indexados.
5.1. JPQL
para os parâmetros indexados em JPQL, os dados de mola irão passar os parâmetros do método para a consulta pela mesma ordem que aparecem na declaração do método:
@Query("SELECT u FROM User u WHERE u.status = ?1")User findUserByStatus(Integer status);@Query("SELECT u FROM User u WHERE u.status = ?1 and u.name = ?2")User findUserByStatusAndName(Integer status, String name);
para as consultas acima, o parâmetro do método do estado será atribuído ao parâmetro da consulta com o índice 1, e o parâmetro do método do nome será atribuído ao parâmetro da consulta com o índice 2.
5.2. Native
indexed parameters for the native queries work exactly in the same way as for JPQL:
@Query( value = "SELECT * FROM Users u WHERE u.status = ?1", nativeQuery = true)User findUserByStatusNative(Integer status);
na próxima seção, vamos mostrar uma abordagem diferente: passar parâmetros através do nome.
parâmetros nomeados
também podemos passar parâmetros do método para a consulta usando parâmetros nomeados. Nós os definimos usando a anotação @Param dentro de nossa Declaração de método do repositório.
cada parâmetro anotado com @Param deve ter uma cadeia de valor correspondente ao nome do parâmetro de consulta JPQL ou SQL correspondente. Uma consulta com parâmetros nomeados é mais fácil de ler e é menos propensa a erros no caso de a consulta precisa ser refactored.
6.1. JPQL
como mencionado acima, usamos a anotação @Param na declaração do método para combinar parâmetros definidos pelo nome em JPQL com parâmetros da declaração do método:
@Query("SELECT u FROM User u WHERE u.status = :status and u.name = :name")User findUserByStatusAndNameNamedParams( @Param("status") Integer status, @Param("name") String name);
Note que no exemplo acima, definimos nossa consulta SQL e parâmetros de método para ter os mesmos nomes, mas não é necessário desde que as cadeias de valor sejam as mesmas:
@Query("SELECT u FROM User u WHERE u.status = :status and u.name = :name")User findUserByUserStatusAndUserName(@Param("status") Integer userStatus, @Param("name") String userName);
6.2. Nativo
para a definição de consulta nativa, não há diferença em como passamos um parâmetro através do nome para a consulta em comparação com JPQL-usamos a anotação @Param:
@Query(value = "SELECT * FROM Users u WHERE u.status = :status and u.name = :name", nativeQuery = true)User findUserByStatusAndNameNamedParamsNative( @Param("status") Integer status, @Param("name") String name);
7. Parâmetro de coleta
vamos considerar o caso quando a cláusula onde de nossa consulta JPQL ou SQL contém a palavra-chave IN (ou não) :
SELECT u FROM User u WHERE u.name IN :names
neste caso, podemos definir um método de consulta que toma a coleção como um parâmetro:
@Query(value = "SELECT u FROM User u WHERE u.name IN :names")List<User> findUserByNameList(@Param("names") Collection<String> names);
como o parâmetro é uma coleção, ele pode ser usado com lista, HashSet, etc.
a seguir, vamos mostrar como modificar dados com a anotação @modificando.
actualizar as consultas com @modificando
podemos usar a anotação @ consulta para modificar o estado da base de dados, adicionando também a anotação @modificando ao método do repositório.
8.1. JPQL
O repositório, método que modifica os dados tem duas diferenças em comparação com a consulta select — ele tem o @Modificação de anotação e, claro, a JPQL consulta usa a atualização, em vez de selecionar:
@Modifying@Query("update User u set u.status = :status where u.name = :name")int updateUserSetStatusForName(@Param("status") Integer status, @Param("name") String name);
O valor de retorno define quantas linhas a execução da consulta atualizado. Tanto os parâmetros indexados como nomeados podem ser usados dentro das consultas de atualização.
8.2. Native
we can modify the state of the database also with a native query. Só precisamos adicionar a anotação @modificando:
@Modifying@Query(value = "update Users u set u.status = ? where u.name = ?", nativeQuery = true)int updateUserSetStatusForNameNative(Integer status, String name);
8.3. Insere
Para executar uma operação de inserção, nós temos que aplicar @Modificar e utilizar uma consulta nativa desde INSERIR não é uma parte da interface JPA:
@Modifying@Query( value = "insert into Users (name, age, email, status) values (:name, :age, :email, :status)", nativeQuery = true)void insertUser(@Param("name") String name, @Param("age") Integer age, @Param("status") Integer status, @Param("email") String email);
Consulta Dinâmica
muitas Vezes, nós vamos encontrar a necessidade de criação de instruções SQL com base nas condições ou conjuntos de dados cujos valores são conhecidos apenas em tempo de execução. E nesses casos, não podemos usar apenas uma consulta estática.
9.1. Exemplo de uma Consulta Dinâmica
Por exemplo, vamos imaginar uma situação onde precisamos para selecionar todos os usuários cujo e-mail é COMO um a partir de um conjunto definido em tempo de execução — email1, email2, …, emailn:
SELECT u FROM User u WHERE u.email LIKE '%email1%' or u.email LIKE '%email2%' ... or u.email LIKE '%emailn%'
uma vez que o conjunto é construído dinamicamente, não podemos saber em tempo de compilação como muitos GOSTAM de cláusulas para adicionar.
neste caso, não podemos apenas usar a anotação @Query já que não podemos fornecer uma declaração SQL estática.
em vez disso, ao implementar um repositório composto personalizado, podemos estender a funcionalidade jparepository base e fornecer nossa própria lógica para construir uma consulta dinâmica. Vamos ver como se faz isto.
9.2. Repositórios personalizados e a API de critérios da JPA
felizmente para nós, a Primavera fornece uma maneira de estender o repositório de base através do uso de interfaces de fragmentos personalizadas. Podemos então ligá-los juntos para criar um repositório composto.Vamos começar por criar uma interface de fragmentos personalizada .:
public interface UserRepositoryCustom { List<User> findUserByEmails(Set<String> emails);}
e depois vamos implementá-lo.:
public class UserRepositoryCustomImpl implements UserRepositoryCustom { @PersistenceContext private EntityManager entityManager; @Override public List<User> findUserByEmails(Set<String> emails) { CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<User> query = cb.createQuery(User.class); Root<User> user = query.from(User.class); Path<String> emailPath = user.get("email"); List<Predicate> predicates = new ArrayList<>(); for (String email : emails) { predicates.add(cb.like(emailPath, email)); } query.select(user) .where(cb.or(predicates.toArray(new Predicate))); return entityManager.createQuery(query) .getResultList(); }}
como mostrado acima, nós alavancamos a API de critérios da App para construir nossa consulta dinâmica.Além disso, precisamos ter certeza de incluir o Impl postfix no nome da classe. A primavera irá procurar a implementação do Relatório de auditoria do utilizador como Oimpl do Relatório de auditoria do utilizador. Uma vez que os fragmentos não são repositórios por si mesmos, a primavera se baseia neste mecanismo para encontrar a implementação dos fragmentos.
9.3. Extending the Existing Repository
Notice that all the query methods from section 2 through section 7 are in the UserRepository.Então, agora vamos integrar nosso fragmento estendendo a nova interface no Userrepositório:
public interface UserRepository extends JpaRepository<User, Integer>, UserRepositoryCustom { // query methods from section 2 - section 7}
9.4. Usando o repositório
e, finalmente, podemos chamar o nosso método de consulta dinâmica:
Set<String> emails = new HashSet<>();// filling the set with any number of itemsuserRepository.findUserByEmails(emails);
nós criamos com sucesso um repositório composto e chamamos nosso método personalizado.
Conclusion
In this article, we covered several ways of defining queries in Spring Data JPA repository methods using the @Query annotation.Também aprendemos a implementar um repositório personalizado e criar uma consulta dinâmica.
como sempre, os exemplos de código completos usados neste artigo estão disponíveis no GitHub.