使用简单的邻接模型,其中每行都包含对其父级的引用,该父级将引用同一表中的另一行,这与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,只需将“path”列设置为持久对象的属性即可。但是,您必须进行簿记以保持“路径”字段的最新状态。JPA/Hibernate 不会为你做这件事。例如,如果将节点移动到其他父对象,则必须更新父引用并从新的父对象确定新的路径值。
另一种方法称为嵌套集模型,它稍微复杂一些。可能最好由其发起人描述(而不是由我逐字添加)。
还有第三种方法称为嵌套间隔模型,但是这种方法在很大程度上依赖于存储过程来实现。
对这个问题的更完整的解释在《SQL的艺术》的第7章中进行了描述。