2014-12-23 3 views
19

Использование Spring Data JPA можно сделать query by example, где конкретный экземпляр объекта используется в качестве критериев поиска?Весенние данные JPA: запрос по примеру?

Например (не каламбур), если у меня есть Person сущность, которая выглядит как:

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

я мог бы найти всех работающих лиц с фамилией Смит родился 1 января 1977 года с примером :

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

Ваши вопросы не ясны. Что именно вы ищете? –

+2

Нет, вы не можете, поскольку это ограничено спящим режимом, Spring Data предназначена для JPA. Вы всегда можете создать «Спецификацию» и выполнить то, что вы могли бы использовать, чтобы сделать что-то подобное. –

ответ

7

Spring данные опираются на вершине JPA и EntityManager, а не спящий режим и Session, и как таковая не имеет findByExample из коробки. Вы можете использовать автоматические создание запросов весной данных и написать метод в вашем хранилище со следующей подписью:

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

JPA! = Hibernate. Имеет смысл. Я думаю, что это маршрут «Спецификация», как упоминалось в @M. Deinum - это способ пойти сюда, поскольку я хотел бы иметь возможность выполнять больше специальных запросов. –

+1

Вы можете ознакомиться с примерами здесь http://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/. Он может служить вашим потребностям –

+0

Я открыл [DATAJPA-844] (https://jira.spring.io/browse/DATAJPA-844), чтобы запросить эту функцию в Spring Data JPA. Похоже, что это на их дорожной карте! –

19

Использование Specification интерфейса Весны Дейты я был в состоянии приблизить использование запроса, например. Вот PersonSpec класс, который реализует Specification и требует «пример» лицо в порядке, чтобы настроить Predicate, возвращаемые 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])); 
    } 
} 

Репозиторий просто: пример

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

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

Использование:

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

Хорошо, но все же мне нужно создать класс реализации для каждого Запроса, который я хочу написать. –

+1

Откуда у Person_? –

+0

Person_ - это статический метамодель класса – fyrite

36

Это возможно с использованием данных Spring. Проверьте 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); 

Обратите внимание, что это требует очень последние версии 2016

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

см https://github.com/paulvi/com.example.spring.findbyexample

+0

wow, that hot! Ответ получил 5 голосов в день –

+0

Как насчет более сложного домена. Я имею в виду, когда у нас есть ассоциации, как я могу использовать пример? Есть идеи ? –

+1

Для более сложного домена я в конечном итоге использовал QueryDSL с Spring Data JPA. Немного научился и обнимал голову, но в итоге мы фактически переработали нашу базу кода и полностью исключили использование примера. –

Смежные вопросы