[英]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.