使用CaseBuilder时Querydsl InvalidDataAccessApiUsageException

时间:2018-12-06 12:31:38

标签: java spring querydsl

public class X {
    private AC ac;
}

public class AC {
    private AP ap;
}

public class AP {
    private List<AC> acs;
    private BD bd;
}

public class BD {
    private List<AP> aps;
    private List<BD> childBds;
    private BD parentBD;
}
数据库中的

Bd条目是具有childBds的父项或具有父项和多个AP的childBds。父Bds从不直接链接到Ap,而仅链接到其childBds。

查询

public Predicate createPredicate(Integer bdId) {
    QX qX = new QX("x");
    BooleanExpression expression = // Some predicate which isn't causing issues
    QAp qAp = new QAp(qX.a.ap.getMetaData(), PathInits.DIRECT);
    QBd qChildBd = new QBd(qAp.bd().getMetaData(), PathInits.DIRECT);
    QBd qParentBd = new QBd(qChildBd.parentBd().getMetaData(), PathInits.DIRECT);
    BooleanExpression childOrParentBd = new CaseBuilder().
        when(qParentBd.id.eq(bdId).and(qParentBd.childBds.size.gt(0))).
            then((Predicate) qParentBd.id.eq(bdId)).
        otherwize(qChildBd.id.eq(bdId));
    return expression.and(childOrParentBd);
}

此谓词的目标是在查询的where子句中使用,以便检索链接到特定bdId的a的所有X。 ID是唯一的,但我无法知道bdId是属于带孩子的Bd还是带父母的Bd。

要检查bdId是否属于parentBd,请检查相应的Bd是否具有childBds。如果是这种情况,则表达式中使用的谓词需要为qParentBd.id.eq(bdId)。如果不是这种情况,则必须为qChildBd.id.eq(bdId)。

我可能是错的,但是所有这些对我来说都是正确的。但是,执行查询时会出现异常:

InvalidDataAccessApiUsageException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected AST node: case near line 3, column 3850

我在这一行和职位上都有案情陈述:

case when (x.ac.ap.bd.parent.id = ?1 and size(x.ac.ap.bd.parentBd.childBds) > ?94) then (x.ac.ap.bd.parentBd.id = ?1) else (x.ac.ap.bd.id = ?1) end

我尝试了什么

  1. 我查看了InvalidDataAccessApiUsageException的文档。从无法编译的查询来看,我假设我错误地使用了case when then end语句。
  2. 我找到了这个StackOverflow post,并尝试添加... .otherwize(qChild.id.eq(BdId).eq(true)),这导致了QueryException: Could not determine data type for searched case statement异常。我决定先研究该帖子提供的其他解决方案。
  3. 请参阅下面的答案。

1 个答案:

答案 0 :(得分:0)

经验教训:保持简单

我将case when then end子句更改为一个简单的x OR y子句,该子句似乎已解决了此特定问题。

public Predicate createPredicate(Integer bdId) {
    QX qX = new QX("x");
    BooleanExpression expression = // Some predicate which isn't causing issues
    QAp qAp = new QAp(qX.a.ap.getMetaData(), PathInits.DIRECT);
    QBd qChildBd = new QBd(qAp.bd().getMetaData(), PathInits.DIRECT);
    QBd qParentBd = new QBd(qChildBd.parentBd().getMetaData(), PathInits.DIRECT);
    BooleanExpression childOrParentBd = bovenBeleidsDoelstelling.id.eq(beleidsDoelstellingId)
        .or(beleidsDoelstelling.id.eq(beleidsDoelstellingId));
    return expression.and(childOrParentBd);
}

由于bdId是唯一的,因此足以检查两个可能的QueryDsl路径:

  1. x.ac.ap.bd.parentBd.id.eq(bdId)
  2. x.ac.ap.bd.id.ed(bdId)

如果找到二者之一,则只会为此特定bdId返回x个结果。

重要

这不能解释为什么我会遇到错误。如果有人对此进行详细说明,将不胜感激。