递归JPA查询?

JPA 2是否有任何运行递归查询的机制?

这是我的情况:我有一个实体E,它包含一个整数字段x。 它也可能有类型E的子节点,通过@OneToMany映射。 我想做的是通过主键找到一个E,并获得它的x值以及它所有后代的x值。 有没有办法在单个查询中执行此操作?

我正在使用Hibernate 3.5.3,但我不想对Hibernate API有任何明确的依赖。


编辑:根据这个项目,Hibernate没有这个function,或者至少它没有在3月。 所以JPA似乎不太可能拥有它,但我想确定一下。

使用简单的邻接模型 ,其中每行包含对其父项的引用,该引用将引用同一表中的另一行,但与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' 

因此,要获得Node’1’及其所有子节点,查询是:

 SELECT * FROM node WHERE id = 1 OR path LIKE '1.%'; 

要将此映射到JPA,只需将“path”列作为持久对象的属性。 但是,您必须进行簿记才能使“路径”字段保持最新状态。 JPA / Hibernate不会为您执行此操作。 例如,如果将节点移动到另一个父节点,则必须更新父节点引用并从新父节点确定新路径值。

另一种方法称为嵌套集模型 ,它有点复杂。 可能是其创始人最好的描述 (而不是我逐字逐句加入)。

还有第三种方法称为嵌套间隔模型,但是这很大程度上依赖于存储过程来实现。

SQL的这一章的第7章描述了对这个问题的更完整的解释。

这篇文章中的最佳答案对我来说似乎是一次大规模的破解。 我已经不得不处理数据模型,其中杰出的工程师认为在数据库领域中编写树高级数据库是一个好主意,例如:“Europe | Uk | Shop1 | John”以及这些表中的大量数据。 并不令人瞩目,MyHackedTreeField LIKE’parentHierharchy%’表单查询表现为杀手。 解决这类问题最终需要创建树的层次结构和许多其他的内存缓存……

如果您需要运行递归查询,并且您的数据量不大……让您的生活变得简单,只需加载运行计划所需的数据库字段即可。 并在java中编写递归代码。 除非你有充分的理由这样做,否则不要在数据库中创建它。

即使您拥有的数据量很大,您也很可能将问题细分为独立的递归树批次,并在不需要一次加载所有数据的情况下及时处理这些数据。