2016-08-26 3 views
7

У меня есть фильтр в моем webapp, позволяющий искать по типу транспортного средства, марке, топливу, штату и городу, но все эти фильтры являются необязательными.Весенняя обувь Динамический запрос

Как это сделать, используя репозитории.

класс контроллера

@RequestMapping(value = "/vehicle/search", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) 
public Iterable<Veiculo> findBySearch(@RequestParam Long vehicletype, @RequestParam Long brand, 
     @RequestParam Long model, @RequestParam Long year, 
     @RequestParam Long state, @RequestParam Long city) { 
    return veiculoService.findBySearch(vehicletype, brand, model, year, state, city); 
} 

Класс обслуживания

public Iterable<Vehicle> findBySearch(Long vehicletype, Long brand, Long model, Long year, Long state, Long city) { 
    if(vehicletype != null){ 
     //TODO: filter by vehicletype 
    } 
    if(brand != null){ 
     //TODO: filter by brand 
    } 
    if(model != null){ 
     //TODO: filter by model 
    } 

    //OTHER FILTERS 
    return //TODO: Return my repository with personal query based on filter 
} 

Я не реализовали еще ничего, потому что я не понимаю, как я могу сделать этот фильтр.

Класс автомобиля

@Entity 
@Table(name = "tb_veiculo") 
public class Veiculo { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "id", nullable = false) 
    private Long id; 

    @ManyToMany(cascade = CascadeType.ALL) 
    @JoinTable(name = "veiculo_opcionais", 
    joinColumns = @JoinColumn(name = "veiculo_id", referencedColumnName = "id"), 
    inverseJoinColumns = @JoinColumn(name = "opcional_id", referencedColumnName = "id")) 
    private List<Opcional> opcionais; 

    @JsonIgnore 
    @OneToMany(mappedBy = "veiculo", fetch = FetchType.LAZY, cascade = CascadeType.ALL) 
    private List<VeiculoImagem> veiculoImagens; 

    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) 
    @JoinColumn(name = "cambio_id", foreignKey = @ForeignKey(name = "fk_cambio")) 
    private Cambio cambio; 

    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) 
    @JoinColumn(name = "combustivel_id", foreignKey = @ForeignKey(name = "fk_combustivel")) 
    private Combustivel combustivel; 

    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) 
    @JoinColumn(name = "cor_id", foreignKey = @ForeignKey(name = "fk_cor")) 
    private Cor cor; 

    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) 
    @JoinColumn(name = "modelo_id", foreignKey = @ForeignKey(name = "fk_modelo")) 
    private Modelo modelo; 

    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) 
    @JoinColumn(name = "usuario_id", foreignKey = @ForeignKey(name = "fk_usuario")) 
    private Usuario usuario; 

    @Column(name = "anoFabricacao", nullable = false) 
    private int anoFabricacao; 

    @Column(name = "anoModelo", nullable = false) 
    private int anoModelo; 

    @Column(name = "quilometragem", nullable = false) 
    private int quilometragem; 

    @Column(name = "porta", nullable = false) 
    private int porta; 

    @Column(name = "valor", nullable = false) 
    private double valor; 

    //GETTERS AND SETTERS 

vehicletype и бренд это из другой таблицы ... Я португальский, я переводил код на английский ...

Когда это произойдет, что мне нужно сделать?

+0

Если вы говорите о репозиториях, вы имеете в виду репозитории JPA данных Spring? Если это так, то я думаю, что этот вопрос является дубликат https: // stackoverflow.com/questions/39015244/is-it-possible-to-build-customized-query-at-run-time-in-spring-boot/39015944 # 39015944 – g00glen00b

+0

короткую заметку, вы можете также использовать '@ matrixvariable' – emotionlessbananas

ответ

5

Вы можете использовать API спецификации из Spring, который является оболочкой API критериев из JPA, что позволяет создавать более динамические запросы.

В вашем случае я предполагаю, что у вас есть Vehicle юридического лица, которое имеет поле brand, year, state, city ....

Если это так, то вы можете написать следующую спецификацию:

public class VehicleSpecifications { 
    public static Specification<Vehicle> withCity(Long city) { 
     if (city == null) { 
      return null; 
     } else { 
      // Specification using Java 8 lambdas 
      return (root, query, cb) -> cb.equal(root.get("city"), city); 
     } 
    } 

    // TODO: Implement withModel, withVehicleType, withBrand, ... 
} 

Если вы должны сделать присоединиться (к примеру, если вы хотите получить Vehicle.city.id), то вы можете использовать:

return (root, query, cb) -> cb.equal(root.join("city").get("id"), city); 

Теперь у вас хранилище, вы должны убедиться, что вы простираться от JpaSpecificationExecutor, например:

public interface VehicleRepository extends JpaRepository<Vehicle, Long>, JpaSpecificationExecutor<Vehicle> { 

} 

Расширяясь от этого интерфейса, вы получите доступ к методу findAll(Specification spec), который позволяет выполнять спецификации. Если вам нужно объединить несколько спецификаций (один фильтр = одна спецификация обычно), вы можете использовать Specifications класс:

repository.findAll(where(withCity(city)) 
    .and(withBrand(brand)) 
    .and(withModel(model)) 
    .and(withVehicleType(type)) 
    .and(withYear(year)) 
    .and(withState(state))); 

В примере кода выше, я использую статический импорт для Specifications.where и VehicleSpecifications.*, чтобы сделать его немного более декларативным.

Здесь нет необходимости писать заявления if(), потому что мы уже писали их в VehicleSpecifications.withCity(). Пока вы возвращаете null из этих методов, они будут проигнорированы весной.

+0

Невозможно найдите Атрибут с данным именем [vehicletype] в этом ManagedType, что мне нужно сделать? –

+0

@FelipeA. у вас есть поле под названием «vehicletype» на «Vehicle»? – g00glen00b

+0

Тип транспортного средства, бренд, город и указать его из другого стола ... когда это произойдет, что мне нужно сделать? –

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