JPA/JPQL: AS identifier disallowed in SELECT clause

对着背影说爱祢 提交于 2019-12-12 18:16:52

问题


I have a pretty complex JPQL query of the form

  SELECT NEW com.domain.project.view.StandingsStatLine(
      ro.id                                                                                                 AS rid
    , cl.name                                                                                               AS team
    , te.ordinalNbr + 1                                                                                     AS nr
    , pa.wasWithdrawn                                                                                       AS wd

    , SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore IS NOT NULL THEN 1 ELSE 0 END)                                           AS g
    , SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore > sca.finalScore THEN 1 ELSE 0 END)                                      AS w
    , SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore < sca.finalScore THEN 1 ELSE 0 END)                                      AS l
    , SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore = 20 AND sca.finalScore =  0 THEN 1 ELSE 0 END)                          AS wbr
    , SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore =  0 AND sca.finalScore = 20 THEN 1 ELSE 0 END)                          AS lbr
    , SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore =  0 AND sca.finalScore =  0 THEN 1 ELSE 0 END)                          AS blbr

    , SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore > sca.finalScore THEN 1 ELSE 0 END)
      + SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore IS NOT NULL THEN 1 ELSE 0 END)
      - SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore = 0 AND sca.finalScore = 20 THEN 1 ELSE 0 END)                         AS rp
    , CASE WHEN (  SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore > sca.finalScore THEN 1 ELSE 0 END)
                 + SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore IS NOT NULL THEN 1 ELSE 0 END)
                 - SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore = 0 AND sca.finalScore = 20 THEN 1 ELSE 0 END)
                 - SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore IS NOT NULL THEN 1 ELSE 0 END))
                   / SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore IS NOT NULL THEN 1.0 ELSE 0.0 END) >= 0.0
           THEN ((  SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore > sca.finalScore THEN 1 ELSE 0 END)
                 + SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore IS NOT NULL THEN 1 ELSE 0 END)
                 - SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore = 0 AND sca.finalScore = 20 THEN 1 ELSE 0 END)
                 - SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore IS NOT NULL THEN 1 ELSE 0 END))
                   / SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore IS NOT NULL THEN 1.0 ELSE 0.0 END))
           ELSE 0.0 END                                                                                                                                               AS nrp
    , CASE WHEN SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore IS NOT NULL THEN 1 ELSE 0 END) > 0
           THEN  (SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore > sca.finalScore THEN 1.0 ELSE 0.0 END)
                / SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore IS NOT NULL THEN 1 ELSE 0 END))
           ELSE NULL END                                                                                                                                              AS wperc

    , SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore IS NOT NULL THEN scf.finalScore ELSE 0 END)                              AS ptsf
    , SUM(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND sca.finalScore IS NOT NULL THEN sca.finalScore ELSE 0 END)                              AS ptsa

    , MAX(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore NOT IN (0, 20) THEN scf.finalScore ELSE NULL END)                        AS hi
    , MAX(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore NOT IN (0, 20) THEN scf.game.id ELSE NULL END)                           AS higid
    , MIN(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore NOT IN (0, 20) THEN scf.finalScore ELSE NULL END)                        AS lo
    , MIN(CASE WHEN paf.wasWithdrawn = FALSE AND paa.wasWithdrawn = FALSE AND scf.finalScore NOT IN (0, 20) THEN scf.game.id ELSE NULL END)                           AS logid
    )
  FROM Club cl
    JOIN cl.teams te
    JOIN te.rosters ro
    JOIN ro.season se
    JOIN ro.participations pa
    JOIN pa.group gr
    JOIN gr.round rd
    JOIN rd.subCompetition sc
    JOIN sc.competition cn
    JOIN gr.games ga
    JOIN ga.scores scf
    JOIN ga.scores sca
    JOIN scf.roster rof
    JOIN sca.roster roa
    JOIN rof.participations paf
    JOIN roa.participations paa
  WHERE ...
  GROUP BY ...
  ORDER BY pa.wasWithdrawn, nrp DESC, w DESC, lbr, g DESC, cl.shorthand

Running this with Hibernate 4.x works without problems, however Eclipse Dali shows a JPQL error on pretty much every line of the constructor expression. Removing the ... AS <identifier> gets rid of these errors.

I looked at the JPQL BNF http://en.wikibooks.org/wiki/Java_Persistence/JPQL_BNF here, but I couldn't find the AS in the SELECT clause hierarchy.

Q's:

Is this Hibernate-specific syntax?

Why doesn't JPQL support this?

Sometimes expression can become very complex and I'd like to document what the expression actually means via the AS clause, especially considering that JPQL has no commenting functionality. This is a real flaw in JPQL IMHO.

Furthermore, Hibernate allows me to reference these ASes in the ORDER BY clause, which allows me to reuse the complex statement from above.

Maybe my expressions could be shortened but complexity can still be high in other cases/projects.

Thanks


回答1:


Found it.

According to the JPQL BNF at http://en.wikibooks.org/wiki/Java_Persistence/JPQL_BNF#New_in_JPA_2.0 this should be supported by JPA 2.0. Note, the second to last example.

This pretty much answers the original question why Eclipse Dali shows JPQL validation errors. It seems to be a problem with Dali.



来源:https://stackoverflow.com/questions/11807738/jpa-jpql-as-identifier-disallowed-in-select-clause

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!