À l'aide de Spring Data JPA, puis-je effectuer un 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 à ceci:
@Entity
public class Person {
private String firstName;
private String lastName;
private boolean employed;
private LocalDate dob;
...
}
Je pourrais trouver toutes les personnes employées portant le nom de famille Smith nées le 1 er 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);
Les données de printemps reposent sur JPA et EntityManager, et non sur Hibernate et Session. Par conséquent, findByExample n'est pas prêt à l'emploi. Vous pouvez utiliser la création automatique de requête de données de printemps et écrire une méthode dans votre référentiel avec la signature suivante:
List<Person> findByEmployedAndLastNameAndDob(boolean employed, String lastName, LocalDate dob);
C'est maintenant possible avec Spring Data. Départ 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 requête par exemple. Voici une classe PersonSpec
qui implémente Specification
et nécessite un "exemple" pour pouvoir configurer le Predicate
renvoyé 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);