JPA: реализация иерархии модели - @MappedSuperclass против @Inheritance
Я использую Play Framework 1.2.4 с PostgreSQL
и JPA
. Я хотел бы иметь иерархию модели и видеть, что есть некоторые альтернативы для этого.
У меня есть базовый класс (который является абстрактным) и два конкретных класса, расширяющих этот базовый класс. Я не хочу упорствовать в этом базовом классе, пока я хочу иметь конкретные классы. В базовом классе у меня есть другие классы Model как свойства, другими словами, у меня есть отношения @ManyToOne
в моем базовом классе.
Мой вопрос - лучший способ реализации этого? Используя @MappedSuperclass
или @Inheritance
с помощью стратегии TABLE_PER_CLASS
? Я немного смущен, поскольку они кажутся практически эквивалентными.
У меня также есть некоторые проблемы с запросами и проблемами производительности, с которыми я могу столкнуться в будущем.
Ответы
Ответ 1
MappedSuperClass необходимо использовать для наследования свойств, ассоциаций и методов.
Наследование Entity должно использоваться, когда у вас есть сущность и несколько сущностей.
Вы можете узнать, нужен ли вам тот или иной вопрос, ответив на следующие вопросы: есть ли в модели какой-то другой объект, который может иметь связь с базовым классом?
Если да, то базовый класс на самом деле является сущностью, и вы должны использовать наследование объекта. Если нет, то базовый класс на самом деле является классом, который содержит атрибуты и методы, которые являются общими для нескольких несвязанных объектов, и вы должны использовать сопоставленный суперкласс.
Например:
- У вас может быть несколько видов сообщений: SMS-сообщения, сообщения электронной почты или телефонные сообщения. И у человека есть список сообщений. У вас также может быть напоминание, связанное с сообщением, независимо от типа сообщения. В этом случае Message явно является сущностью, и необходимо использовать наследование объекта.
- Все объекты вашего домена могут иметь дату создания, дату изменения и идентификатор, и вы можете сделать их наследованием из базового класса AbstractDomainObject. Но ни одна организация никогда не будет ассоциирована с объектом AbstractDomainObject. Он всегда будет ассоциацией с более конкретным лицом: Заказчиком, Компанией, независимо от того. В этом случае имеет смысл использовать MappedSuperClass.
Ответ 2
Как я объяснил в в этой статье, @MappedSupperclass
отличается от аннотации @Inheritance
.
@MappedSuperclass
сообщает провайдеру JPA включить постоянные свойства базового класса, как если бы они были объявлены дочерним классом, расширяющим суперкласс, аннотированный с помощью @MappedSuperclass
.
Однако наследование видимо только в мире ООП, поскольку с точки зрения базы данных нет указания базового класса. Только дочерний объект класса будет иметь сопоставленную сопоставленную таблицу.
Аннотация @Inheritance
предназначена для материализации модели наследования ООП в структуре таблицы базы данных. Более того, вы можете запросить базовый класс, аннотированный с помощью @Inheritance
, но вы не можете сделать это для базового класса, аннотированного с помощью @MappedSuperclass
.
Теперь, почему вы хотите использовать аннотацию @Inheritance
JPA, - это реализовать шаблоны, управляемые поведением, такие как шаблон стратегии.
С другой стороны, @MappedSuperclass
- это просто способ использовать как базовые свойства, ассоциации, так и даже сущность @Id
, используя общий базовый класс. Тем не менее, вы можете достичь почти той же цели, используя тип @Embeddable
. Единственное существенное отличие состоит в том, что вы не можете повторно использовать определение @Id
с помощью @Embeddable
, но вы можете сделать это с помощью @MappedSuperclass
.