Рекурсивный запрос JPA?

имеет ли JPA 2 какой-либо механизм для запуска рекурсивных запросов?

вот моя ситуация: у меня есть сущность E, которая содержит целое поле x. У него также могут быть дети типа E, отображаемые через @OneToMany. Я хотел бы найти E по первичному ключу и получить его значение x вместе со значениями x всех его потомков. Есть ли способ сделать это в одном запросе?

Я использую Hibernate 3.5.3, но я бы предпочел не иметь явных зависимостей от Апис Гибернации.


EDIT: согласно этой пункт, Hibernate делает не есть эта функция, или, по крайней мере, это не было в марте. Поэтому маловероятно, что у JPA это будет, но я хотел бы убедиться.

2 ответов


использовать простой Модель Смежности где каждая строка содержит ссылку на своих родителей, которые будут ссылаться на другую строку в той же таблице, не сотрудничает хорошо с JPA. Это связано с тем, что JPA не поддерживает создание запросов с помощью предложения Oracle CONNECT BY или инструкции SQL standard WITH. Без любого из этих 2 пунктов его на самом деле невозможно сделать модель смежности полезной.

однако существует несколько других подходов к моделированию эта проблема, которая может применяться к этой проблеме. Первый-это Материализованная Модель Пути. Здесь полный путь к узлу сплющивается в один столбец. Определение таблицы расширено следующим образом:

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 не сделает этого за вас. Е. Г. при перемещении узла к другому родителю вам придется обновить оба родителя ведения и определить новое значение пути от нового родительского объекта.

другой подход называется Вложенная Модель Набора, что немного сложнее. Наверное, лучше описал его составителем (а не добавлено дословно я.)

существует третий подход, называемый вложенной моделью интервалов, однако это имеет большую зависимость от хранимых процедур для реализации.

гораздо более полное объяснение этой проблемы описано в главе 7 искусство SQL.


лучший ответ в этом посте кажется мне массивным обходным взломом. Мне уже приходилось иметь дело с моделями данных, где блестящие инженеры решили, что было бы неплохо кодировать дерево Hiarchies в полях БД как текст, такой как: "Европа|Великобритания|Shop1|John" и с огромными объемами данных в этих таблицах. Неудивительно, что выполнение запроса формы MyHackedTreeField похоже на " parentHierharchy%", где убийцы. Решение этой проблемы в конечном счете требует создания в кэше памяти о древе hiearchies и многих других...

Если вам нужно выполнить рекурсивный запрос и ваш объем данных не большой... сделайте свою жизнь простой и просто загрузите поля БД, необходимые для запуска вашего плана. И Закодируйте свою рекурсию на java. Не делайте этого в БД, если у вас нет веской причины это делать.

и даже если объем данных у вас огромный, вы, скорее всего, можете разделить свою проблему на независимые рекурсивные пакеты дерева и обработать их одновременно без необходимости загружать все данные сразу.