我正在尝试使用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');

我们可以看到account和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";

此请求不会返回没有广告客户目标的工作表。
 "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值也会如此) )。

幸运的是,我只需要有关AD帐户的2条信息:它的存在和一个布尔“停用”信息。

经过更多的反射Reflection ,我有了一个主意:
    "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

它工作正常,但是非常丑陋。我希望有一天能找到另一种方法。

关于java - JPQL TREAT AS/左外连接,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29100905/

10-13 03:04