Upload
others
View
0
Download
0
Embed Size (px)
Citation preview
Java Persistence API: Inheritance
Mapping Entity Inheritance to the Database
Revision: v2013-10-05Built on: 2019-08-22 07:10 EST
Copyright © 2019 jim stafford ([email protected])
This presentation provides information for mapping Java entity class inheritance to the database
using JPA.
iii
Purpose ............................................................................................................................ v
1. Goals .................................................................................................................... v
2. Objectives ............................................................................................................. v
1. Inheritance Strategy: Single Table .............................................................................. 1
1.1. Single Table Strategy Overview ........................................................................... 1
1.2. Single Table Example Database Schema ............................................................. 1
1.3. Single Table Example Java Mapping ................................................................... 2
1.4. Single Table Example Usage .............................................................................. 3
1.5. @DiscriminatorColumn Annotation ....................................................................... 4
1.6. Summary ............................................................................................................ 5
2. Inheritance Strategy:Table per Concrete Class ........................................................... 7
2.1. Table per Concrete Class Strategy Overview ........................................................ 7
2.2. Table per Concrete Class Example Database Schema .......................................... 7
2.3. Table per Concrete Class Example Java Mapping ................................................ 8
2.4. Table per Concrete Class Example Usage ........................................................... 9
2.5. Summary .......................................................................................................... 10
3. Inheritance Strategy:Join ........................................................................................... 11
3.1. Join Strategy Overview ..................................................................................... 11
3.2. Join Example Database Schema ....................................................................... 11
3.3. Join Example Java Mapping .............................................................................. 12
3.4. Join Example Usage (Persist) ............................................................................ 13
3.5. Summary .......................................................................................................... 14
4. Inheritance Strategy:Non-Entity ................................................................................. 15
4.1. Non-Entity Strategy Overview ............................................................................ 15
4.2. Non-Entity Example Database Schema .............................................................. 15
4.3. Non-Entity Example Java Mapping ..................................................................... 16
4.4. Non-Entity Example Usage (Persist) .................................................................. 17
4.5. Summary .......................................................................................................... 18
5. Mixed Inheritance Strategies ..................................................................................... 21
5.1. Which Strategy Gets Used for Subclass? ........................................................... 21
5.2. Generated Database Schema ............................................................................ 21
5.3. Summary .......................................................................................................... 22
iv
v
Purpose
1. Goals• Introduce mapping entity class inheritance to the database
2. Objectives
At the completion of this topic, the student shall
• have an understanding of:
• Inheritance strategies
• Single Table
• Table per Concrete Class
• Joined
• Mapped Superclass for non-entity parent classes
• be able to:
• Be able to map a Java inheritance relationship using a Single Table strategy
• Be able to map a Java inheritance relationship using a Table per Concrete Class strategy
• Be able to map a Java inheritance relationship using a Table per Subclass (Join) strategy
vi
Chapter 1.
1
Inheritance Strategy: Single Table
1.1. Single Table Strategy Overview
Figure 1.1. Single Table Inheritance Strategy
• Advantages
• Simplest to implement
• Single table to administer
• Performs better than other inheritance strategies
• No complex joins
• Disadvantages
• Unused fields when sub-types have unique properties
• Sub-type columns must be nullable
• Harder to enforce constraints within database
• SQL "check" constraint can help
check(TYPE != 'BREAD_TYPE' or (BAKEDON is not null and SLICES is not null))
check(TYPE != 'Soup' or (SOUPTYPE is not null and EXPIRATION is not null)
• Not normalized
• More suitable for hierarchies with sub-types that...
• Differ primarily in behavior only
• Do not have unique data requirements
1.2. Single Table Example Database Schema
Figure 1.2. Single Table Example Database Schema
create table ORMINH_PRODUCT (
PTYPE varchar(32) not null,
id bigint generated by default as identity,
Chapter 1. Inheritance Strate...
2
cost double not null,
expiration date,
SOUPTYPE varchar(16),
bakedOn date,
slices integer,
primary key (id)
)
• Single table
• No joins
• Unused columns
1.3. Single Table Example Java Mapping
Figure 1.3. Single Table Example Java Mapping (Parent Class)
@Entity @Table(name="ORMINH_PRODUCT")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="PTYPE", //column in root table indicating type
discriminatorType=DiscriminatorType.STRING,//data type of column
length=32) //length of discriminator string
public abstract class Product {
@Id @GeneratedValue
private long id;
private double cost;
...
@Transient
public abstract String getName();
• Parent defines default mapping for all derived types
Figure 1.4. Single Table Example Java Mapping (Annotated Derived)
@Entity
@DiscriminatorValue("BREAD_TYPE") //value placed in root table to indicate type
public class Bread extends Product {
private int slices;
@Temporal(TemporalType.DATE)
private Date bakedOn;
...
@Transient
public String getName() { return "Bread"; }
• Supplies type-specific column value
Figure 1.5. Single Table Example Java Mapping (Default Derived)
@Entity
public class Soup extends Product {
public enum SoupType {
UNKNOWN("Unknown"),
Single Table Example Usage
3
CHICKEN_NOODLE("Chicken Noodle"),
NEW_ENGLAND_CLAM_CHOWDER("New England Clam Chowder"),
TOMATO("Tomato");
private String text;
private SoupType(String text) { this.text = text; }
public String text() { return text; }
};
@Enumerated(EnumType.STRING)
@Column(name="SOUPTYPE", length=16)
private SoupType type = SoupType.UNKNOWN;
@Temporal(TemporalType.DATE)
private Date expiration;
...
@Transient
public String getName() { return type.text() + "Soup"; }
• Accepts default type-specific column value
1.4. Single Table Example Usage
Figure 1.6. Single Table Example Usage (Persist)
ejava.examples.orm.inheritance.annotated.Soup soup = new Soup();
soup.setCost(2.12);
final long lifetime = 365L*24*60*60*1000;
soup.setExpiration(new Date(System.currentTimeMillis() + lifetime));
soup.setSoupType(Soup.SoupType.CHICKEN_NOODLE);
em.persist(soup);
ejava.examples.orm.inheritance.annotated.Bread bread = new Bread();
bread.setBakedOn(new Date());
bread.setCost(2.25);
bread.setSlices(24);
em.persist(bread);
Hibernate:
insert into ORMINH_PRODUCT (id, cost, expiration, SOUPTYPE, PTYPE)
values (null, ?, ?, ?, 'Soup')
Hibernate:
insert into ORMINH_PRODUCT(id, cost, bakedOn, slices, PTYPE)
values (null, ?, ?, ?, 'BREAD_TYPE')
• Two rows inserted into single base table with discriminator type supplied
Figure 1.7. Single Table Example Usage (Get Entities)
List<Product> products = em.createQuery(
"select p from Product p", Product.class)
.getResultList();
assertTrue("unexpected number of products:" + products.size(),
products.size() == 2);
Chapter 1. Inheritance Strate...
4
for(Product p: products) {
log.info("product found:" + p);
}
Hibernate:
select
product0_.id as id2_9_,
product0_.cost as cost3_9_,
product0_.expiration as expirati4_9_,
product0_.SOUPTYPE as SOUPTYPE5_9_,
product0_.bakedOn as bakedOn6_9_,
product0_.slices as slices7_9_,
product0_.PTYPE as PTYPE1_9_
from
ORMINH_PRODUCT product0_
-product found:Soup, id=1, cost=2.12, type=CHICKEN_NOODLE, expiration=2014-10-05
-product found:Bread, id=2, cost=2.25, slices=24, baked=2013-10-05
• Single table queried for objects
Figure 1.8. Single Table Example Usage (Verify DB Schema)
//query specific tables for columns
int rows = em.createNativeQuery(
"select ID, TYPE, COST, SOUPTYPE, EXPIRATION, BAKEDON, SLICES " +
" from ORMINH_PRODUCT")
.getResultList().size();
assertEquals("unexpected number of product rows:" + rows, 2, rows);
select * from ORMINH_PRODUCT
PTYPE ID COST BAKEDON SLICES EXPIRATION SOUPTYPE
---------- -- ---- ---------- ------ ---------- --------------
Soup 1 2.12 (null) (null) 2007-10-08 CHICKEN_NOODLE
BREAD_TYPE 2 2.25 2006-10-08 24 (null) (null)
• Single table "sparsely" filled based on type
1.5. @DiscriminatorColumn Annotation
@DiscriminatorColumn defines column to hold type-specific value
name (default="DTYPE")
Column name
discriminatorType
STRING (defaults to Entity.name)
Only portable technique when accepting default
CHAR
Vendor-specific value when accepting default
Summary
5
INTEGER
Vendor-specific value when accepting default
columnDefinition
Database-specific definition for when generating schema
length
Size of STRING
1.6. Summary• Single table represents all sub-classes
• Discriminator columns used to distinguish between types
• No joins
• Good choice when no/minor differences in subclass properties
• Bad choice when subclasses differ greatly in subclass properties
6
Chapter 2.
7
Inheritance Strategy:Table per
Concrete Class
2.1. Table per Concrete Class Strategy Overview
Figure 2.1. Table per Concrete Class Inheritance Strategy
• Advantages
• May have constrained columns
• No joins when accessing a single concrete type
• Disadvantages
• Not normalized
• Redundant columns in each concrete child table
• More work required to query across tables
• Requires use of SQL "UNION"
• Least desirable from a performance/portability standpoint
• More suitable for ...
• Sub-types not needed to be manipulated with sibling other sub-types
2.2. Table per Concrete Class Example Database
Schema
Figure 2.2. Table per Concrete Class Example Database Schema
create table ORMINH_CHECKING (
Chapter 2. Inheritance Strate...
8
id bigint not null,
balance double not null,
fee double not null,
primary key (id)
)
create table ORMINH_INTERESTACCT (
id bigint not null,
balance double not null,
rate double not null,
primary key (id)
)
create sequence ORMINH_SEQ
• Table for each concrete class
• No separate table for parent class
• Parent columns repeated in concrete sub-class tables
• * his particular example uses SEQUENCE for primary key generation
2.3. Table per Concrete Class Example Java Mapping
Figure 2.3. Table per Concrete Class Example Java Mapping (Parent Class)
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
@SequenceGenerator(
name="orminhSeq", //required logical name
sequenceName="ORMINH_SEQ" //name in database
)
public abstract class Account {
@Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="orminhSeq")
private long id;
private double balance;
...
public void deposit(double amount) throws AccountException {
setBalance(getBalance() + amount);
}
public abstract void withdraw(double amount) throws AccountException;
...
• Parent defines default mapping for all derived types, including PK generation
• Using a common SEQUENCE allows sub-classes to have unique PKs across all tables
Figure 2.4. Table per Concrete Class Example Java Mapping (Subclasses)
@Entity
@Table(name="ORMINH_CHECKING")
public class CheckingAccount extends Account {
private double fee;
public void withdraw(double amount) throws AccountException {
super.setBalance(super.getBalance() - fee);
Table per Concrete Class Example Usage
9
}
@Entity
@Table(name="ORMINH_INTERESTACCT")
public class InterestAccount extends Account {
private double rate;
public void withdraw(double amount) throws AccountException {
super.setBalance(super.getBalance() - amount);
}
• Subclasses name their specific entity class table
2.4. Table per Concrete Class Example Usage
Figure 2.5. Table per Concrete Class Example Usage (Persist)
ejava.examples.orm.inheritance.annotated.CheckingAccount checking = new CheckingAccount();
checking.setFee(0.50);
em.persist(checking);
ejava.examples.orm.inheritance.annotated.InterestAccount savings = new InterestAccount();
savings.setRate(0.25);
em.persist(savings);
Hibernate:
call next value for ORMINH_SEQ
Hibernate:
insert into ORMINH_CHECKING (balance, fee, id)
values (?, ?, ?)
Hibernate:
insert into ORMINH_INTERESTACCT (balance, rate, id)
values (?, ?, ?)
• Rows for entities placed into separate tables
Figure 2.6. Table per Concrete Class Example Usage (Get Entities)
List<Account> accounts =em.createQuery("select a from Account a").getResultList();
assertTrue("unexpected number of accounts:" + accounts.size(), accounts.size() == 2);
for(Account a: accounts) {
log.info("account found:" + a);
}
select
account0_.id as id1_0_,
account0_.balance as balance2_0_,
account0_.rate as rate1_7_,
account0_.fee as fee1_2_,
account0_.clazz_ as clazz_
Chapter 2. Inheritance Strate...
10
from (
select id, balance, rate, null as fee, 1 as clazz_
from ORMINH_INTERESTACCT
union all
select id, balance, null as rate, fee, 2 as clazz_
from ORMINH_CHECKING
) account0_
-account found:InterestAccount, id=51, balance=0.0, rate=0.25
-account found:CheckingAccount, id=50, balance=0.0, fee=0.5
• Query through parent type causes SQL "UNION ALL" of each concrete sub-class table
Figure 2.7. Table per Concrete Class Example Usage (Verify DB Schema)
//query specific tables for columns
int rows = em.createNativeQuery(
"select ID, BALANCE, FEE from ORMINH_CHECKING")
.getResultList().size();
assertEquals("unexpected number of checking rows:" + rows, 1, rows);
rows = em.createNativeQuery(
"select ID, BALANCE, RATE from ORMINH_INTERESTACCT")
.getResultList().size();
assertEquals("unexpected number of interestacct rows:" + rows, 1, rows);
select * from ORMINH_CHECKING
ID BALANCE FEE
-- ------- ---
50 0.0 0.5
select * from ORMINH_INTERESTACCT
ID BALANCE RATE
-- ------- ----
51 0.0 0.25
• Table per concrete class
• No unused columns
• Parent columns repeated in each sub-class table
2.5. Summary• Properties pushed down to each concrete class' table
• Requires no joins
• Requires SQL "UNION ALL" of all concrete class table to access common properties across
hierarchy
Chapter 3.
11
Inheritance Strategy:Join
3.1. Join Strategy Overview
Figure 3.1. Joined Inheritance Strategy
• Advantages
• Can be normalized
• Permits constraints to be defined
• Disadvantages
• Requires access to multiple tables when using (insert, select, update, and delete) an entity
• More suitable for sub-classes that...
• Have many unique properties
• Require database constraints
• Are queried for across sibling sub-types
3.2. Join Example Database Schema
Figure 3.2. Join Example Database Schema
create table ORMINH_PERSON (
id bigint generated by default as identity,
firstName varchar(255),
Chapter 3. Inheritance Strate...
12
lastName varchar(255),
primary key (id)
)
create table ORMINH_EMPLOYEE (
hireDate date,
payrate double not null,
id bigint not null,
primary key (id)
)
alter table ORMINH_CUSTOMER
add constraint FK6D5464A42122B7AC
foreign key (id)
references ORMINH_PERSON
alter table ORMINH_EMPLOYEE
add constraint FK9055CB742122B7AC
foreign key (id)
references ORMINH_PERSON
• Table for each entity class is created
• Each table has a primary key
• Sub-class tables use a primary key join with parent class
3.3. Join Example Java Mapping
Figure 3.3. Join Example Java Mapping (Parent Class)
@Entity @Table(name="ORMINH_PERSON")
@Inheritance(strategy=InheritanceType.JOINED)
public class Person {
@Id @GeneratedValue
private long id;
private String firstName;
private String lastName;
• Parent defines default mapping for all derived types
• Parent entity class table also defined
Figure 3.4. Join Example Java Mapping (Subclasses)
@Entity
@Table(name="ORMINH_CUSTOMER") //joined with Person table to form Customer
public class Customer extends Person {
public enum Rating { GOLD, SILVER, BRONZE }
@Enumerated(EnumType.STRING)
private Rating rating;
@Entity
@Table(name="ORMINH_EMPLOYEE") //joined with Person table to form Employee
public class Employee extends Person {
private double payrate;
@Temporal(TemporalType.DATE)
Join Example Usage (Persist)
13
private Date hireDate;
• Sub-classes define their entity-specific tables
3.4. Join Example Usage (Persist)
Figure 3.5. Join Example Usage
ejava.examples.orm.inheritance.annotated.Employee employee = new Employee();
employee.setFirstName("john");
employee.setLastName("doe");
employee.setHireDate(new Date());
employee.setPayrate(10.00);
em.persist(employee);
ejava.examples.orm.inheritance.annotated.Customer customer = new Customer();
customer.setFirstName("jane");
customer.setLastName("johnson");
customer.setRating(Customer.Rating.SILVER);
em.persist(customer);
Hibernate:
insert into ORMINH_PERSON (id, firstName, lastName)
values (null, ?, ?)
Hibernate:
insert into ORMINH_EMPLOYEE (hireDate, payrate, id)
values (?, ?, ?)
Hibernate:
insert into ORMINH_PERSON (id, firstName, lastName)
values (null, ?, ?)
Hibernate:
insert into ORMINH_CUSTOMER (rating, id)
values (?, ?)
• Each persist() must insert into concrete class table and parent class table(s)
Figure 3.6. Join Example Usage (Get Entities)
List<Person> people = em.createQuery("select p from Person p", Person.class).getResultList();
assertTrue("unexpected number of people:" + people.size(),
people.size() == 2);
for(Person p: people) {
log.info("person found:" + p);
}
select
person0_.id as id1_8_,
person0_.firstName as firstNam2_8_,
person0_.lastName as lastName3_8_,
person0_1_.hireDate as hireDate1_6_,
person0_1_.payrate as payrate2_6_,
person0_2_.rating as rating1_5_,
Chapter 3. Inheritance Strate...
14
case
when person0_1_.id is not null then 1
when person0_2_.id is not null then 2
when person0_.id is not null then 0
end as clazz_
from ORMINH_PERSON person0_
left outer join ORMINH_EMPLOYEE person0_1_
on person0_.id=person0_1_.id
left outer join ORMINH_CUSTOMER person0_2_
on person0_.id=person0_2_.id
-person found:Employee, id=1, firstName=john, lastName=doe, payrate=10.0
-person found:Customer, id=2, firstName=jane, lastName=johnson, rating=SILVER
• Parent class table joined with each sub-class table during query of parent type
Figure 3.7. Join Example Usage (Verify DB Schema)
int rows = em.createNativeQuery(
"select ID, FIRSTNAME, LASTNAME from ORMINH_PERSON")
.getResultList().size();
assertEquals("unexpected number of person rows:" + rows, 2, rows);
rows = em.createNativeQuery(
"select ID, RATING from ORMINH_CUSTOMER")
.getResultList().size();
assertEquals("unexpected number of customer rows:" + rows, 1, rows);
rows = em.createNativeQuery(
"select ID, PAYRATE, HIREDATE from ORMINH_EMPLOYEE")
.getResultList().size();
assertEquals("unexpected number of employee rows:" + rows, 1, rows);
select * from ORMINH_PERSON
ID FIRSTNAME LASTNAME
-- --------- --------
1 john doe
2 jane johnson
select * from ORMINH_EMPLOYEE
ID HIREDATE PAYRATE
-- ---------- -------
1 2006-10-08 10.0
select * from ORMINH_CUSTOMER
ID RATING
-- ------
2 SILVER
• Entities span multiple tables
3.5. Summary• Each class is mapped to a separate table
• Tables are joined together (by primary key join default)
• Very similar to @OneToOne relation using @PrimaryKeyJoinColumn
Chapter 4.
15
Inheritance Strategy:Non-Entity
4.1. Non-Entity Strategy Overview
Figure 4.1. Non-Entity Inheritance Strategy
• Advantages
• Allows inheritance of non-entity classes
• Disadvantages
• No base entity to form queries across hierarchy (unlike TABLE_PER_CLASS)
• Tables not normalized (like TABLE_PER_CLASS)
• Parent columns repeated in each subclass table
• More suitable for ...
• Independent subclasses
4.2. Non-Entity Example Database Schema
Figure 4.2. Non-Entity Example Database Schema
create table ORMINH_ALBUM (
ALBUM_ID bigint generated by default as identity,
ALBUM_VERSION bigint,
artist varchar(255),
title varchar(255),
primary key (ALBUM_ID)
)
create table ORMINH_TOOTHPASTE (
id bigint generated by default as identity,
Chapter 4. Inheritance Strate...
16
version bigint not null,
size integer not null,
primary key (id)
)
• Non-entity base class properties appear in subclass tables
4.3. Non-Entity Example Java Mapping
Figure 4.3. Non-Entity Example Java Mapping (Parent Class)
@MappedSuperclass
public abstract class BaseObject {
private long id;
@Access(AccessType.FIELD)
private long version;
@Transient
public long getId() { return id; }
protected void setId(long id) {
this.id = id;
}
• Parent class is not a legal entity -- has no @Id
Note
In this example, the implementation of BaseObject actually has an id attribute
that the derived classes make use of. However, it is marked as @Transient in
the base class and @Id in the derived Entity classes since MappedSuperClasses
do not have primary keys. This specific example could have also used
TABLE_PER_CLASS because of the availability of an id property in the base class.
Figure 4.4. Non-Entity Example Java Mapping (Override Defaults)
@Entity
@Table(name="ORMINH_ALBUM") //this table holds both this entity and parent class
@AttributeOverrides({
@AttributeOverride(name="version", column=@Column(name="ALBUM_VERSION"))
})
public class Album extends BaseObject {
@Access(AccessType.FIELD)
private String artist;
@Access(AccessType.FIELD)
private String title;
@Id @GeneratedValue //id is being generated independent of other siblings
@Column(name="ALBUM_ID")
public long getId() { return super.getId(); }
protected void setId(long id) {
super.setId(id);
Non-Entity Example Usage (Persist)
17
}
• "version" column name from parent being renamed
• "id" property defined in this class given custom column name
• Transient attribute in parent being reused to hold @Id for subclass using PROPERTY access
Figure 4.5. Non-Entity Example Java Mapping (Default Derived)
@Entity
@Table(name="ORMINH_TOOTHPASTE") //table holds this entity and parent class
public class ToothPaste extends BaseObject {
@Access(AccessType.FIELD)
private int size;
@Id @GeneratedValue //id is being generated independent of other siblings
public long getId() { return super.getId(); }
protected void setId(long id) {
super.setId(id);
}
• Entity accepts mapping defaults
4.4. Non-Entity Example Usage (Persist)
Figure 4.6. Non-Entity Example Usage
ejava.examples.orm.inheritance.annotated.Album album = new Album();
album.setArtist("Lynyrd Skynyrd");
album.setTitle("One More for the Road");
em.persist(album);
ejava.examples.orm.inheritance.annotated.ToothPaste toothpaste = new ToothPaste();
toothpaste.setSize(10);
em.persist(toothpaste);
Hibernate:
insert into ORMINH_ALBUM (ALBUM_ID, ALBUM_VERSION, artist, title)
values (null, ?, ?, ?)
Hibernate:
insert into ORMINH_TOOTHPASTE (id, version, size)
values (null, ?, ?)
• Rows are inserted into type-specific entity class tables
Figure 4.7. Non-Entity Example Usage (Get Entities)
List<BaseObject> objects = em.createQuery("select a from Album a").getResultList();
objects.addAll( em.createQuery("select tp from ToothPaste tp").getResultList());
assertTrue("unexpected number of objects:" + objects.size(), objects.size() == 2);
Chapter 4. Inheritance Strate...
18
for(BaseObject o: objects) {
log.info("object found:" + o);
}
Hibernate:
select
album0_.ALBUM_ID as ALBUM1_1_,
album0_.ALBUM_VERSION as ALBUM2_1_,
album0_.artist as artist3_1_,
album0_.title as title4_1_
from ORMINH_ALBUM album0_
Hibernate:
select
toothpaste0_.id as id1_12_,
toothpaste0_.version as version2_12_,
toothpaste0_.size as size3_12_
from ORMINH_TOOTHPASTE toothpaste0_
-object found:ejava.examples.orm.inheritance.annotated.Album@3822f407, id=1, name=Lynyrd Skynyrd:One More for
the Road
-object found:ejava.examples.orm.inheritance.annotated.ToothPaste@22a79bc, id=1, name=10oz toothpaste
• Separate tables are accessed when obtaining each type
Figure 4.8. Non-Entity Example Usage (Verify DB Schema)
int rows = em.createNativeQuery(
"select ALBUM_ID, ALBUM_VERSION, ARTIST, TITLE " +
" from ORMINH_ALBUM")
.getResultList().size();
assertEquals("unexpected number of album rows:" + rows, 1, rows);
rows = em.createNativeQuery(
"select ID, VERSION, SIZE " +
" from ORMINH_TOOTHPASTE")
.getResultList().size();
assertEquals("unexpected number of toothpaste rows:" + rows, 1, rows);
select * from ORMINH_ALBUM
ALBUM_ID ALBUM_VERSION ARTIST TITLE
-------- ------------- -------------- ---------------------
1 0 Lynyrd Skynyrd One More for the Road
select * from ORMINHTOOTHPASTE
ID VERSION SIZE
-- ------- ----
1 0 10
• Separate tables per concrete class (like TABLE_PER_CLASS)
• No unused columns (like TABLE_PER_CLASS)
4.5. Summary• Similar mapping to TABLE_PER_CLASS
Summary
19
• Parent class not an @Entity
• Parent/base class not mapped -- cannot use as query type
20
Chapter 5.
21
Mixed Inheritance Strategies
5.1. Which Strategy Gets Used for Subclass?
Figure 5.1. Mixed Inheritance Strategy
5.2. Generated Database Schema
Figure 5.2. Generated Database Schema
create table ORMINH_SHAPE (
id bigint generated by default as identity,
version bigint not null,
posx integer not null,
posy integer not null,
primary key (id)
)
create table ORMINH_CIRCLE (
radius integer not null,
Chapter 5. Mixed Inheritance ...
22
id bigint not null,
primary key (id)
)
create table ORMINH_RECTANGLE (
height integer not null,
width integer not null,
id bigint not null,
primary key (id)
)
alter table ORMINH_CIRCLE
add constraint FKFF2F1F1632C97600
foreign key (id)
references ORMINH_SHAPE
alter table ORMINH_RECTANGLE
add constraint FK1FFF614932C97600
foreign key (id)
references ORMINH_SHAPE
create table ORMINH_CUBE (
depth integer not null,
id bigint not null,
primary key (id)
)
alter table ORMINH_CUBE
add constraint FK84203FB112391CE
foreign key (id)
references ORMINH_RECTANGLE
• Provider used parent's JOIN strategy over child's TABLE_PER_CLASS specification
5.3. Summary• Provider behavior undefined by spec
• Leverage DAOs to bridge the mis-match between legacy DB schema and Java class model