web-dev-qa-db-fra.com

Données JPA de printemps et paramètres pouvant être nuls

Ma compréhension est que, avec les données Spring JPA, je ne peux pas avoir de méthode de requête pour récupérer toutes les lignes où une colonne est égale à un paramètre de méthode non nul donné et utiliser la même méthode pour récupérer toutes les lignes où cette colonne est NULL lorsque le paramètre de méthode est nul .

Est-ce exact?

Je dois donc distinguer cela dans mon Java et je dois utiliser une méthode de requête distincte demandant explicitement des valeurs nulles, comme dans l'exemple ci-dessous?

// Query methods
List<Something> findByParameter(Parameter parameter);
List<Something> findByParameterIsNull();

...

List<Something> result = new ArrayList<>();

if (parameter == null)
  result = findByParameterIsNull();
else
  result = findByParameter(parameter);

C'est mauvais, si j'ai 4 paramètres qui pourraient être nuls et devraient coder 16 méthodes de requête différentes.

27
Sebastian S.

Vous avez raison.

Une demande a été faite pour prendre en charge une meilleure gestion des paramètres nuls. https://jira.spring.io/browse/DATAJPA-121

Dans votre cas, je vous conseillerais d'écrire l'implémentation de votre référentiel et d'utiliser un CriteriaQuery personnalisé pour gérer votre cas.

Vous pouvez également utiliser l'annotation @ Query avec la syntaxe is null :

@Query("[...] where :parameter is null"
public List<Something> getSomethingWithNullParameter();

[~ # ~] modifier [~ # ~]

Depuis Spring data jpa 2.0, spring prend désormais en charge l'annotation @Nullable. Cela peut être utile pour gérer les paramètres nuls transmis.

De la documentation :

@Nullable - à utiliser sur un paramètre ou une valeur de retour qui peut être nulle.

18
Laurent B

Il semble Query by Example pourrait être ce dont vous avez besoin.

Query by Example est une nouvelle fonctionnalité de Spring Data ( depuis la version Hopper , sortie en avril 2016), qui permet de créer des requêtes dynamiques simples avec un code comme celui-ci

Person person = new Person();                          
person.setFirstname("Dave");                           

ExampleMatcher matcher = ExampleMatcher.matching()     
  .withIncludeNullValues();                        

Example<Person> example = Example.of(person, matcher);

personRepository.count(example);
personRepository.findOne(example);
personRepository.findAll(example);

Méthodes count/findOne/findAll qui prennent une instance de org.springframework.data.domain.Example en tant que paramètre (et certains d'entre eux prennent également des paramètres de tri/pagination) proviennent de org.springframework.data.repository.query.QueryByExampleExecutor<T> interface, qui est étendue par org.springframework.data.jpa.repository.JpaRepository<T, ID extends Serializable> interface.

En bref, toutes les instances JpaRepository ont désormais ces méthodes.

12
mvmn

j'ai trouvé quelque chose ... si vous mettez le paramètre dans la méthode jpa comme ceci

@Param("value") String value,

alors il peut être nul et dans la requête vous aurez cette condition:

(table.value = :value OR :value IS NULL)

si la valeur est nulle, elle renverra automatiquement true et si elle n'est pas nulle, elle recherchera cette valeur dans la table.

5
fvukovic

Aujourd'hui en juin 2018, en consultant https://jira.spring.io/browse/DATAJPA-121 , la requête formera automatiquement is null si votre paramètre est nul.

Je l'ai fait dans mon projet, c'est vrai:

compile group: 'org.springframework.data', name: 'spring-data-jpa', version: '2.0.7.RELEASE'

-

public interface AccountDao extends CrudRepository<T, ID> {

    //this can accept null and it will become isNull
    public List<MyAccount> findByEmail(String email);

}

si le paramètre est nul:

select
        myaccount0_.id as id1_0_,
        myaccount0_.email as email2_0_,
        myaccount0_.password as password3_0_,
        myaccount0_.user_id as user_id4_0_ 
    from
        my_account myaccount0_ 
    where
        myaccount0_.email is null

si le paramètre n'est pas nul:

select
        myaccount0_.id as id1_0_,
        myaccount0_.email as email2_0_,
        myaccount0_.password as password3_0_,
        myaccount0_.user_id as user_id4_0_ 
    from
        my_account myaccount0_ 
    where
        myaccount0_.email=?
11:02:41.623 [qtp1507181879-72] TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [1] as [VARCHAR] - [[email protected]] 

Ensuite, il s'agit d'une question intéressante, certains développeurs souhaitent un meilleur contrôle pour ignorer le paramètre dans la requête s'il est nul, cela est toujours à l'étude dans https://jira.spring.io/browse/DATAJPA-209 .

4
GMsoF

Dans mon cas, membershipNumber est nullable, et je l'ai traité de cette façon. Cela gérera tous les cas où table.membershipNumber est également nul.

      @Query(value = "SELECT pr FROM ABCTable pr " +
            "WHERE LOWER(pr.xyz) = LOWER(:xyz) " +
            "and LOWER(pr.subscriptionReference) = LOWER(:subscriptionReference) " +
            "and pr.billId = :billId " +
            "and ((pr.membershipNumber = :membershipId) or (pr.membershipNumber = null and :membershipId = null))")
    List<PaymentRequest> getSomething (@Param("xyz") String xyz,
                                                 @Param("subscriptionReference") String subscriptionReference,
                                                 @Param("billId") Integer billId,
                                                 @Param("membershipId") String membershipNumber);

1