Spring Data JPA: requête par exemple?

En utilisant Spring Data JPA puis-je faire une requête par exemple où une instance d'entité particulière est utilisée comme critère de recherche?

Par exemple (sans jeu de mots), si j'ai une entité Person qui ressemble à:

@Entity
public class Person {
  private String firstName;
  private String lastName;
  private boolean employed;
  private LocalDate dob;
  ...
}

J'ai pu trouver toutes les personnes employées avec un nom de famille de Smith né le 1er janvier 1977 avec un exemple:

Person example = new Person();
example.setEmployed(true);
example.setLastName("Smith");
example.setDob(LocalDate.of(1977, Month.JANUARY, 1));
List<Person> foundPersons = personRepository.findByExample(example);
23
demandé sur mp911de 2014-12-23 22:32:00

3 réponses

Spring data repose sur JPA et EntityManager, pas Hibernate et Session, et en tant que tel, vous n'avez pas findByExample hors de la boîte. Vous pouvez utiliser la création automatique de requête spring data et écrire une méthode dans votre référentiel avec la signature suivante:

List<Person> findByEmployedAndLastNameAndDob(boolean employed, String lastName, LocalDate dob);
9
répondu David Rabinowitz 2015-01-14 08:59:18

Ceci est maintenant possible avec les données de printemps. Découvrez http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#query-by-example

Person person = new Person();                         
person.setLastname("Smith");                          
Example<Person> example = Example.of(person);
List<Person> results = personRepository.findAll(example);

Notez que cela nécessite des versions 2016 très récentes

    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-jpa</artifactId>
        <version>1.10.1.RELEASE</version>       
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-commons</artifactId>
        <version>1.12.1.RELEASE</version>
    </dependency>

Voir https://github.com/paulvi/com.example.spring.findbyexample

43
répondu Adam Erstelle 2016-06-08 12:13:45

En utilisant l'interface Specification de Spring data, j'ai pu approximer l'utilisation de la requête par exemple. Voici une classe PersonSpec qui implémente Specification et nécessite une personne "example" afin de configurer le Predicate retourné par le Specification:

public class PersonSpec implements Specification<Person> {

  private final Person example;

  public PersonSpec(Person example) {
    this.example = example;
  }

  @Override
  public Predicate toPredicate(Root<Person> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
    List<Predicate> predicates = new ArrayList<>();

    if (StringUtils.isNotBlank(example.getLastName())) {
      predicates.add(cb.like(cb.lower(root.get(Person_.lastName)), example.getLastName().toLowerCase() + "%"));
    }

    if (StringUtils.isNotBlank(example.getFirstName())) {
      predicates.add(cb.like(cb.lower(root.get(Person_.firstName)), example.getFirstName().toLowerCase() + "%"));
    }

    if (example.getEmployed() != null) {
      predicates.add(cb.equal(root.get(Person_.employed), example.getEmployed()));
    }

    if (example.getDob() != null) {
      predicates.add(cb.equal(root.get(Person_.dob), example.getDob()));
    }

    return andTogether(predicates, cb);
  }

  private Predicate andTogether(List<Predicate> predicates, CriteriaBuilder cb) {
    return cb.and(predicates.toArray(new Predicate[0]));
  }
}

Le référentiel est simplement:

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

public interface PersonRepository extends JpaRepository<Person, Long>, JpaSpecificationExecutor {}

Exemple d'Utilisation:

Person example = new Person();
example.setLastName("James");
example.setEmployed(true);
PersonSpec personSpec = new PersonSpec(example);
List<Person> persons = personRepository.findAll(personSpec);
25
répondu Brice Roncace 2015-01-06 04:07:26