web-dev-qa-db-fra.com

Comment initialiser la spécification de Spring Data JPA?

J'ai une méthode qui fait une recherche avec des filtres, donc j'utilise spécification pour construire une requête dynamique:

public Page<Foo> searchFoo(@NotNull Foo probe, @NotNull Pageable pageable) {

        Specification<Foo> spec = Specification.where(null);  // is this ok?

        if(probe.getName() != null) {
            spec.and(FooSpecs.containsName(probe.getName()));
        }
        if(probe.getState() != null) {
            spec.and(FooSpecs.hasState(probe.getState()));
        }
        //and so on...

        return fooRepo.findAll(spec, pageable);
}

Il y a la possibilité qu'aucun filtre ne soit spécifié, donc je listerais tout sans filtrer. Donc, ayant cela à l'esprit, comment dois-je initialiser spec? Pour le moment, le code ci-dessus ne fonctionne pas car il me renvoie toujours le même résultat: tous les registres de la table, aucun filtrage n'a été appliqué bien que des opérations and aient été effectuées.

FooSpecs:

public class PrescriptionSpecs {

    public static Specification<Prescription> containsCode(String code) {
        return (root, criteriaQuery, criteriaBuilder) ->
            criteriaBuilder.like(root.get(Prescription_.code), "%" + code + "%");
    }

    // some methods matching objects...
    public static Specification<Prescription> hasContractor(Contractor contractor) {
        return (root, criteriaQuery, criteriaBuilder) ->
            criteriaBuilder.equal(root.get(Prescription_.contractor), contractor);
    }
    //... also some methods that access nested objects, not sure about this
    public static Specification<Prescription> containsUserCode(String userCode) {
        return (root, criteriaQuery, criteriaBuilder) ->
            criteriaBuilder.like(root.get(Prescription_.user).get(User_.code), "%" + userCode + "%");
    }
}
12
anat0lius

Specification.where(null) fonctionne très bien. Il est annoté de @Nullable et l'implémentation gère les valeurs null comme il se doit.

Le problème est que vous utilisez la méthode and comme si elle modifierait la Specification, mais elle en crée une nouvelle. Vous devez donc utiliser

spec = spec.and( ... );
14
Jens Schauder