使用简单的邻接模型,其中每一行都包含对其父级的引用,该父级将引用同一表中的另一行,这与 JPA 不能很好地合作。这是因为 JPA 不支持使用 Oracle CONNECT BY 子句或 SQL 标准 WITH 语句生成查询。如果没有这两个条款中的任何一个,就不可能真正使邻接模型有用。
但是,还有一些其他方法可以对这个问题进行建模,可以应用于这个问题。第一个是物化路径模型。这是节点的完整路径被展平为单列的地方。表定义扩展如下:
CREATE TABLE node (id INTEGER,
path VARCHAR,
parent_id INTEGER REFERENCES node(id));
插入节点树看起来像:
INSERT INTO node VALUES (1, '1', NULL); -- Root Node
INSERT INTO node VALUES (2, '1.2', 1); -- 1st Child of '1'
INSERT INTO node VALUES (3, '1.3', 1); -- 2nd Child of '1'
INSERT INTO node VALUES (4, '1.3.4', 3); -- Child of '3'
因此,要获取节点“1”及其所有子节点,查询是:
SELECT * FROM node WHERE id = 1 OR path LIKE '1.%';
要将其映射到 JPA,只需将“路径”列作为持久对象的属性。但是,您必须进行簿记以使“路径”字段保持最新。JPA/Hibernate 不会为您执行此操作。例如,如果您将节点移动到不同的父级,您将必须更新父级引用并确定来自新父级对象的新路径值。
另一种方法称为嵌套集模型,它有点复杂。可能最好由它的创始人来描述(而不是由我逐字添加)。
还有第三种方法称为嵌套间隔模型,但是这严重依赖存储过程来实现。
The Art of SQL的第 7 章描述了对这个问题的更完整的解释。