Dados de Primavera JPA e Parâmetros Nulos

Dados de Primavera JPA e Parâmetros Nulos

1. Visão geral

Neste artigo, mostraremos as maneiras de lidar com os parâmetrosnull emSpring Data JPA.

Em alguns casos, quando buscamos registros pelos parâmetroswe want to find rows with null as the field value. Outras vezes, podemos querer ignorarnulleskip that field in our query.

Abaixo, mostraremos como implementar cada um deles.

2. Exemplo rápido

Digamos que temos uma entidadeCustomer:

@Entity
public class Customer {

    @Id
    @GeneratedValue
    private long id;
    private String name;
    private String email;

    public Customer(String name, String email) {
        this.name = name;
        this.email = email;
    }

    // getters/setters

}

Além disso, temos um repositório JPA:

public interface CustomerRepository extends JpaRepository {

   // method1
   // method2
}

Queremos pesquisar clientes pornameeemail.

Para este propósito, vamos escrever dois métodos que tratam os parâmetros denull de forma diferente.

3. Maneiras de lidar com os parâmetros deNull

Em primeiro lugar, criaremos um método que interpreta os valoresnull dos parâmetros comoIS NULL e, em seguida, criaremos um método que ignora os parâmetrosnull e os exclui da cláusula WHERE.

3.1. IS NULL Consulta

O primeiro método é muito simples de criar porque os parâmetrosnull nos métodos de consulta são interpretados comoIS NULL por padrão.

Vamos criar o método:

List findByNameAndEmail(String name, String email);

Agora, se passarmos um e-mailnull, o JPQL gerado incluirá a condiçãoIS NULL:

customer0_.email is null

Para demonstrar isso, vamos criar um teste.

Primeiro, vamos adicionar alguns clientes ao repositório:

@Before
public void before() {
    entityManager.persist(new Customer("A", "[email protected]"));
    entityManager.persist(new Customer("D", null));
    entityManager.persist(new Customer("D", "[email protected]"));
}

Agora vamos passar“D” como o valor do parâmetroname enull como o valor do parâmetroemail para nosso método de consulta. Podemos ver que exatamente um cliente será encontrado:

List customers = repository.findByNameAndEmail("D", null);

assertEquals(1, customers.size());

Customer actual = customers.get(0);

assertEquals(null, actual.getEmail());
assertEquals("D", actual.getName());

3.2. Evite o parâmetronull com métodos alternativos

Às vezes, queremos ignorar alguns parâmetros e não incluir seus campos correspondentes na cláusulaWHERE.

Podemos adicionar mais métodos de consulta ao nosso repositório. Por exemplo, para ignoraremail, podemos adicionar um método que aceita apenasname:

 List findByName(String name);

Mas essa maneira de ignorar uma de nossas colunas é reduzida em escala à medida que o número aumenta, pois teríamos que adicionar muitos métodos para obter todas as combinações.

3.3. Ignorando os parâmetros denull usando a anotação@Query

Podemos evitar a criação de métodos adicionais usando a anotação@Query e adicionando uma pequena complicação à instrução JPQL:

@Query("SELECT c FROM Customer c WHERE (:name is null or c.name = :name) and (:email is null"
  + " or c.email = :email)")
List findCustomerByNameAndEmail(@Param("name") String name, @Param("email") String email);

Observe que se o parâmetro:email fornull:

:email is null or s.email = :email

Então, a cláusula é sempretrue e, portanto, não influencia toda a cláusulaWHERE.

Vamos nos certificar de que isso funcione:

List customers = repository.findCustomerByNameAndEmail("D", null);

assertEquals(2, customers.size());

Encontramos dois clientes cujo nome é“D” ignorando seus e-mails.

A cláusula JPQL WHERE gerada se parece com isso:

where (? is null or customer0_.name=?) and (? is null or customer0_.email=?)

Com este método, estamos confiando no servidor de banco de dados para reconhecer a cláusula sobre nosso parâmetro de consulta sernulle otimizar o plano de execução da consulta para que não tenha uma sobrecarga de desempenho significativa. Para algumas consultas ou servidores de banco de dados, especialmente envolvendo uma enorme varredura de tabela, pode haver uma sobrecarga de desempenho.

4. Conclusão

Demonstramos como Spring Data JPA interpreta parâmetrosnull em métodos de consulta e mostramos como alterar o comportamento padrão.

Talvez no futuro, seremos capazes de especificar como interpretar os parâmetrosnull usando a anotação@NullMeans. Observe que é um recurso proposto no momento e ainda está sendo considerado.

Para resumir, existem duas maneiras principais de interpretar os parâmetrosnull, e ambos seriam fornecidos pela anotação@NullMeans proposta:

  • IS (is null) – a opção padrão demonstrada na seção 3.1.

  • IGNORED (excluir um parâmetronull da cláusulaWHERE) - obtido por métodos de consulta extras (seção 3.2.) ou usando uma solução alternativa (seção 3.3.)

Como de costume, o código-fonte completo está disponívelover on GitHub.