[英]JPQL TREAT AS /LEFT OUTER JOIN
我正在嘗試JPA 2.1(eclipselink)中的“TREAT AS”功能,我遇到了JPA的錯誤:
異常描述:ReportQuery結果大小不匹配。 期待[263],但檢索[197]
這是我的JPQL查詢(我將一些部分更改為更明確):
String jpql = "select distinct s, accountAD "
+ "from SheetAccountUser s "
+ "left join fetch s.userTarget target "
+ "left join TREAT(target.accounts AS ADAccount) accountAD ";
ADAccount是AbstractAccount的子類(@Inheritance(strategy = InheritanceType.JOINED)。用戶有一個AbstractAccount列表。
我想用userTarget的AD帳戶選擇工作表。 如果沒有userTarget或userTarget沒有AD帳戶(左連接),我想要null。
問題來自對待操作員。 SQL生成的查詢在AbstractAccount表和ADAccount表之間具有左連接。 這導致每個帳戶類型的targetUser檢索一行。
這是生成的SQL查詢:
SELECT DISTINCT
t0.Id, --etc
t6.Id, t6.name, --etc
t7.userId --etc
FROM sheet t0
LEFT OUTER JOIN user t6 ON (t6.Id = t0.userTargetId),
account t7 LEFT OUTER JOIN ad_account t8 ON ((t8.userId = t7.userId) AND (t8.idApp = t7.idApp))
WHERE (t7.userId = t6.Id) AND (t7.DTYPE = 'ADAccount');
我們可以在帳戶和ad_account之間看到左外連接。 此外,select子句中不存在ad_account表。 (idApp字段是主鍵的一部分,並保持唯一(userId,idApp)約束)。 我不知道這是我的理解或JPA的問題。
感謝你們對我的幫助!
"select distinct s, accountAD "
+ "from SheetAccountUser s "
+ "left join fetch s.userTarget target "
+ "left join target.accounts accountAD where TYPE(accountAD) = ADAccount";
此請求不會返回具有沒有AD帳戶的目標的工作表。
"select distinct s, accountAD "
+ "from SheetAccountUser s "
+ "left join fetch s.userTarget target "
+ "left join target.accounts accounts "
+ " join TREAT(accounts AS ADAccount) accountAD";
這個生成與我的第一個jpql請求相同的SQL並生成Eclipselink錯誤。
如果目標有一個AD帳戶和至少一個其他帳戶類型,我還有一個工作表的多行:一行設置了AD帳戶屬性,另一行設置了空值(這些不同的值阻止了distinct子句,因此DTYPE值也是如此)。
幸運的是,我只需要2個關於AD帳戶的信息:它的存在和一個布爾“停用”。
經過更多的反思,我有了一個想法:
"select u, "
// 0 if line with no target or no ADAccount or with another account type, else 1 (one 1 by sheet/target)
+ "sum( "
+ " case "
+ " when accountAD.desactivated is not null then 1 "
+ " else 0 "
+ " end "
+ ") as ADAccountExists, "
// the target have an AD Account desactivated
+ "sum( "
+ " case "
+ " when compteAD.desactivated = 1 then 1 "
+ " else 0 "
+ " end"
+ ") as ADAccountDesactivated "
+ "from SheetAccountUser s "
+ "left join fetch s.userTarget target "
+ "left join treat(target.accounts as ADAccount) accountAD "
+ "group by s,target " //the group by maintains unicity of the sheets
它工作正常,但它非常難看。 我有一天會跳過另一種方法。
TREAT表達式意味着允許在查詢中訪問子類的參數; 過濾是必要的副產品,但不是主要意圖。 您可能希望查詢“工資> 100k的工人或管理人員數量<10”的人員。 在這種情況下,人員+員工與人員+經理之間的嚴格聯系會妨礙查詢。
TYPE表達式允許您自己控制過濾,以便獲得您正在尋找的嚴格結果。 就像是:
"select distinct s, accountAD "
+ "from SheetAccountUser s "
+ "left join fetch s.userTarget target "
+ "left join target.accounts accountAD where TYPE(accountAD) = ADAccount";
可能更多你需要的東西。 請記住,您需要明確列出您想要包含的任何子類。
如果必須使用Treat來過濾,但希望外部聯接超過target.accounts,請嘗試以下方法:
"select distinct s, accountAD "
+ "from SheetAccountUser s "
+ "left join fetch s.userTarget target "
+ "left join target.accounts accounts "
+ " join TREAT(accounts AS ADAccount) accountAD";
可能會工作,但您可能只想在需要時在where子句中使用TREAT。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.