[英]Efficient JPQL query for retrieving complex entities
我是JPA / JPQL的新手,所以如果這個問題不清楚,請原諒。
我試圖找到一個有效的JQPL查詢,以獲取復雜對象的所有記錄。
(即由多個表表示,具有多個一對多關系 - 請參閱下面的簡化示例):
class ComplexObject {
private Set< SubOject1> so1 ...
.....
@OneToMany(fetch = FetchType.LAZY)
public Set< SubOject1>...
}
class SubObject1 {
private Set< SubOject2> so2 ...
.....
@OneToMany(fetch = FetchType.LAZY)
public Set< SubOject2>...
}
我使用以下JPQL查詢:
select distinct CO
from ComplexObject CO
left join fetch CO.so1 SO1
left join fetch SO1.so2
查詢在無狀態會話上運行,以便獲得DB中當前數據的事實上的快照,該快照與實體管理器分離(因此使用左連接提取)。
不幸的是,我遇到了兩個問題:
由於復雜對象包含so1的多個實例,並且每個so1實例包含so2的多個實例,因此對SQL查詢的基礎轉換會為所有表連接的每一行產生一個特定的選擇查詢 - 這是一個非常浪費的解決方案。 有沒有辦法減少內部選擇查詢的數量? (這似乎是可怕的N + 1查詢問題)。
JPQL查詢在所有表連接的產品上為每個內部SQL查詢返回一個ComplexObject實例 - 這意味着對ComplexObject實例的多個引用。 為什么會在'select distinct'查詢中發生這種情況?
我使用的JPA框架是hibernate,而DB是HyperSQL。
(1)問題與使用p6spy
日志框架有關,該框架打印出來自大型數據庫表的所有結果。 日志記錄格式導致錯誤的假設,即許多查詢正在執行。
在嘗試微調性能時,使用本機查詢似乎沒有比使用JPQL查詢更好的性能。 使用本機查詢還會導致對象類型的結果,這需要后期處理。
您可以使用“查看對象”僅接收所需的列:
StringBuilder sb = new StringBuilder();
sb.append(" SELECT new ").append(ObjectVO.class.getName()).append("(co.someInfo1, co.someInfo2, so1.someInfo )");
sb.append(" FROM ComplexObject co ");
sb.append(" JOIN co.subOject1s so1 ");
sb.append(" LEFT JOIN so1.so2 so2 ");
sb.append(" WHERE so1.id = :idSo1 AND so2 = :someThing");
Query q = em.createQuery(sb.toString());
q.setParameter("idSo1", idSo1);
q.setParameter("someThing", someThing);
List<ObjectVO> listResult = q.getResultList();
ObjectVO類:
public class ObjectVO {
private String info1;
private Long info2;
private String info3;
public PedidoModel(String info1, Long info2, String info3){
this.info1 = info1;
this.info2 = info2;
this.info3 = info3;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.