Ответ 1
Поскольку я снова и снова сталкиваюсь с этим, я думаю, что это может помочь прояснить:
Во-первых, это правда, что Hibernate не требует дискриминации при использовании отображения JOINED_TABLE
. Однако это необходимо при использовании SINGLE_TABLE
. Что еще более важно, другие провайдеры JPA в основном требуют этого.
То, что Hibernate на самом деле делает при выполнении полиморфного запроса JOINED_TABLE
, заключается в создании дискриминатора с именем clazz
"на лету" с использованием case-switch, который проверяет наличие уникальных полей для конкретных подклассов после внешнего соединения всех таблиц участвует в дереве наследования. Вы можете видеть это, когда включаете свойство "hibernate.show_sql"
в свой persistence.xml
. На мой взгляд, это, вероятно, идеальное решение для запросов JOINED_TABLE
, поэтому люди Hibernate могут похвастаться этим.
При выполнении обновлений и удалений этот вопрос несколько отличается; здесь hibernate сначала запрашивает вашу корневую таблицу для любых ключей, которые соответствуют предложению where where, и создает виртуальный pkTable
из результата. Затем он выполняет "DELETE FROM / UPDATE table WHERE pk IN pkTable"
для любого конкретного класса с вашим деревом наследования; оператор IN вызывает отсканированный подзапрос O(log(N))
для каждой записи таблицы, но, скорее всего, это в памяти, поэтому это не так уж плохо с точки зрения производительности.
Чтобы ответить на ваш конкретный вопрос, Hibernate просто не видит здесь проблемы, и с определенной точки зрения они верны. Было бы невероятно просто прокомментировать аннотации @DiscriminatorValue
, введя значения дискриминатора во время entityManager.persist()
, даже если они на самом деле их не используют. Однако не соблюдение столбца дискриминатора в JOINED_TABLE
имеет преимущество (для Hibernate) для создания мягкого случая блокировки поставщика, и это даже оправданно, указывая на превосходную технологию.
@ForceDiscriminator
или @DiscriminatorOptions(force=true)
уверены, что немного облегчают боль, но вы должны использовать их до создания первых объектов или принудительно вручную добавлять отсутствующие значения дискриминатора с помощью операторов SQL. Если вы смеете отойти от Hibernate, это, по крайней мере, потребует некоторого изменения кода для удаления этих аннотаций Hibernate, создающих устойчивость к миграции. И это, очевидно, все, что Hibernate волнует в этом случае.
По моему опыту, lockin - это рай, на котором все самые смелые мечты любого лидера рынка, потому что это волшебная палочка макиавелли, которая защищает долю рынка без усилий; таким образом, это делается, когда клиенты не сопротивляются и не влияют на продавца, который выше, чем выгоды, получаемые. Кто сказал, что мир с открытым исходным кодом будет другим?
p.s, просто чтобы избежать путаницы: я никоим образом не связан с каким-либо разработчиком JPA.
p.p.s: то, что я обычно делаю, игнорирует проблему до момента миграции; вы можете затем сформулировать инструкцию SQL UPDATE ... FROM
, используя тот же самый трюк case-switch-with-outer-join, который использует Hibernate для заполнения отсутствующих значений дискриминатора. Это действительно легко, как только вы поняли основной принцип.