Я думаю о макете таблицы для иерархии классов, управляемой Hibernate, и, безусловно, таблица для метода подкласса поражает меня как наиболее подходящего в общем смысле. Однако, анализируя логику, у меня есть некоторые сомнения относительно ее производительности, особенно в том, что количество шкал подклассов.
Чтобы дать очень короткий (и классический) пример, скажем, у вас есть следующие классы:
public abstract class Animal {
int pkey;
String name;
}
public class Dog extends Animal {
long numSlippersChewed; // int is not large enough...
}
public class Cat extends Animal {
short miceCaught; // ... but here int is far bigger than required :-)
}
(Я возвращаю геттеры, сеттеры и сопоставления Hibernate и т.д., просто предположим, что они являются основным очевидным случаем).
Таблицы базы данных для этих объектов имеют смысл, вы получаете хорошую денормализацию и так далее. Однако, какой запрос делает Hibernate, чтобы вытащить отдельное животное? Я могу подумать, по крайней мере, о двух случаях, когда это может произойти:
- Некоторая другая сущность, имеющая взаимно однозначное (или множественное) отображение, такое как поле
pet
классаHuman
. Это сохранит ключ pkey, поэтому, когда Hibernate выбирает объект Human, ему нужно будет также получить соответствующий объектAnimal
. Когда задан pkey животного, какой запрос будет использовать Hibernate для извлечения и развязывания фактических данных Animal, учитывая, что он может находиться в таблицахCat
илиDog
? - HQL, например
from Animal where name='Rex'
(пусть имена предполагаются уникальными). Это похоже на вышесказанное в том, что оно позволяет вам идентифицировать строку в таблице суперкласса, но вы не знаете, какую таблицу подкласса проверять для получения дополнительной информации. Предоставляет ли HQL запрос на выпускfrom
абстрактного класса? (Использование подкласса конкретного материала работает хорошо, например,from Cat where miceCaught > 5
).
Я могу подумать о двух способах, которые это может быть сделано в SQL, и ни один из них не выглядит симпатичным. Один из них - запустить запрос exists
для каждой таблицы подкласса для заданного ключа p, а затем загрузить из таблицы, которая вернула хит. В качестве альтернативы, Hibernate может выполнить какой-то ужасный союзный запрос, соединяющий во всех таблицах, - по существу, имитируя схему таблицы за иерархию, поскольку в результирующий набор будут включены атрибуты для всех возможных подклассов с отдельными выборами из таблиц подклассов, возвращающих null
для нерелевантных аргументы. В последнем случае, вероятно, даже потребуется добавить столбец синтетического дискриминатора, чтобы Hibernate мог знать, какая таблица подкласса фактически вернула строку и, следовательно, какой класс Java они должны быть проанализированы.
Вещи становятся более волосатыми, если у вас есть подтипы конкретных типов:
public class Greyhound extends Dog {
float lifetimeRacingWinnings;
}
Теперь для заданного животного pkey могут быть допустимые строки в таблицах Dog
и Greyhound
, что означает, что мой первый подход к проверке вручную класса, который соответствует pkey, получает намного сложнее.
Причина, по которой я так беспокоюсь, заключается в том, что я хочу использовать этот подход в иерархии классов с примерно 70 классами с максимальной цепочкой вложенности из 4-5 уровней, поэтому выполнение запроса объединения на все это возможно иметь ужасную производительность. Есть ли у Hibernate какие-либо трюки в рукаве, чтобы сохранить это относительно результативным? Или загружает ссылку на один из этих классов с помощью pkey, который займет много времени?