用 SQL 来做
对于我的回答,我将假设 seq 用于在您的菜单层次结构中订购兄弟姐妹,并且您的示例数据是错误的(没有两个兄弟姐妹可能具有相同的 seq 值,即应该是UNIQUE (pid, seq)。所以,我将使用这个示例数据(为简单起见,INT IDs):
INSERT INTO menu (id, pid, name, seq)
VALUES
(1, null, 'Menu 1', 1),
(2, null, 'Menu 2', 2),
(3, null, 'Menu 3', 3),
(4, 1, 'Sub Menu 1', 1),
(5, null, 'Menu 1', 9);
您将需要使用WITH clause 进行递归查询。在 SQL 中:
WITH RECURSIVE m AS (
SELECT
id,
ARRAY[seq] AS path,
name, 1 AS level,
'- ' || name AS display
FROM menu
WHERE pid IS NULL
UNION ALL
SELECT
menu.id,
path || seq,
menu.name,
m.level + 1 AS level,
repeat(' ', m.level) || '- ' || menu.name
FROM menu JOIN m ON m.id = menu.pid
)
SELECT *
FROM m
ORDER BY path;
The query output can be seen here。它是:
id |path |name |level |display |
---|------|-----------|------|---------------|
1 |{1} |Menu 1 |1 |- Menu 1 |
4 |{1,1} |Sub Menu 1 |2 | - Sub Menu 1 |
2 |{2} |Menu 2 |1 |- Menu 2 |
3 |{3} |Menu 3 |1 |- Menu 3 |
5 |{9} |Menu 1 |1 |- Menu 1 |
当然,还有其他方法可以达到相同的效果。栏目说明:
-
id:原菜单项id
-
path:通向任何给定菜单项的路径(连接的 seq 值数组,假设它们在 pid 中是唯一的)
-
name:菜单项的原始名称
-
level:递归或嵌套级别(用于填充)
-
display:菜单项的填充显示,根据您的问题
用 jOOQ 来做
现在,您只需将上述内容转换为 jOOQ 查询即可。
假设这些静态导入(一如既往):
import static org.jooq.impl.DSL.*;
import static com.example.generated.Table.*;
如下:
Field<Integer[]> path = array(MENU.SEQ).as("path");
Field<Integer> level = inline(1).as("level");
Field<String> display = inline("- ").concat(MENU.NAME).as("display");
Table<?> m = name("m").as(
select(MENU.ID, path, MENU.NAME, level, display)
.from(MENU)
.where(MENU.PID.isNull())
.unionAll(
select(
MENU.ID,
PostgresDSL.arrayAppend(path, MENU.SEQ),
MENU.NAME,
level.add(inline(1)),
repeat(inline(" "), level).concat(inline("- ")).concat(MENU.NAME))
.from(MENU)
.join(table(name("m"))).on(field(name("m", "id"), Integer.class).eq(MENU.PID)))
);
ctx.selectFrom(m).orderBy(path).fetch();