wake-up-neo.com

Spring Data JPA: Abfrage anhand eines Beispiels?

Kann ich mit Spring Data JPA ein Abfrage anhand eines Beispiels ausführen, wobei eine bestimmte Entitätsinstanz als Suchkriterium verwendet wird?

Zum Beispiel (kein Wortspiel beabsichtigt), wenn ich eine Person -Entität habe, die wie folgt aussieht:

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

Ich konnte alle am 1. Januar 1977 geborenen Erwerbstätigen mit dem Nachnamen Smith anhand eines Beispiels finden:

Person example = new Person();
example.setEmployed(true);
example.setLastName("Smith");
example.setDob(LocalDate.of(1977, Month.JANUARY, 1));
List<Person> foundPersons = personRepository.findByExample(example);
36
Brice Roncace

Spring-Daten basieren auf JPA und EntityManager, nicht auf Ruhezustand und Sitzung, und daher ist findByExample nicht sofort einsatzbereit. Sie können die automatische Abfrageerstellung von spring data verwenden und eine Methode mit der folgenden Signatur in Ihr Repository schreiben:

List<Person> findByEmployedAndLastNameAndDob(boolean employed, String lastName, LocalDate dob);
11

Dies ist jetzt mit Spring Data möglich. Check out 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);

Beachten Sie, dass hierfür die neuesten Versionen von 2016 erforderlich sind

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

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

63
Adam Erstelle

Unter Verwendung der Specification -Schnittstelle von Spring Data konnte ich die Verwendung der Abfrage anhand eines Beispiels approximieren. Hier ist eine PersonSpec -Klasse, die Specification implementiert und eine "Beispiel" -Person benötigt, um das von Predicate zurückgegebene Specification einzurichten:

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

Das Repository ist einfach:

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

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

Anwendungsbeispiel:

Person example = new Person();
example.setLastName("James");
example.setEmployed(true);
PersonSpec personSpec = new PersonSpec(example);
List<Person> persons = personRepository.findAll(personSpec);
26
Brice Roncace