Как hibernate узнает, какой подкласс создать при использовании объединенного наследования - PullRequest
1 голос
/ 27 января 2012

если у меня есть

@Inheritance(strategy = InheritanceType.JOINED)
Organization{
}

Account extends Organization{
   private Organization organization
}

Client extends Organization{
   private Organization organization
}

User {
   private Organization organization
}

Когда я вызываю userDAO.get (1) и возвращаю экземпляр User, как hibernate узнает, что я должен вернуть экземпляр Account, а не Client?

Ответы [ 3 ]

2 голосов
/ 27 января 2012

без дискриминатора

Hibernate выполняет OUTER JOIN с каждой дочерней таблицей:

SELECT *,
case
    when a.id is not null then 0
    when c.id is not null then 1
    when u.id is not null then 2
end as clazz
FROM Organization o
    OUTER JOIN Account a
    OUTER JOIN Client c
    OUTER JOIN User u

И определяет фактический тип, посмотрев на который OUTER JOIN действительно что-то вернул. Очевидно, что будет ровно одна таблица из Account, Client и User, содержащая запись с таким же id - и это обозначает фактический тип. Вот что делает неловкий case / when.

с дискриминатором

Если присутствует столбец дискриминатора, OUTER JOIN все еще необходимы, но легче определить фактический тип, поскольку он явно хранится в базе данных. Нет case / when магия.

Резюме

Как видите, эта стратегия наследования очень неэффективна. Намного лучше, когда вы явно запрашиваете данный подтип, потому что Hibernate сделает JOIN только с одной таблицей.

Смотри также:

1 голос
/ 27 января 2012

Для каждой записи Hibernate может хранить дополнительный (дискриминаторный) столбец в главной таблице, который указывает, какой тип используется.

0 голосов
/ 27 января 2012

ПРИМЕЧАНИЕ. Относится только к стратегии SINGLE_TABLE , см. Ответ @Tomazs для стратегии JOINED.

Hibernate хранит явный подкласс, используемый в качестве некоторой формы перечисления, обычно какстроковое значение в базе данных.Вы можете установить имя этого столбца, используя аннотацию @DescriminatorColumn, а затем использовать аннотацию @DiscriminatorValue для подклассов.Когда Hibernate переходит к сохранению Account в базе данных, любые строки, для которых характерно, например, Client, все еще сохраняются для этого Account, но имеют значение null, а DiscriminatorColumn устанавливается на "Account".Затем, когда организация десериализована, Hibernate смотрит на этот DiscriminatorColumn, видит, что Organization является Account, и возвращает вам этот тип объекта.

DescriminatorColumn можно изменитьиспользовать другие типы данных, например.не строки, используя параметр columnDefinition.По умолчанию имя этого столбца равно DTYPE, а значения для классов, у которых нет DiscriminatorValue, являются именами классов.

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