web-dev-qa-db-fra.com

JPA: Implémentation de la hiérarchie des modèles - @MappedSuperclass vs. @Inheritance

J'utilise Play Framework 1.2.4 avec PostgreSQL et JPA. J'aimerais avoir une hiérarchie de modèles et voir qu'il existe des alternatives à cela.

J'ai une classe de base (qui est abstraite) et deux classes concrètes étendant cette classe de base. Je ne veux pas persister cette classe de base alors que je veux avoir des classes concrètes. Dans la classe de base, j'ai d'autres classes Model en tant que propriétés, en d'autres termes, j'ai @ManyToOne relations dans ma classe de base.

Ma question est quelle est la meilleure façon de mettre en œuvre cela? En utilisant @MappedSuperclass ou @Inheritance avec TABLE_PER_CLASS stratégie? Je suis un peu confus car ils semblent pratiquement équivalents.

J'ai également quelques inquiétudes concernant les problèmes d'interrogation et de performances auxquels je pourrais être confronté à l'avenir.

57
huzeyfe

MappedSuperClass doit être utilisé pour hériter des propriétés, des associations et des méthodes.

L'héritage d'entité doit être utilisé lorsque vous avez une entité et plusieurs sous-entités.

Vous pouvez dire si vous avez besoin de l'une ou de l'autre en répondant à ces questions: y a-t-il une autre entité dans le modèle qui pourrait avoir une association avec la classe de base?

Si oui, la classe de base est en fait une entité et vous devez utiliser l'héritage d'entité. Si non, la classe de base est en fait une classe qui contient des attributs et des méthodes communs à plusieurs entités non liées, et vous devez utiliser une superclasse mappée.

Par exemple:

  • Vous pouvez avoir plusieurs types de messages: SMS messages, e-mails ou messages téléphoniques. Et une personne a une liste de messages. Vous pouvez également avoir un rappel lié à un message, quel que soit le Dans ce cas, Message est clairement une entité, et l'héritage d'entité doit être utilisé.
  • Tous vos objets de domaine peuvent avoir une date de création, une date de modification et un ID, et vous pouvez ainsi les faire hériter d'une classe AbstractDomainObject de base. Mais aucune entité n'aura jamais d'association à un AbstractDomainObject. Ce sera toujours une association à une entité plus spécifique: Client, Entreprise, peu importe. Dans ce cas, il est logique d'utiliser une MappedSuperClass.
120
JB Nizet

Comme je l'ai expliqué dans cet article , @MappedSupperclass est différent de @Inheritance annotation.

@MappedSuperclass indique au fournisseur JPA d'inclure les propriétés persistantes de la classe de base comme si elles avaient été déclarées par la classe enfant étendant la superclasse annotée avec @MappedSuperclass.

Cependant, l'héritage n'est visible que dans le monde OOP, car, du point de vue de la base de données, il n'y a aucune indication de la classe de base. Seule l'entité de classe enfant aura une table mappée associée.

Le @Inheritance l'annotation est destinée à matérialiser le modèle d'héritage OOP dans la structure de la table de base de données. De plus, vous pouvez interroger une classe de base annotée avec @Inheritance mais vous ne pouvez pas faire cela pour une classe de base annotée avec @MappedSuperclass.

Maintenant, la raison pour laquelle vous souhaitez utiliser le @Inheritance L'annotation JPA consiste à implémenter des modèles basés sur le comportement comme le modèle de stratégie .

D'autre part, @MappedSuperclass n'est qu'un moyen de réutiliser à la fois les propriétés de base, les associations et même l'entité @Id en utilisant une classe de base commune. Néanmoins, vous pouvez atteindre presque le même objectif en utilisant un @Embeddable type. La seule différence majeure est que vous ne pouvez pas réutiliser un @Id définition avec @Embeddable, mais vous pouvez le faire avec @MappedSuperclass.

13
Vlad Mihalcea