簡體   English   中英

JPQL - 使用過濾器連接查詢

[英]JPQL - JOIN query with filter

我有實體:

第一的

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

我想從我的數據庫中獲取結果,其中包含每個對象技術中的列表我有列表 technicStatusList = new ArrayList<>(),我希望在其中只有一個值為 isActive=true 的 TechnicStatus。

為此,我正確的 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個選擇。 如果您只對狀態為 Active 的 TechnicalStatus 感興趣,那么您可以在關聯上使用不可移植的、Hibernate 特定的@Where子句。

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

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

否則,您所做的只是從查詢方法返回一個技術狀態列表,這不是您想要的,而是您所擁有的。

無法在查詢條件中過濾相關集合。 您可以通過在 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);
}

我注意到的另一件事:

使用 join 時不要on t.id = ts.technic.id使用。 JPA 將在您編寫時創建正確的本機 SQL: join TechnicStatus ts WHERE ...

使用 join fetch 應該可以解決這個問題,這將迫使查詢一次急切地運行,並且只帶回與 where 子句匹配的記錄。 所以你的查詢是:

TypedQuery<Technic> query = em.createQuery("Select t from Technic t join fetch TechnicStatus ts 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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM