gpt4 book ai didi

java - QueryDSL 重复标识变量/相等语法错误与任何设置?

转载 作者:行者123 更新时间:2023-11-29 05:58:33 24 4
gpt4 key购买 nike

我有此处概述的 JPA 实体: QueryDSL JPA syntax error with contains on Set?

现在我尝试在单个查询中对 Set tags 设置多个限制:

Set<Tag> withTags = ...;
Set<Tag> withoutTags = ...;

q.where(license.tags.any().in(withTags));
q.where(license.tags.any().in(withoutTags).not());

执行查询时出现以下异常:

Exception [EclipseLink-8019] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Error compiling the query [select distinct license
from License license
where exists (select license_tags
from Tag license_tags
where license_tags member of license.tags and license_tags = ?1)
and not exists (select license_tags
from Tag license_tags
where license_tags member of license.tags and license_tags = ?2)]
multiple declaration of identification variable [license_tags], previously declared as [Tag license_tags].

我试图将 as("withTags") 插入到查询中,但我可以这样做的位置是在 any() 之后,它在 JPQL 中插入了 AS关于我要解决的重复问题,在错误的地方。我可以在 tags 之后插入它,但随后我得到一个 SimpleExpression 作为返回,我无法在其上执行 any()

还有其他想法可以防止这种标识变量的重复吗?

此外,上述语句仅在给定的 Set withTags/withoutTags 仅包含单个值时才有效。如果存在多个值,则抛出以下异常:

Exception [EclipseLink-6075] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.QueryException
Exception Description: Object comparisons can only use the equal() or notEqual() operators. Other comparisons must be done through query keys or direct attribute level comparisons.
Expression: [Relation operator IN Base my.package.Tag Parameter 1]
select distinct license
from License license
where exists (select license_tags
from Tag license_tags
where license_tags member of license.tags and license_tags in ?1)
at org.eclipse.persistence.exceptions.QueryException.invalidOperatorForObjectComparison(QueryException.java:614)
at org.eclipse.persistence.internal.expressions.RelationExpression.normalize(RelationExpression.java:393)
at org.eclipse.persistence.internal.expressions.CompoundExpression.normalize(CompoundExpression.java:226)
at org.eclipse.persistence.internal.expressions.CompoundExpression.normalize(CompoundExpression.java:218)
at org.eclipse.persistence.internal.expressions.SQLSelectStatement.normalize(SQLSelectStatement.java:1306)
at org.eclipse.persistence.internal.expressions.SubSelectExpression.normalizeSubSelect(SubSelectExpression.java:134)
at org.eclipse.persistence.internal.expressions.ExpressionNormalizer.normalizeSubSelects(ExpressionNormalizer.java:93)
at org.eclipse.persistence.internal.expressions.SQLSelectStatement.normalize(SQLSelectStatement.java:1379)
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.buildNormalSelectStatement(ExpressionQueryMechanism.java:482)
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.prepareSelectAllRows(ExpressionQueryMechanism.java:1553)
at org.eclipse.persistence.queries.ReadAllQuery.prepareSelectAllRows(ReadAllQuery.java:793)
at org.eclipse.persistence.queries.ReadAllQuery.prepare(ReadAllQuery.java:734)
at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:464)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.checkPrepare(ObjectLevelReadQuery.java:732)
at org.eclipse.persistence.queries.DatabaseQuery.prepareCall(DatabaseQuery.java:1577)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:240)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:173)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:125)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:109)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1326)
at sun.reflect.GeneratedMethodAccessor552.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.jboss.weld.util.reflection.SecureReflections$13.work(SecureReflections.java:304)
at org.jboss.weld.util.reflection.SecureReflectionAccess.run(SecureReflectionAccess.java:54)
at org.jboss.weld.util.reflection.SecureReflectionAccess.runAsInvocation(SecureReflectionAccess.java:163)
at org.jboss.weld.util.reflection.SecureReflections.invoke(SecureReflections.java:298)
at org.jboss.weld.bean.proxy.ClientProxyMethodHandler.invoke(ClientProxyMethodHandler.java:113)
at org.jboss.weld.util.CleanableMethodHandler.invoke(CleanableMethodHandler.java:43)
at javax.persistence.EntityManager_$$_javassist_131.createQuery(EntityManager_$$_javassist_131.java)
at com.mysema.query.jpa.impl.DefaultSessionHolder.createQuery(DefaultSessionHolder.java:35)
at com.mysema.query.jpa.impl.AbstractJPAQuery.createQuery(AbstractJPAQuery.java:139)
at com.mysema.query.jpa.impl.AbstractJPAQuery.createQuery(AbstractJPAQuery.java:108)
at com.mysema.query.jpa.impl.AbstractJPAQuery.list(AbstractJPAQuery.java:276)

还有 EclipseLink 2.4

Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: The SQL datatype to be used for an instance of mypackage.Tag cannot be determined. Use 'setObject()' with an explizit type, to define it.
Error Code: 0
Call: SELECT DISTINCT t0.ID, ...all the other properties...
FROM LICENSE t0, WHERE ((NOT EXISTS (SELECT ? FROM LicenseTags t5, TAG t4, TAG t3 WHERE (((t3.ID = t4.ID) AND (t3.ID IN (?,?))) AND ((t5.License_ID = t0.ID) AND (t4.ID = t5.tags_ID))))))

现在我尝试使用以下 QueryDSL 语法来解决这个问题:

for (Tag tag : withTags) {
q.where(license.tags.contains(tag));
}

for (Tag tag : withoutTags) {
q.where(license.tags.contains(tag).not());
}

前一部分确实像魅力一样工作,但后者没有返回预期的结果。 withoutTags 中存在的带有标签的许可证并未按应有的方式从结果集中排除。

后一条语句的 JPQL 和 SQL 如下所示:

select distinct license
from License license
where not ?1 member of license.tags

SELECT DISTINCT t1.ID, ...all the other properties...
FROM LicenseTags t2, LICENSE t1, TAG t0
WHERE (NOT (133170 = t0.ID) AND (t2.License_ID = t1.ID) AND (t0.ID = t2.tags_ID))

JPQL 对我来说看起来不错,但如果一个许可证关联了多个标签,SQL 显然会失败。所以我认为这实际上是 EclipseLink 翻译失败的情况。我会看看这是否是我正在使用的版本的已知错误。 JPQL "NOT MEMBER OF" query using criteria API 对本论文有所支持尽管在那种情况下,问题只发生在使用 creteria api 而不是 JPQL 时。这个错误的翻译在 EclipseLink 2.4 RC 2 中仍然存在。这里终于有一个解决方法,它对“没有标签”的部分做了它的意思:

Collection<Integer> tagIds = new ArrayList<Integer>();
for (Tag tag : withoutTags) {
tagIds.add(tag.getId());
}
q.where(license.tags.any().id.in(tagIds).not());

问候,蒂尔曼

最佳答案

您可以使用连接而不是子选择吗?这也会更有效率。

您也可以尝试 EclipseLink 2.4,它可能没有这些问题。

QueryDSL 支持连接,包括 innerJoin() 和 leftJoin(),您应该改用它。

关于java - QueryDSL 重复标识变量/相等语法错误与任何设置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11088064/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com