2010-06-17 4 views
3

У меня есть подкласс и суперкласс. Однако необходимо сохранить только поля суперкласса.Персистский подкласс как суперкласс с использованием Hibernate

session.saveOrUpdate((Superclass) subclass); 

Если я сделаю это, я получу следующее исключение.

org.hibernate.MappingException: Unknown entity: test.Superclass 
    at org.hibernate.impl.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:628) 
    at org.hibernate.impl.SessionImpl.getEntityPersister(SessionImpl.java:1366) 
    at org.hibernate.engine.ForeignKeys.isTransient(ForeignKeys.java:203) 
    at org.hibernate.event.def.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:535) 
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:103) 
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93) 
    at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:535) 
    at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:527) 
    at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:523) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:342) 
    at $Proxy54.saveOrUpdate(Unknown Source) 

Как я могу сохранить подкласс как суперкласс? Я не предпочитаю создавать экземпляр суперкласса, а затем передавать значения из экземпляра подкласса. Потому что легко забыть обновлять логику, если в будущем добавляются дополнительные поля в суперкласс.

+0

Действительно ли надпись «Суперкласс»? Исключение указывает на то, что это не так. –

+0

Ooops, это должно быть «org.hibernate.MappingException: Неизвестный объект: test.Subclass». – franziga

ответ

1

То, что вы пытаетесь достичь, вызовет у вас много проблем. Представьте, что произойдет, если вы снова загрузите данные. Какой класс должен использовать Hibernate? Суперкласс? Или один из подклассов? Который из?

Я предлагаю сопоставить суперкласс непосредственно, а затем использовать delegate pattern для реализации расширенной функциональности (в основном превращая ваш суперкласс в объект данных, который передается в «рабочие» экземпляры).

+0

Я буду загружать данные только в суперкласс. Ваше предложение также требует уведомления об обновлении делегирования, если суперкласс добавляет дополнительные поля. – franziga

0

Мне также интересно узнать, как это сделать. Вот мотивирующий случай. Предположим, у меня есть объект User для представления пользователя в моем приложении. Пользовательский объект имеет несколько свойств, таких как имя пользователя, пароль, адрес электронной почты, имя и т. Д., Которые я буду хранить в базе данных.

Когда я создаю экран, который позволяет пользователю редактировать свой собственный профиль, я хочу установить флажок «Изменить пароль», чтобы я мог отображать/скрывать поле пароля, а также хочу «подтвердить» пароль ", чтобы они не ошибочно вводили его. Я не хочу хранить эти свойства в базе данных, и они не являются частью объекта User, поэтому я не хочу, чтобы эти поля существовали в User. Тем не менее, многие веб-фреймворки упрощают сбор страницы формы на основе объекта, который редактируется.

Способ, которым я хотел бы решить это сделать подкласс пользователя, назовем его EditableUser, который имеет несколько дополнительных полей, таких как «changePassword» и «confirmPassword», и использовать этот объект в моей форме. Но проблема в том, что Hibernate не будет знать, как сохранить объект EditableUser. (Это также проблема создания EditableUser от пользователя, загружаемого из базы данных, но это можно сделать, если у вас есть конструктор копирования)

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

2

Существует тип решения этой проблемы, и это на самом деле покрыта здесь, на StackOverflow:

Hibernate/NHibernate : how to persist subclass as instance of superclass

Hibernate Documentation

По сути вы просто сказать Hibernate, чтобы сохранить класс как суперкласс с помощью строка для суперкласса типа:

session.save ("my.superclass", подкласс);

Это может не работать во всех случаях использования, но для меня это был всего лишь билет.

Смежные вопросы