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);
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);
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
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);