From 25d341f297af1bf7f3e3b917e5ecbe95aabb3cbc Mon Sep 17 00:00:00 2001 From: Gavin Date: Wed, 10 May 2023 17:28:07 +0200 Subject: [PATCH] start on inheritance mapping --- .../introduction/Hibernate_Introduction.adoc | 1 + .../main/asciidoc/introduction/Mapping.adoc | 69 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 documentation/src/main/asciidoc/introduction/Mapping.adoc diff --git a/documentation/src/main/asciidoc/introduction/Hibernate_Introduction.adoc b/documentation/src/main/asciidoc/introduction/Hibernate_Introduction.adoc index 8c35413ac1..7c052f7737 100644 --- a/documentation/src/main/asciidoc/introduction/Hibernate_Introduction.adoc +++ b/documentation/src/main/asciidoc/introduction/Hibernate_Introduction.adoc @@ -93,4 +93,5 @@ Naturally, we'll start at the top of this list, with the least-interesting topic include::Configuration.adoc[] include::Entities.adoc[] +include::Mapping.adoc[] diff --git a/documentation/src/main/asciidoc/introduction/Mapping.adoc b/documentation/src/main/asciidoc/introduction/Mapping.adoc new file mode 100644 index 0000000000..055d30776a --- /dev/null +++ b/documentation/src/main/asciidoc/introduction/Mapping.adoc @@ -0,0 +1,69 @@ +[[object-relational-mapping]] +== Object/relational mapping + +Given a domain model—that is, a collection of entity classes decorated with all the fancy annotations we <> in the previous chapter—Hibernate will happily go away and infer a complete relational schema, and even <> if you ask politely. + +The resulting schema will be entirely sane and reasonable, though if you look closely, you'll find some flaws. +For example, every `VARCHAR` column will have the same length, `VARCHAR(255)`. + +But the process I just described—which we call _top down_ mapping—simply doesn't fit the most common scenario for the use of O/R mapping. +It's only rarely that the Java classes precede the relational schema. +Usually, _we already have a relational schema_, and we're constructing our domain model around the schema. +This is called _bottom up_ mapping. + +[NOTE] +."Legacy" data +==== +Developers often refer to a pre-existing relational database as "legacy" data. +That's perhaps a bad word to use, conjuring images of bad old "legacy apps" written in COBOL or something. +But it's not "legacy" data—it's just your data. +And it's valuable. +So learning to work with "legacy" data is important. +==== + +Especially when mapping bottom up, we often need to customize the inferred object/relational mappings. +This is a somewhat tedious topic, and so we don't want to spend too many words on it. +Instead, we'll quickly skim the most important mapping annotations. + +[[mapping-inheritance]] +=== Mapping entity inheritance hierarchies + +In <> we saw that entity classes may exist within an inheritance hierarchy. +There's three basic strategies for mapping an entity hierarchy to relational tables. +Let's put them in a table, so we can more easily compare the points of difference between them. + + +|=== +| Strategy | Mapping | Polymorphic queries | Constraints | Normalization | When to use it + +| `SINGLE_TABLE` +| Map every class in the hierarchy to the same table, and uses the value of a _discriminator column_ to determine which concrete class each row represents. +| To retrieve instances of a given class, we only need to query the one table. +| Attributes declared by subclasses map to columns without `NOT NULL` constraints. 💀 + + Any association may have a `FOREIGN KEY` constraint. 🤓 +| Subclass data is denormalized. 🧐 +| Works well when subclasses declare few or no additional attributes. +| `JOINED` +| Map every class in the hierarchy to a separate table, but each table only maps the attributes declared by the class itself. + + Optionally, a discriminator column may be used. +a| To retrieve instances of a given class, we must `JOIN` the table mapped by the class with: + + - all tables mapped by its superclasses and + - all tables mapped by its subclasses. +| Any attribute may map to a column with a `NOT NULL` constraint. 🤓 + + Any association may have a `FOREIGN KEY` constraint. 🤓 +| The tables are normalized. 🤓 +| The best option when we care a lot about constraints and normalization. +| `TABLE_PER_CLASS` +| Map every concrete class in the hierarchy to a separate table, but denormalize all inherited attributes into the table. +| To retrieve instances of a given class, we must take a `UNION` over the table mapped by the class and the tables mapped by its subclasses. +| Associations targeting a superclass cannot have a corresponding `FOREIGN KEY` constraint in the database. 💀💀 + + Any attribute may map to a column with a `NOT NULL` constraint. 🤓 +| Superclass data is denormalized. 🧐 +| Not very popular. + + From a certain point of view, competes with `@MappedSuperclass`.