Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In a JPA entity hierarchy using InheritanceType.JOINED, all relationships with subclasses results in foreign key constraints on the superclass table

I have the following JPA 2.0 Entities

@Entity
@Inheritance(strategy= InheritanceType.JOINED)
public abstract class BookKeepingParent implements Serializable {
    @Id
    protected Long Id;
    ...
}

@Entity
public class Employee extends BookKeepingParent {
    private String name;

    @ManyToOne
    private Role role;
    ...
}

@Entity
public class Role extends BookKeepingParent {
    private String name;
    ...
}

I want to let JPA generate tables for me, since it makes it easier to install at multiple locations. I would usually expected it to generate this:

CREATE TABLE bookkeepingparent (
  id bigint NOT NULL,
  dtype character varying(31),
  CONSTRAINT bookkeepingparent_pkey PRIMARY KEY (id )
)

CREATE TABLE role (
  id bigint NOT NULL,
  name character varying(255),
  CONSTRAINT role_pkey PRIMARY KEY (id ),
  CONSTRAINT fk_role_id FOREIGN KEY (id) REFERENCES bookkeepingparent (id)
)

CREATE TABLE employee (
  id bigint NOT NULL,
  name character varying(255),
  role_id bigint,
  CONSTRAINT employee_pkey PRIMARY KEY (id ),
  CONSTRAINT fk_employee_id FOREIGN KEY (id) REFERENCES bookkeepingparent (id),
  CONSTRAINT fk_employee_role_id FOREIGN KEY (role_id) REFERENCES role (id)
)

First two tables where the same, but it generated the employee table this way:

CREATE TABLE employee (
  id bigint NOT NULL,
  name character varying(255),
  role_id bigint,
  CONSTRAINT employee_pkey PRIMARY KEY (id ),
  CONSTRAINT fk_employee_id FOREIGN KEY (id) REFERENCES bookkeepingparent (id),
  CONSTRAINT fk_employee_role_id FOREIGN KEY (role_id) REFERENCES bookkeepingparent (id)
)

You can notice that the fk_employee_role_id references the bookkeepingparent table, instead of the role table. I have a large heirarchy of JPA entities, and I want the bookkeepingparent to be the superclass of most of them. This is primarily because of some very specific Id generation strategies and other bookkeeping activities. This design, helps keep all this book keeping code separate from the functional code, and let programmers working on the functional code not worry about it.

All this worked alright till the the number of tables grew. Now we see that, for all ManyToOne and OneToOne relationships, JPA is generating foreign keys referring to the parent table. With 200 odd tables, the inserts are already slow because all foreign key constraints refer to the bookekeepingparent, and every entity, when persisted for the first time, inserts into the bookkeeping parent table. Which I guess is checking some 150 odd constraints.

So, following are my questions: why is JPA doing it? Is it a standard JPA behaviour? (I'm using EclipseLink) If I manually change the DB schema, are their any pitfalls to expect?

This is my first question on StackOverflow, I tried my best to search for any existing answers. Apologies if I missed any. Thanks.

like image 800
Nikhilesh Avatar asked Nov 12 '22 03:11

Nikhilesh


1 Answers

You are using joined inheritance, which means that for every class, the bookkeepingparenttable is the main table and any subclass table is secondary. The primary key for the subclasses are inherited from the parent, and foreign keys must reference the id, so the will all reference the id in bookkeepingparenttable by design. Different providers allow referencing non-pk fields, but it can cause problems as resolving references can require database hits instead of using the cache.

The database constraints are not JPA related, so you can change them as required and not affect the app as long as inserts updates and deletes will still conform.

like image 190
Chris Avatar answered Dec 10 '22 05:12

Chris