如何在 JPA 中为 MySQL 编写自连接

How to write a self join in JPA for MySQL

我有一个名为 table 的组,其中包含四个 [相关] 列; id、parent_id、activated_datetype。 parent_id 和 activated_date 可以为空,如果一个组在今天之前有一个 activated_date,属于类型 A,或者它的 parent 组被激活,则该组被认为是激活的.

id parent_id activated_date type
1 2020-01-01 typeA
2 3 typeB
3 2020-01-01 typeC

我正在尝试编写一个查询来列出所有已激活的组,但我 运行 遇到了一个非常令人困惑的问题。 (注意:我正在使用 CASE 语句,因为在 JPA 中,SELECT 子句中不允许条件表达式,但它们在 CASE 表达式中)

如果我的 WHERE 子句如下所示:

(CASE
  WHEN
    g.activated_date is not null AND
    g.activated_date < CURDATE()
    THEN TRUE
  WHEN
    g.group_type = 'typeA'
    THEN TRUE
  ELSE FALSE
END) = TRUE

然后我找到 9000 个激活的组(如果我更改为 FALSE,则找到 1000 个停用的组)。这是意料之中的,一共10000组。

但是当我添加一个附加条件来检查 parent 的状态时(注意:这不需要递归,在这个用例中组不能有 'grandparents'):

(CASE
  WHEN
    g.activated_date is not null AND
    g.activated_date < CURDATE()
    THEN TRUE
  WHEN
    g.group_type = 'typeA'
    THEN TRUE
  WHEN
    (g.parent.activated_date is not null AND g.parent.activated_date < CURDATE()) OR
    (g.parent.group_type = 'typeA')
    THEN TRUE
  ELSE FALSE
END) = TRUE

然后我突然发现我有 8500 个激活的组(和 750 个停用的)。我无法解释丢失的 750 个组;我做错了什么吗?

您的完整查询不明确,但如果 'g' 个实例没有父项,它们将从查询结果中删除。您需要对此关系使用左联接才能将它们包含在结果中。

"select <your select clause> where G g left join g.parent parent where <your Where clause>"

在 select 或 where 子句中使用 g.parent 的地方,您只需使用 parent。所以

(CASE
  WHEN
    g.activated_date is not null AND
    g.activated_date < CURDATE()
    THEN TRUE
  WHEN
    g.group_type = 'typeA'
    THEN TRUE
  WHEN
    parent is not null AND
    ((parent.activated_date is not null AND parent.activated_date < CURDATE()) OR
    (parent.group_type = 'typeA'))
    THEN TRUE
  ELSE FALSE
END) = TRUE