带有 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.1537490,JOIN ... 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
我有一个带有 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.1537490,JOIN ... 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