0

所以我有2層休眠的POJO如下標準查詢

class Owner{ 

Integer id; 
String name; 
Integer age; 
String address; 

/* 
    Many more fields here 
*/ 

Set<Cat> cats; 

} 

class Cat{ 
Owner owner; //referenced from Owner.id 
String color; 
} 

我使用的標準如下查詢主表 -

Criteria criteria = session.createCriteria(Owner.class); 
criteria.createAlias("cats", "cats"); 

ProjectionList projList = Projections.projectionList(); 
projList.add(Projections.property("id"), "id"); 
projList.add(Projections.property("name"), "name"); 
projList.add(Projections.property("cats"), "cats"); 

criteria.setProjection(projList); 
criteria.setResultTransformer(Transformers.aliasToBean(Owner.class)); 
List<Owner> owners = (List<Owner>)criteria.list(); 

我需要業主的名單與他們各自的貓居住。

如果我不添加預測(這相當於選擇*),我得到爲每個所有者填充的貓。但select *會非常昂貴,因爲所有者表具有超過60列,並且具有與其他許多表的外鍵關係。我想要使​​用投影來僅選擇所需的列,以便查詢執行得更快。如果我添加預測和/或別名,我得到的業主,但沒有貓(每個所有者的貓爲空)。

我已經搜索了很多解決方案,嘗試了所有方法在條件中創建別名和投影,甚至嘗試使用自定義ResultTransformers。當我使用預測時,這些似乎都不起作用。

其他人面臨類似的問題?有任何想法嗎?

回答

1

這個問題不是很清楚。你說如果你不添加預測,你會得到爲每個所有者填充的貓。但是在投影列表中,您將貓添加爲投影場,所以基本上您需要結果中的貓,對吧?如果是這樣,使用預測的唯一理由是不包括業主的年齡和地址?

作爲一個建議,請嘗試思考你從查詢中獲得的SQL是什麼?你想是這樣的:

select id, name from owner; 

或者是這樣的:

select o.id, o.namer, c.color from owner o join cat c on o.id = c.owner_id; 

我想是你想獲得再怎麼做,在休眠首先應該做的事情很重要。

編輯: 好吧,我想我明白你現在想完成什麼。但我不認爲你能夠像你想要的那樣去做 - 直接提取也填充了貓的Owner實體。這是因爲默認情況下,通過應用投影,結果不會是Owner實體列表,而是Object []的列表。

例如,假設您想要所有者ID,所有者名稱和貓的顏色。你的預測看起來是這樣的:

projList.add(Projections.property("id"), "id"); 
projList.add(Projections.property("name"), "name"); 
projList.add(Projections.property("cats.color"), "catsColor"); 

和生成的sql將與上面用cat join相似。

然後您可以應用結果轉換器。這是從接口中的方法:

public Object transformTuple(Object[] tuple, String[] aliases); 
public List transformList(List collection); 

現在第一個將被要求在結果列表中的每個對象,如果你想返回的每一行映射到一個對象,但如果你願意,你可以處理整個列出併合並結果。也許你會這樣做,因爲例如,您將擁有一個擁有貓顏色列表或catDtos列表的OwnerDto,並且可以將結果轉換爲此樹狀結構。要注意的是由於加入你的結果會是這樣的(假設你有2個業主,每一個與貓):

tuple: [1, 'Owner1', 'white'] - aliases ['id', 'name', 'catsColor'] 
tuple: [1, 'Owner1', 'black'] - aliases ['id', 'name', 'catsColor'] 
tuple: [2, 'Owner2', 'yellow'] - aliases ['id', 'name', 'catsColor'] 
.. etc 

這就是爲什麼你會喜歡它結合了這個原始列表的東西,結果變壓器更合適。

這個想法是,預測是非常有用的,只獲取您需要的數據和性能增益,但您現在必須返回的結果不會是實體 - 您必須準備好並使用它們。將DTO中的投影數據進行轉換並使用它們更有意義,因爲這就是爲什麼您首先使用投影 - 不檢索整個實體,對嗎?

我們希望這能解決問題,如果您需要更多的建議,請發表評論。

+0

感謝您的回覆。 我更新了問題,以便更清楚。我需要各自的貓主人名單。我正在使用預測,以避免40多列與許多人再次有其他表的外鍵關係。預測將有助於大幅縮短查詢執行時間。 –

+0

編輯答案包括一個可能的解決方案,讓我知道你在想什麼。 –