2016-08-26 8 views
7

Ich habe einen Filter in meiner Webapp, so dass nach Fahrzeugtyp, Marke, Kraftstoff, Zustand und Stadt suchen, aber alle diese Filter sind optional.Spring Boot Dynamische Abfrage

Wie kann ich dies mithilfe von Repositories tun.

Controller-Klasse

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

Service-Klasse

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 
} 

ich noch nichts umgesetzt haben, weil ich verstehe nicht, wie kann ich diese Filter zu tun.

Fahrzeugklasse

@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 

Die vehicletype und Marke von einem anderen Tisch ... Ich bin portugiesisch, ich den Code auf Englisch übersetzt habe ...

wenn es passiert, was ich tun muss?

+0

Wenn Sie über Repositories sprechen, meinen Sie die JPA-Repositorys für Spring-Daten? Wenn das der Fall ist, dann denke ich, dass diese Frage ein Duplikat für https: // stackoverflow ist.com/questions/39015244/ist-es-möglich-zu-build-customized-query-bei laufzeit-im-sprung-boot/39015944 # 39015944 – g00glen00b

+0

eine kurze Anmerkung, die Sie '@ matrixvariable' auch verwenden können – emotionlessbananas

Antwort

5

Sie können die Spezifikations-API von Spring verwenden, die ein Wrapper um die Kriterien-API von JPA ist, mit der Sie dynamischere Abfragen erstellen können.

In Ihrem Fall gehe ich davon aus, dass Sie eine Vehicle Einheit haben, die ein Feld hat brand, year, state, city, ....

Wenn das der Fall ist, können Sie die folgende Spezifikation schreiben:

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, ... 
} 

Wenn Sie tun müssen, um ein (zum Beispiel, wenn Sie Vehicle.city.id abrufen möchten) anschließen, dann können Sie verwenden:

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

nun in ihrem Repository Sie müssen sicherstellen, dass Sie von JpaSpecificationExecutor erweitern, zum Beispiel:

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

} 

Durch die Erweiterung von dieser Schnittstelle aus erhalten Sie Zugriff auf die findAll(Specification spec)-Methode, mit der Sie Spezifikationen ausführen können. Wenn Sie mehrere Spezifikationen kombinieren müssen (ein Filter = eine Spezifikation in der Regel), können Sie die Specifications Klasse verwenden:

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

Im Codebeispiel oben I für Specifications.where und für VehicleSpecifications.* statische Import bin mit es aussehen zu lassen ein bisschen mehr deklarativ.

Sie müssen nicht if() Anweisungen hier schreiben, weil wir sie bereits in VehicleSpecifications.withCity() geschrieben haben. Solange Sie null von diesen Methoden zurückgeben, werden sie von Spring ignoriert.

+0

Unable to Finde Attribut mit dem gegebenen Namen [Fahrzeugtyp] auf diesem ManagedType, was muss ich tun? –

+0

@FelipeA. Hast du ein Feld namens "Fahrzeugtyp" auf "Fahrzeug"? – g00glen00b

+0

Der Fahrzeugtyp, Marke, Stadt und Staat ist von einem anderen Tisch ... wenn es passiert, was ich tun muss? –

Verwandte Themen