Hibernate, SQL и рекурсивные ассоциации - PullRequest
4 голосов
/ 23 июня 2010

В моей базе данных есть две таблицы: «вопрос» и «поле». Вопросы могут иметь много полей, а поля могут иметь много полей. Это дерево со специальным корневым узлом.

Я хочу использовать их с Hibernate (в настоящее время potgresql) - так что это должно быть просто и просто использовать его из Java.

Какое лучшее решение для этого?

  1. добавить question_parent_id и field_parent_id в таблицу «field» и использовать question_parent_id, только если он является его прямым потомком. (проверьте XOR, какое ограничение SQL ... может зависеть от сервера SQL)
  2. добавить question_parent_id и field_parent_id и всегда использовать question_parent_id. Не забывайте придерживаться последовательности ... (вопрос_ид не должен меняться, вероятно, это не реальный риск)
  3. Используйте специфичное для postgresql наследование таблиц: «question» и «field» расширяют «content», поэтому достаточно одного столбца внешнего ключа. Используйте дополнительные ограничения как для «вопроса», так и для «поля».
  4. использовать третью таблицу (называемую «контейнер»), состоящую из просто идентификатора. Контейнеры могут иметь много полей, а поле может иметь один контейнер. Вопросы имеют один контейнер. Но для этого требуется дополнительный код в Java, и существует риск бесконечных циклов, даже с уникальным ключом field_container_id ...

Ответы [ 3 ]

2 голосов
/ 23 июня 2010

Я бы скорее подумал о модели классов, чем о реляционной модели.Пользователь в конце (как правило) не заботится о том, сколько ключей у вас есть в вашей базе данных.Он использует ваши классы, где оно должно быть «простым и простым в использовании».Поэтому сначала напишите модель своего класса, а потом подумайте о отображении.

Решение в базе данных зависит от модели вашего класса.

Редактировать : ваша модель с другой стороны зависитна то, что вам нужно сделать.

Навигация: Вам обычно нужны все поля из вопроса?Вам обычно нужны только поля, непосредственно связанные с вопросом или полем, или все поля рекурсивно вниз по дереву?Вам нужно знать родителя поля?и т. д. и т. п.

Запросы. Вам необходимо отфильтровать вопросы или поля по назначенным им полям?Рекурсивный?Вам нужно отфильтровать поля по родителю?и т. д.

Другими словами: вы не можете оптимизировать все.Есть типичные запросы и типичные пути навигации.Поддержка слишком многих способов может стать дорогостоящей и потребовать избыточных данных как в модели, так и в базе данных, что затрудняет обслуживание.

0 голосов
/ 02 июля 2010

Вы должны тщательно обдумать, насколько глубокой будет ваша иерархия, если вы хотите эффективное решение.Этот вид рекурсивных структур может быть чрезвычайно дорогим для загрузки в спящем режиме, так как это часто приводит к созданию большого количества объединений для каждого поля, поскольку оно может иметь дочерние поля (и они могут иметь дочерние поля и т.* Если вы хотите разрешить бесконечную глубину, но вы всегда хотите загрузить весь вопрос, включая все поля и подполя.Тогда я бы предложил, чтобы у Field было родительское поле (nullable) и собственный вопрос (non-nullable).Это позволяет эффективно загружать весь вопрос следующим HQL:

SELECT q FROM Question q
JOIN FETCH q.allFields
0 голосов
/ 23 июня 2010

Если я что-то упускаю, у вас есть отношение один-ко-многим между [Question] и [Field] (это один-ко-многим, верно?) И самоотверженная связь один-ко-многим [Field]. Поэтому я бы:

  • добавить question_id в таблицу [Field] для прежнего отношения
  • добавить parent_id в таблицу [Field] для более позднего отношения

Hibernate может отобразить это без проблем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...