2015-11-27 4 views
2

Я довольно новичок в этих техносах, и мне нужно поле, чтобы понять, как это сделать. У меня есть сущность Employee, и я хочу перечислить их, сделав запрос GET конечной точке. Мне нужно вернуть страницу сотрудников после применения фильтров в поле. В настоящее время работает страница с данными GET, но не мой фильтр.Spring Boot REST WebService + JPA: доступен для просмотра и фильтра

Вот моя конечная точка REST:

@RequestMapping(value = "/employees", 
      method = RequestMethod.GET, 
      produces = MediaType.APPLICATION_JSON_VALUE) 
@Timed 
@Transactional(readOnly = true) 
public ResponseEntity<List<EmployeeDTO>> getAllEmployees(Pageable pageable, String filters) throws URISyntaxException, JSONException { 

     JSONObject sfilters = null; 
     try { 
      sfilters = new JSONObject(filters.trim()); 
     } catch (JSONException e) { 
      e.printStackTrace(); 
     } 

     // I wish this on could works, but still have to update it if we add fields to our Employee entity 
     Page<Employee> page = employeeRepository.findAllByCompanyIdAndFirstnameLikeAndLastnameLike(
      userService.getUserWithAuthorities().getCompany().getId(), 
      sfilters.get("firstname").toString(), 
      sfilters.get("lastname").toString(), 
      pageable); 

     HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/employees"); 
     ResponseEntity<List<EmployeeDTO>> result = new ResponseEntity<>(page.getContent().stream() 
      .map(employeeMapper::employeeToEmployeeDTO) 
      .collect(Collectors.toCollection(LinkedList::new)), headers, HttpStatus.OK); 

     return result; 
} 

NB: Я должен фильтровать больше полей, чем это, но я хочу, чтобы пример как можно четче.

Моего репозиторий метод:

Page<Employee> findAllByCompanyIdAndFirstnameLikeAndLastnameLike(Long idCompany, String firstname, String lastname, Pageable pageable); 

на стороне клиента, он хорошо работает, я посылаю хороший Params для выгружаемых и моего фильтра, чтобы быть преобразован в JSONObject. Но теперь мне нужны предложения о том, как правильно генерировать фильтры динамиков по моему запросу. Мой метод репозитория JPA не работает.

Я пытался использовать предикаты, но это не помогает, поскольку методы терпят неудачу, когда я даю ему Predicate arg. Этот метод, по-видимому, хорош, чтобы проверять элементы по элементам, если один или несколько соответствуют вашему представлению, но не уверены, что они созданы для извлечения набора элементов с динамическим запросом.

EDIT: Я создал класс EmployeeSpecification, реализующий спецификацию, но хочу вернуть список/массив предикатов не только один. Таким образом, метод по умолчанию для переопределения возвращает один Predicate. Как я могу получить множественный предикат от этого объекта?

Благодарим за любой намек, помогает, прошлый опыт делиться.

+0

Тема рассматривается 13 раз. Я должен признать, что вопросы JPA - это не самые популярные предметы. Я проверю документацию и прочитаю кое-что. – Alex

ответ

3

Я узнал, как это сделать с помощью Predicates. Во-первых, я должен использовать метод JPA FindAll в моем хранилище:

Page<Employee> findAll(Specification<Employee> spec, Pageable pageable); 

Затем я создал пользовательский класс, который реализует объект Спецификация Spring загрузочную:

public class EmployeeSpecification implements Specification<Employee> { 

    private final JSONObject criteria; 
    private List<Predicate> filters; 

    public EmployeeSpecification(JSONObject criteria) { 
     this.criteria = criteria; 
    } 

    @Override 
    public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) { 
     Iterator<?> keys = criteria.keys(); 
     List<Predicate> filters = new ArrayList<>(); 

     if (criteria.length() != 0) { 

      while (keys.hasNext()) { 
       String key = (String) keys.next(); 
       String filterValue = null; 

       try { 
        filterValue = criteria.get(key).toString(); 
       } catch (JSONException e) { 
        e.printStackTrace(); 
       } 

       if (filterValue != null) { 
        filters.add(criteriaBuilder.like(criteriaBuilder.upper(root.<String>get(key)), "%" + filterValue.toUpperCase() + "%")); 
       } 
      } 
     } 
     //this is the point : didn't know we could concatenate multiple predicates into one. 
     return criteriaBuilder.and(filters.toArray(new Predicate[filters.size()])); 
    } 
} 

После этого, в мой метод конечной точки WS, мне просто нужно instanciate EmployeeSpecification и до вызов метода JPA findAll, передающий мой объект JSON объекта и мой объект, относящийся к странице:

@RequestMapping(value = "/employees", 
      method = RequestMethod.GET, 
      produces = MediaType.APPLICATION_JSON_VALUE) 
@Timed 
@Transactional(readOnly = true) 
public ResponseEntity<List<EmployeeDTO>> getAllEmployees(Pageable pageable, String filters) throws URISyntaxException, JSONException { 

    JSONObject sfilters = null; 
    try { 
     sfilters = new JSONObject(filters.trim()); 
    } catch (JSONException e) { 
     e.printStackTrace(); 
    } 

    EmployeeSpecification spec = new EmployeeSpecification(sfilters); 

    Page<Employee> page = employeeRepository.findAll(
     spec, 
     pageable); 

    HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/employees"); 
    ResponseEntity<List<EmployeeDTO>> result = new ResponseEntity<>(page.getContent().stream() 
     .map(employeeMapper::employeeToEmployeeDTO) 
     .collect(Collectors.toCollection(LinkedList::new)), headers, HttpStatus.OK); 
    return result; 
} 

Теперь я могу отправлять элементы страницы и фильтры нескольких полей, я могу правильно получать результаты в зависимости от сортировки, количества на страницы, текущей страницы и фильтров по полям. Большое спасибо за помощь;) (lol)

+0

О, черт возьми, я узнал, что я не могу передать аргумент @Param методу, потому что он принимает только тип сортировки и типа страниц. Поэтому я не могу сделать запрос на объединение, добавить к нему спецификацию и элементы страницы. – Alex

+0

Собственно, вы можете сделать запрос соединения с использованием JPA Predicates, используя .join() – Alex

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