Given a domain model—that is, a collection of entity classes decorated with all the fancy annotations we just met in the previous chapter—Hibernate will happily go away and infer a complete relational schema, and even export it to your database 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.
In [entity-inheritance] 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 |
---|---|---|---|---|---|
|
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 Any association may have a |
Subclass data is denormalized. 🧐 |
Works well when subclasses declare few or no additional attributes. |
|
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. |
To retrieve instances of a given class, we must
|
Any attribute may map to a column with a Any association may have a |
The tables are normalized. 🤓 |
The best option when we care a lot about constraints and normalization. |
|
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 |
Associations targeting a superclass cannot have a corresponding Any attribute may map to a column with a |
Superclass data is denormalized. 🧐 |
Not very popular. From a certain point of view, competes with |