带有 JOIN ... ON 子句的 JPQL 查询 + 使用 EclipseLink 的子查询导致异常 "Internal problem encountered while compiling"

JPQL query with JOIN ... ON clause + sub query results in exception "Internal problem encountered while compiling" using EclipseLink

我有一个带有 JOIN ... ON ... 子句的 JPQL 查询,自 JPA 2.1 起有效:

SELECT NEW net.bbstats.dto.CompetitionListDto(
  gl.name,
  se.startYear,
  -1,
  cm.level,
  cml.code,
  cml.name,
  tt.code,
  tt.ageGroup,
  tt.gender,
  cm.type,
  -1
)
FROM Group gr
  LEFT JOIN gr.groupLabel gl
  LEFT JOIN gr.groupMembers gm
  LEFT JOIN gm.roster ro
  JOIN gr.round rd
  JOIN rd.season se
  JOIN rd.competition cm
  JOIN cm.teamType tt
  JOIN cm.geoContext gc
  JOIN cm.competitionLabels cml ON cml.seasonStartYear = SELECT MAX(lbl.seasonStartYear)
                                                          FROM CompetitionLabel lbl
                                                            JOIN lbl.competition cmp
                                                            JOIN cmp.geoContext geo
                                                            JOIN cmp.teamType tet
                                                          WHERE geo.id = ge.id
                                                            AND tet.code = tt.code
                                                            AND cmp.type = cm.type
                                                            AND cmp.level = cm.level
                                                            AND lbl.seasonStartYear <= :seasonStartYear
WHERE se.startYear = :seasonStartYear
GROUP BY rd.id, gl.code, cml.code, cml.name
ORDER BY se.startYear, gc.type, gc.name, cm.type, tt.ageGroup DESC, tt.gender DESC, rd.id, gl.code

我得到一个例外:

Exception Description: Unable to deploy PersistenceUnit [BBStatsPU] in invalid state [DeployFailed].
Internal Exception: javax.persistence.PersistenceException: Exception [EclipseLink-28019] (Eclipse Persistence Services - 2.7.5.v20191016-ea124dd158): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Deployment of PersistenceUnit [BBStatsPU] failed. Close all factories for this PersistenceUnit.
Internal Exception: Exception [EclipseLink-0] (Eclipse Persistence Services - 2.7.5.v20191016-ea124dd158): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Internal problem encountered while compiling [
            SELECT NEW net.bbstats.dto.CompetitionListDto(
              gl.name,
              se.startYear,
              -1,
              cm.level,
              cml.code,
              cml.name,
              tt.code,
              tt.ageGroup,
              tt.gender,
              cm.type,
              -1
            )
            FROM Group gr
              LEFT JOIN gr.groupLabel gl
              LEFT JOIN gr.groupMembers gm
              LEFT JOIN gm.roster ro
              JOIN gr.round rd
              JOIN rd.season se
              JOIN rd.competition cm
              JOIN cm.teamType tt
              JOIN cm.geoContext gc
              JOIN cm.competitionLabels cml ON cml.seasonStartYear = SELECT MAX(lbl.seasonStartYear)
                                                                      FROM CompetitionLabel lbl
                                                                        JOIN lbl.competition cmp
                                                                        JOIN cmp.geoContext geo
                                                                        JOIN cmp.teamType tet
                                                                      WHERE geo.id = ge.id
                                                                        AND tet.code = tt.code
                                                                        AND cmp.type = cm.type
                                                                        AND cmp.level = cm.level
                                                                        AND lbl.seasonStartYear <= :seasonStartYear
            WHERE se.startYear = :seasonStartYear
            GROUP BY rd.id, gl.code, cml.code, cml.name
            ORDER BY se.startYear, gc.type, gc.name, cm.type, tt.ageGroup DESC, tt.gender DESC, rd.id, gl.code
        ].
Internal Exception: java.lang.NullPointerException
    at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:634)
    at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.getAbstractSession(EntityManagerFactoryDelegate.java:222)
    at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.createEntityManagerImpl(EntityManagerFactoryDelegate.java:330)
    at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:350)
    at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:313)
    at org.jboss.as.jpa.container.TransactionScopedEntityManager.createEntityManager(TransactionScopedEntityManager.java:187)
    at org.jboss.as.jpa.container.TransactionScopedEntityManager.getOrCreateTransactionScopedEntityManager(TransactionScopedEntityManager.java:157)
    at org.jboss.as.jpa.container.TransactionScopedEntityManager.getEntityManager(TransactionScopedEntityManager.java:87)
    at org.jboss.as.jpa.container.AbstractEntityManager.createNamedQuery(AbstractEntityManager.java:98)
    at net.bbstats.framework.service.Repository.findByNamedQuery(Repository.java:173)
    at net.bbstats.framework.service.BaseEntityService.findByNamedQuery(BaseEntityService.java:467)
    at net.bbstats.framework.service.BaseEntityService.findByNamedQuery(BaseEntityService.java:453)
    at net.bbstats.framework.service.BaseEntityService.findByNamedQuery(BaseEntityService.java:429)
    at net.bbstats.framework.service.BaseEntityService.findAllWithFetchGraph(BaseEntityService.java:385)
    ... 192 more

查看 JPA 2.1 规范的 JPQL BNF,参见 https://download.oracle.com/otn-pub/jcp/persistence-2_1-fr-eval-spec/JavaPersistence.pdf?#G4.1537490JOIN ... ON ... 似乎实际上不允许 [=15] 右侧的子查询=] 如果进一步评估:

问题:

我的假设正确吗?

如果是这样,那么我将如何使用标准 JPA + EclipseLink 而不 本机查询(这将是明显的替代方案)来解决我手头的问题?

解释一下:子查询以赛季开始年份为参数,比如2010年,然后将确定最新的name/label比赛,这可能是在2005年插入的。例如,比赛就像德国篮球德甲联赛可能每 X 年更换一次赞助商,因此 2010 年的名称可能是 "Beko Basketball Bundesliga",从 2014 年开始将是 "easycredit BBL",等等

简短版本:"Get the MAX label entity of all before the passed :seasonStartYear"

顺便说一句:上面的查询使用 Hibernate。 EclipseLink 版本为 2.7.5,请参阅堆栈跟踪。

EclipseLink 根本不支持这个。由于您使用的是内部联接,因此您实际上也可以像这样在 WHERE 子句中使用子查询:

SELECT NEW net.bbstats.dto.CompetitionListDto(
  gl.name,
  se.startYear,
  -1,
  cm.level,
  cml.code,
  cml.name,
  tt.code,
  tt.ageGroup,
  tt.gender,
  cm.type,
  -1
)
FROM Group gr
  LEFT JOIN gr.groupLabel gl
  LEFT JOIN gr.groupMembers gm
  LEFT JOIN gm.roster ro
  JOIN gr.round rd
  JOIN rd.season se
  JOIN rd.competition cm
  JOIN cm.teamType tt
  JOIN cm.geoContext gc
  JOIN cm.competitionLabels cml
WHERE se.startYear = :seasonStartYear
AND cml.seasonStartYear = (SELECT MAX(lbl.seasonStartYear)
                                                          FROM CompetitionLabel lbl
                                                            JOIN lbl.competition cmp
                                                            JOIN cmp.geoContext geo
                                                            JOIN cmp.teamType tet
                                                          WHERE geo.id = ge.id
                                                            AND tet.code = tt.code
                                                            AND cmp.type = cm.type
                                                            AND cmp.level = cm.level
                                                            AND lbl.seasonStartYear <= :seasonStartYear)
GROUP BY rd.id, gl.code, cml.code, cml.name
ORDER BY se.startYear, gc.type, gc.name, cm.type, tt.ageGroup DESC, tt.gender DESC, rd.id, gl.code