dados de Primavera JPA @Query

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

Explore the query derivation mechanism in Spring Data JPA.
Leia mais →

Spring Data JPA @Modificar Anotação

Criar DML e DDL consultas em Spring Data JPA combinando a Consulta @e @Modificar anotações
Leia mais →

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.

Deixe uma resposta

O seu endereço de email não será publicado.