Question

ABSTRACT

Say, I have two simple @Entity inheritance trees (one abstract base class with two concrete implementation classes in each tree) of InheritanceType.TABLE_PER_CLASS; and I need a bidirectional @OneToMany relation connecting the base classes using a @JoinColumn.

This should produce four tables, one per concrete class, right? EclipseLink produces a fifth table for one of the abstract base classes which does not make sense to me. Consider this example (this is not a real-world example; it is just about JPA):

EXAMPLE

Collection is the abstract root of the first inheritance tree and implementor of the @OneToMany relation:

@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class Collection {
    @Id @GeneratedValue
    public long id;
    @OneToMany(mappedBy="collection")
    public List<Media> items = new ArrayList<Media>();
}

PhysicalCollection and VirtualCollection are concrete implementations of Collection:

@Entity
public class PhysicalCollection extends Collection {}

@Entity
public class VirtualCollection extends Collection {}

Media is the abstract root of the second inheritance tree and implementor of the @ManyToOne relation:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Media {
    @Id
    @GeneratedValue
    public long id;
    @ManyToOne
    @JoinColumn(nullable = false)
    public Collection collection;
}

CdMedia and TapeMedia are concrete implementations of Media:

@Entity
public class CdMedia extends Media {}

@Entity
public class TapeMedia extends Media {}

RESULT

As I said, EclipseLink will produce five tables from this (don't mind the SEQUENCE table):

mysql> SHOW TABLES;
+--------------------+
| Tables_in_test     |
+--------------------+
| CDMEDIA            |
| MEDIA              |
| PHYSICALCOLLECTION |
| SEQUENCE           |
| TAPEMEDIA          |
| VIRTUALCOLLECTION  |
+--------------------+
6 rows in set (0.00 sec)

And the unexpected table MEDIA will have a useless definition (the foreign key target changes semantics when renaming PhysicalCollection):

CREATE TABLE `MEDIA` (
    `COLLECTION_ID` bigint(20) NOT NULL,
    KEY `FK_MEDIA_COLLECTION_ID` (`COLLECTION_ID`),
    CONSTRAINT `FK_MEDIA_COLLECTION_ID` FOREIGN KEY (`COLLECTION_ID`) REFERENCES PHYSICALCOLLECTION` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |

QUESTIONS

  1. Are my expectiations correct? (Create 4 tables, not 5)
  2. Can someone confirm that this is a bug in EclipseLink?
  3. If not a bug, can you point out where I make a mistake?
Was it helpful?

Solution

TABLE_PER_CLASS should not be creating a table for any abstract class, so that is a bug. It is very odd you don't also get a table for Collection? Are you sure MEDIA is abstract, did you miss recompiling/deploying your code?

I know this bug existed in EclipseLink 2.0, but think it was fixed after that, so you may want to try the latest version, otherwise log a bug.

In general I would not recommend TABLE_PER_CLASS, especially in this model where you have a lot of realtionships. It would be much better to use SINGLE_TABLE or JOINED inheritance.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top