Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
766 views
in Technique[技术] by (71.8m points)

java - Mapping Sub-Classes by Type Table (Many-To-One Hibernate)

I have to make the domain-layer of a collage project. We have few standards, like we have to use Hibernate and the database also is fix.

The relevant part of the database looks nearly like that:

BusEntitys (Table 1)

  • BusId
  • Bus specific information

BusType (Table 2)

  • BusTypeId
  • Seats
  • ...
  • SubClass Discriminator

The problem I have is that there are 2 types of buses in the domain-layer distinguish by the discriminator in the BusType-table:

@Entity
class Bus
{
   @Id
   int _id;
   ...
}

@Entity
class BusSubClass1 extends Bus
{
   ...
}

@Entity
class BusSubClass2 extends Bus
{
   ...
}

Is there a way to map something like this with Hibernate and JPA? Thanks for every answer.

Jochen Morent

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...