Yes, there are few ways to map such scenario. JPA provides support for three different data representations:
- single-table strategy
- joined strategy
- table-per-class strategy
In other words depending on inheritance type used you will get different database model. Various JPA providers may support additional inheritance strategies.
Consider the following example:
@Entity
@Inheritance //by default SINGLE_TABLE strategy
@DiscriminatorColumn( //not supported for TABLE_PER_CLASS strategy
name = "BUS_TYPE",
discriminatorType = DiscriminatorType.INTEGER
)
public abstract class Bus {
@Id
protected int id;
protected int seats;
public Bus() {
}
}
@Entity
@DiscriminatorValue(value = "1") //not supported for TABLE_PER_CLASS strategy
public class BusSubClass1 extends Bus {
private String specific1;
public BusSubClass1() {
}
}
@Entity
@DiscriminatorValue(value = "2") //not supported for TABLE_PER_CLASS strategy
public class BusSubClass2 extends Bus {
@Temporal
private Data specific2;
public BusSubClass2() {
}
}
Using InheritanceType.SINGLE_TABLE
strategy leads to a single database table containing all concrete entity types:
Bus
ID BUS_TYPE SEATS SPECIFIC1 SPECIFIC2
-- -------- ----- --------- ---------
1 1 50 qwerty
2 1 55 asdfgh
3 2 30 2014-01-01
- every concrete entity instance in the inheritance hierarchy is distinguished by discriminator value (here indicated by BUS_TYPE column)
- all database columns must be declared as nullable because not all of them may contain values (thus may be problematic for columns that cannot be set to null)
- wide or deep hierarchy may affect performance (a lot of redundant columns or rows respectively in a table)
- lack of normalization can waste space in database table
- offers good performance for read and write operations (polymorphic queries don't require joins, only discriminator value)
- adding/removing entity fields may be problematic (from database administration point of view)
Using InheritanceType.JOINED
strategy leads to multiple database tables per entity type (all shared fields from Bus
are stored in the corresponding table):
Bus BusSubClass1 BusSubClass2
ID BUS_TYPE SEATS ID SPECIFIC1 ID SPECIFIC2
-- -------- ----- -- --------- -- ---------
1 1 50 1 qwerty 3 2014-01-01
2 1 55 2 asdfgh
3 2 30
- every concrete entity class in the inheritance hierarchy is distinguished by the discriminator value (here indicated by BUS_TYPE column)
- normalization improves data storage (less unused space in comparison to SINGLE_TABLE strategy)
- non-polymorphic queries (for a single concrete entity) require a join
- polymorphic queries (for wide or deep hierarchy of entity classes) require multiple joins and may be expensive
- adding/removing entity fields is rather straightforward (from database administration point of view)
Using InheritanceType.TABLE_PER_CLASS
strategy leads to exqactly one database table per entity type (all shared fields from Bus
are redefined in the concrete subclasses):
BusSubClass1 BusSubClass2
ID SEATS SPECIFIC1 ID SEATS SPECIFIC2
-- ----- --------- -- ----- ---------
1 50 qwerty 3 30 2014-01-01
2 55 asdfgh
- every concrete entity class in the inheritance hierarchy is distinguished only by the shared identifier (the discriminator is not used)
- normalization improves data storage (less unused space in comparison to SINGLE_TABLE strategy, but more than in case of JOINED strategy)
- non-polymorphic queries (for a single concrete entity) are efficient as join is not required
- polymorphic queries (for wide or deep hierarchy of entity classes) require multiple joins and may be expensive
- adding/removing entity fields is straightforward (from database administration point of view)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…