java - QueryDSL - 如何加入子查询联合

标签 java querydsl

我正在使用 QueryDSL 构建一个 SQL 查询,其中包含多个连接在一个联合中的子查询。这是我查询的基础:

QTransaction t = QTransaction.transaction;
query = query.from(t).where(t.total.gt(BigDecimal.ZERO));

然后我有几个子查询来获取与事务关联的客户名称。例如,我已经减少到两个:

SQLSubQuery subQuery = new SQLSubQuery();
subQuery = subQuery.from(t).join(t.fk462bdfe3e03a52d4, QClient.client);
ListSubQuery clientByPaid = subQuery.list(t.id, bt.paidId, QClient.client.name.as("clientname"));

subQuery = new SQLSubQuery();
subQuery = subQuery.from(t).where(t.paidId.isNull(), t.clientname.isNotNull());
ListSubQuery clientByName = subQuery.list(t.id, Expressions.constant(-1L), t.clientname.as("clientname"));

我如何将它们合并在一起,并与我的主查询合并?这是我目前的尝试:

subQuery = new SQLSubQuery();
subQuery = subQuery.from(subQuery.unionAll(clientByPaid,clientByName).as("namequery"));


query = query.leftJoin(subQuery.list(
            t.id, Expressions.path(Long.class, "clientid"),
                    Expressions.stringPath("clientname")),
                    Expressions.path(List.class, "namequery"));

这会编译,但当我尝试 query.count() 时会在运行时生成无效的 SQL。可能的错误:

  • 联合子查询的语法。
  • 命名子查询结果列的 .as(...) 表达式与 leftJoin 中使用的路径表达式之间的连接。

最佳答案

修复它。主要错误是我错过了左连接中的 on 子句,但为了表达 on 条件,我必须更加小心地命名子查询。该文档对构建访问子查询结果的路径略有说明,所以这里是示例。

联合中的第一个查询设置列名:

SQLSubQuery subQuery = new SQLSubQuery();
subQuery = subQuery.from(t).join(t.fk462bdfe3e03a52d4, QClient.client);
ListSubQuery clientByPaid = subQuery.list(t.id.as("id"), t.paidId.as("clientid"),
                                QClient.client.name.as("clientname"));

subQuery = new SQLSubQuery();
subQuery = subQuery.from(t).where(t.paidId.isNull(), t.clientname.isNotNull());
ListSubQuery clientByName = subQuery.list(t.id, Expressions.constant(-1L), 
                                  t.clientname);

我现在需要构建一个路径表达式来引用我的内部查询。我使用哪个类作为路径似乎并不重要,所以我选择了 Void 来强调这一点。

subQuery = new SQLSubQuery();
Path innerUnion = Expressions.path(Void.class, "innernamequery");
subQuery = subQuery.from(subQuery.union(clientByPaid,clientByName).as(innerUnion));

还有一个进一步的路径表达式来表达 on 子句。请注意,我加入了联合查询的 list(),使用之前定义的 innerUnion 路径选择了每一列。

Path namequery = Expressions.path(Void.class, "namequery");
query = query.leftJoin(subQuery.list(
                Expressions.path(Long.class, innerUnion, "id"),
                Expressions.path(Long.class, innerUnion, "clientid"),
                Expressions.stringPath(innerUnion, "clientname")),
              namequery)
          .on(t.id.eq(Expressions.path(Long.class, namequery, "id")));

关于java - QueryDSL - 如何加入子查询联合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22923560/

相关文章:

java - 尝试给我的程序礼貌(JAVA初学者)

java - 为什么我可以在测试中访问 protected 方法?

java - 如何从 MongoRepository/QueryDSL 获取不同的字段?

querydsl - 初始化路径时出现 NullPointerException

java - 不使用 Maven 获取 QueryDSL JAR 文件

java - 如何使用 QueryDsl 按日期分组?

java - 如何创建具有多个页面的 Swing 应用程序

java - Apache Olingo4 ExpressionVisitor

Swing 的 JavaFX 模态窗口所有权

java - 如何使用 QuerydslPredicate 按子对象属性进行过滤?