Спящий режим на две группы на одну сущность
У меня есть одна сущность - User
. Он описывается User.class
.
Hibernate создает одну таблицу для каждого объекта, поэтому, когда я вызываю session.save(user)
, мои данные всегда сохраняются в этой таблице.
Теперь мне нужна другая таблица для данных того же типа User
, и мне нужно сохранить мой объект только в этой таблице.
Структура данных (что-то вроде этого):
table users_1_table{
string id;
string username;
}
table users_2_table{
string id;
string username;
}
работать с этим:
session.save(user1,"users_1_table")
session.save(user2,"users_2_table")
и в результате я должен иметь user1
в users_1_table
и user2
в users_2_table
.
Из-за системного ограничения я не могу поместить эти два объекта в одну таблицу. (Даже создание дополнительного поля - плохая идея).
Могу ли я сделать это без подкласса? Использование программной конфигурации спящего режима?
Ответы
Ответ 1
Предисловие:
Это часто задаваемый вопрос даже в отношении SO, а также ответы на многие вопросы связаны с Subclass
или фактически SuperClass
подходом (например, [1])
Фактический ответ:
В этих сообщениях [2], [3] они предлагают использовать сопоставление xml с параметром EntityName
.
Итак, для сопоставления с xml вам не нужен суперкласс, просто задайте параметр EntityName
двум одинаковым сопоставлениям.
Пример сопоставления:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="DomainModel.User, DomainModel"
table="User1Object" entity-name="User1Object">
<id name="_id" access="field" column="id">
<generator class="assigned"/>
</id>
<property name= ...>
</class>
<class name="DomainModel.User, DomainModel"
table="User2Object" entity-name="User2Object">
<id name="_id" access="field" column="id">
<generator class="assigned"/>
</id>
<property name= ...>
</class>
</hibernate-mapping>
Затем, в зависимости от того, какой тип сущности вам нужен, вы вызываете соответствующие методы сеанса как:
_session.Save("User1Object", user1)
или
_session.Save("User2Object", user2)
Сообщения 2 и 3 были использованы в качестве основы для этого фрагмента. Официальный источник [4]
После матча:
В одном ответе на первый вопрос, который фактически является ссылкой на этот пост [5], существует другой подход:
Вы говорите "пока" первому экземпляру объекта, клонируете данные в новый экземпляр и сохраняете это с другим именем. Таким образом, нет нарушений в логике Hibernate и всем содержимом: одни и те же данные в двух таблицах и никакие подклассы не используются.
Что ж, реализация, или код, или доверие к этому подходу такие-то, я их не проверял.
Другой случай:
В этом посте [6] есть еще один человек, пытающийся оспаривать подход суперкласса с помощью чего-то более простого, но, опять же, самый надежный ответ гласит, что это невозможно с другой стороны, официальный Подход xml - это упомянутый подход подкласса.
Источники
[1] Как сопоставить один класс разным таблицам с помощью аннотаций hibernate/jpa
[2] Сопоставить две одинаковые таблицы (одну и ту же схему...) с одним и тем же объектом в Hibernate
[3] Как сопоставить 2 одинаковые таблицы (одинаковые свойства) с 1 объектом
[4] http://docs.jboss.org/hibernate/core/3.2/reference/en/html/mapping.html#mapping-entityname
[5] Hibernate 4: отображение одного класса. Две таблицы. Как сохранить один объект в обеих таблицах?
[6] Hibernate Аннотация для сущности существует более чем в 1 каталоге
Ответ 2
Также он работает с использованием объекта по умолчанию и альтернативного:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="DomainModel.User, DomainModel"
table="User1Object">
<id name="_id" access="field" column="id">
<generator class="assigned"/>
</id>
<property name= ...>
</class>
<class name="DomainModel.User, DomainModel"
table="User2Object" entity-name="User2Object">
<id name="_id" access="field" column="id">
<generator class="assigned"/>
</id>
<property name= ...>
</class>
</hibernate-mapping>
Для стандартного метода вы можете использовать метод
_session.Save(user1)
и
_session.Save("User2Object", user2)
для альтернативного.
Ответ 3
Вы можете сделать это с помощью конфигурации:
- Создайте два сопоставления для одного и того же класса сущностей
name
, но укажите им разные логические entity-name
и таблицу.
- Затем используйте методы
Session
, где вы указываете entityName
как параметр, чтобы отличать один от другого.
Что это достигается?
- "Виртуальный подтипирование"
- При извлечении данных в тип необходимо указать один
entity-type
или другой (таким образом, подразумевая одну таблицу или другую)
- Когда вы изменяете данные и сохраняете их, вы должны указать один и тот же
entity-type
- попытка смены другого entity-type
должна быть отклонена спящим режимом. В противном случае модифицированные объекты уже будут заполнены идентификатором, поэтому hibernate будет пытаться обновить, а не вставлять, но это приведет к сбою в базе данных - попытка обновить данные, которые никогда не существовали в таблице.
- Это приводит к сегрегации - вы должны зафиксировать один тип сущности при работе над сущностью или списком сущностей и не можете смешивать их. то есть "виртуальный подтипирование"
Каковы затраты?
- Это дает очень слабую типизацию. Компилятор и среда выполнения не имеют указаний на истинный подтип. Ошибки ждут и могут быть сложными для отладки.
- Это нестандартное. JPA справилась с этим, я считаю, что это не для радара для включения, и по уважительной причине.
- Вы должны использовать XML, а не аннотации.
- Вы должны вызывать необычные методы, включая параметр "тип сущности".
Есть ли преимущества над подтипированием?
Должны ли вы это сделать?
- Я так не думаю! Используйте подтипирование и стандартный код.
Ответ 4
Хотя я никогда не пользовался, но есть концепция вторичной таблицы в спящем режиме. А @SecondaryTables - это аннотация в спящем режиме, с помощью которой сущность может отображать более одной таблицы для извлечения данных. Объект, который извлекает данные, должен иметь аннотации @SecondaryTables. Он связывает вторичную таблицу на основе первичного и внешнего ключей, а также на основе уникальных ограничений.
Вот один образец, который я нашел после выполнения google, проверьте, помогает ли это вам:
http://www.concretepage.com/hibernate/secondarytables_hibernate_annotation.php
Ответ 5
Я знаю, что этот вопрос задавали давно. Но я хотел бы предложить альтернативный способ, без использования каких-либо спящих вещей. Для тех, кто не хочет использовать конфигурацию XML.
Объявите интерфейс с методами getter и setter для столбцов commun, а затем заставьте свои классы сущностей tow реализовать этот интерфейс.
Оставьте аннотации сопоставления в этом классе двух сущностей как обычно, затем в своем коде вы можете вместо этого вызывать метод этого интерфейса.