Стратегия наследования Hibernate и почему - PullRequest
2 голосов
/ 07 октября 2009

У меня есть 3 неабстрактных персистентных класса. Классы MyClubUser и HisClubUser наследуются от класса User. Я использую одну таблицу для каждой стратегии подкласса, т.е. @Inheritance(strategy = InheritanceType.JOINED), для этих классов.

Что я заметил, так это то, что сгенерированный SQL использует левое внешнее соединение HisClubUser и MyClubUser, когда я делаю запрос к классу User. Почему Hibernate делает это [присоединение к другим таблицам], где меня интересует только пользователь? Я хочу сказать, что, несмотря на то, что данные извлекаются, я не смог бы получить доступ к этим свойствам в MyClubUser или HisClubUser, учитывая, что возвращаются пользовательские экземпляры. Кроме того, это вызывает дополнительные издержки по сравнению с запросом, где он просто запрашивает таблицу пользователя без левого внешнего соединения?

Спасибо

Ответы [ 3 ]

5 голосов
/ 07 октября 2009

Hibernate ВСЕГДА возвращает тип фактического постоянного объекта. Если вы сохранили «MyClubUser», он будет возвращен как «MyClubUser», а не «Пользователь». Причина этого совершенно ясна - если бы Hibernate вернул «MyClubUser» как «Пользователь» и вы бы сохранили его снова, вы потеряете все дополнительные свойства, определенные в «MyClubUser».

Для этого Hibernate должен знать, что это за тип. Для стратегии InheritanceType.JOINED единственный способ выяснить это - проверить все таблицы в иерархии наследования (ну, технически это все таблицы на текущем уровне или ниже, плюс все таблицы выше текущего уровня в текущей ветви дерева). ). Итак, если у вас есть иерархия вроде:

           Root
          /   \
      Node1  Node2
      /   \
   Node11 Node12

и вы пытаетесь выбрать из root, Hibernate выполнит внешнее объединение для ВСЕХ таблиц. Если вы выбираете из Node1, Hibernate выполнит внутреннее соединение на Node1 и Root плюс внешнее соединение на Node11 и Node12. Node2 не будет затронут, потому что он не является потомком Node1.

Что касается накладных расходов на внешнее объединение - да, определенно накладные расходы, но это цена, которую вы платите за объединенную стратегию. Вы можете использовать дискриминаторы, чтобы избежать этого, но это имеет свои побочные эффекты. Является ли эти издержки значительными или нет, зависит от глубины и распространенности вашей иерархии, ваших индексов и многих других вещей. Прослушайте предложение KLE и профилируйте его.

4 голосов
/ 07 октября 2009

Почему Hibernate [присоединяется к другим таблицам], где меня интересует только Пользователь?

Поскольку все HisClubUser также являются действительными экземплярами пользователя, логично получить их, когда вы запрашиваете пользователя.

Суть в том, что, несмотря на то, что данные получены, я не смог бы получить доступ к этим свойствам в MyClubUser или HisClubUser, если возвращены экземпляры User.

Вы действительно уверены? Проверьте (в отладке, например) эффективный класс, который возвращается, это должны быть подклассы. Таким образом, возможно понижение и доступ к свойствам.

Кроме того, это вызывает дополнительные издержки по сравнению с запросом, когда он просто запрашивает таблицу пользователя без левого внешнего соединения?

Да, и дополнительное объединение накладно. Это может быть важно или нет: я предлагаю вам проверить это в вашем конкретном случае.

2 голосов
/ 07 октября 2009

Вы запрашиваете пользователя, поэтому Hibernate выполнит «полиморфный запрос». Поскольку MyClubUser и HisClubUser являются объектами пользователя по своей природе (они наследуются от пользователя), Hibernate также будет извлекать пользователей такого типа.

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