JPQL - JOIN запрос с фильтром - PullRequest
0 голосов
/ 28 февраля 2019

У меня есть объекты:

Первый

@Entity
@Getter
@Setter
@NoArgsConstructor
public class Technic implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String gosNumber;

    private String invNumber;

    private String shassisNumber;

    private String engineNumber;

    @Column(length = 100)
    private String yearOfMake;

    @ManyToOne
    private Farm farm;

    @JsonManagedReference
    @ManyToOne
    private TechGroup techGroup;

    @JsonManagedReference
    @ManyToOne
    private TechType techType;

    @JsonManagedReference
    @ManyToOne
    private TechMark techMark;

    @JsonIgnore
    @CreationTimestamp
    @Column(name = "creation_date", updatable = false)
    private LocalDateTime createdDate;

    @JsonIgnore
    @Column(name = "updated_date")
    @UpdateTimestamp
    private LocalDateTime updatedDate;

    @JsonIgnore
    @Column(columnDefinition = "Bool default false")
    private Boolean isDel;


    @JsonManagedReference
    @OneToMany(mappedBy = "technic")
    private List<TechnicStatus> technicStatusList = new ArrayList<>();

    public List<TechnicStatus> getTechnicStatusList() {
        return technicStatusList;
    }

    public void setTechnicStatus(TechnicStatus technicStatus) {
        this.technicStatusList = new ArrayList<>();
        this.technicStatusList.add(technicStatus);
    }

Второй:

@Entity
@Getter
@Setter
@NoArgsConstructor
public class TechnicStatus implements Serializable  {



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

    @JsonBackReference
    @ManyToOne
    private Technic technic;

    @JsonManagedReference
    @ManyToOne
    private Status status;

    private Boolean isGarantia;

    private Boolean isLizing;

    private LocalDate visitedDate;

    private LocalDate notWorkDate;

    private String description;

    @JsonIgnore
    private boolean isActive;

    @JsonIgnore
    @CreationTimestamp
    @Column(name = "creation_date", updatable = false)
    private LocalDateTime createdDate;
}

Я хочуполучить результат из моей базы данных, которая содержит список в каждом объекте Technic у меня есть список technicStatusList = new ArrayList <> (), в котором я хочу, чтобы TechnicStatus только со значением isActive = true.

Для этого я правтот же JPQL-запрос:

TypedQuery<Technic> query = em.createQuery("Select t  from Technic t join TechnicStatus ts on t.id = ts.technic.id where t.isDel=false and ts.isActive=true and t.farm.id=:farmId order by t.techGroup.name, t.techType.name, t.techMark.name", Technic.class);

Но получить результат, содержащий TechnicStatus, который возвращает TechnicStatus с истиной и ложью (TechnicStatus.isActive = true, TechnicStatus.isActive = false).

Я хочучтобы получить результат как этот собственный запрос:

SELECT 
    *
FROM
    technic
        JOIN
    technic_status ON technic.id = technic_status.technic_id
WHERE
    technic.is_del = FALSE
        AND technic_status.is_active = TRUE
        AND technic.farm_id = 1722

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

Невозможно отфильтровать связанную коллекцию в условиях запроса.Вы можете получить его, выбрав select на TechnicalStatus: select ts from TechnicStatus ts join Technic t where ...

Другая вещь, которую я заметил:

При добавлении нового вы переписываете список существующих статусов:

public void setTechnicStatus(TechnicStatus technicStatus) {
     this.technicStatusList = new ArrayList<>();
     this.technicStatusList.add(technicStatus);
}

Инициализируйте technicStatusList в объявлении поля.Метод в технике для добавления:

public void addTechnicStatus(TechnicStatus technicStatus) {
    getTechnicStatusList().add(technicStatus);
    technicStatus.setTechnic(this);
}

Другая вещь, которую я заметил:

При использовании объединения не используйте on t.id = ts.technic.id.JPA создаст правильный нативный SQL только тогда, когда вы напишите: join TechnicStatus ts WHERE ...

0 голосов
/ 28 февраля 2019

Список TechnicalStatus, связанный с Техникой, всегда будет полным списком, как определено вашими сопоставлениями.

По существу, у вас есть 2 варианта.Если вы только когда-либо заинтересованы в TechnicalStatus со статусом Active, тогда вы можете использовать непереносимое, специфичное для Hibernate условие @Where для ассоциации.

@JsonManagedReference
@OneToMany(mappedBy = "technic")
@Where("active = 1")
private List<TechnicStatus> technicStatusList = new ArrayList<>();

https://dzone.com/articles/hibernate-where-clause

В противном случае все, что вы делаете, это возвращаете список TechnicalStatus из метода запроса, который не тот, который вы хотите, а все, что у вас есть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...