В иерархии сущностей JPA, использующей InheritanceType.JOINED, все отношения с подклассами приводят к ограничениям внешнего ключа для таблицы суперкласса.

У меня есть следующие объекты JPA 2.0

@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;
    ...
}

Я хочу позволить JPA генерировать для меня таблицы, так как это облегчает установку в нескольких местах. Я обычно ожидал, что это сгенерирует это:

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)
)

Первые две таблицы, где то же самое, но он сгенерировал employee таблица таким образом:

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)
)

Вы можете заметить, что fk_employee_role_id ссылается на bookkeepingparent стол, а не role Таблица. У меня большая иерархия сущностей JPA, и я хочу, чтобы бухгалтерский родитель был суперклассом большинства из них. Это в первую очередь из-за некоторых очень специфических стратегий генерации идентификаторов и других бухгалтерских операций. Этот дизайн помогает отделить весь этот код бухгалтерского учета от функционального кода и позволяет программистам, работающим над функциональным кодом, не беспокоиться об этом.

Все это работало нормально, пока не выросло количество столов. Теперь мы видим, что для всех ManyToOne а также OneToOne В связи с этим JPA генерирует внешние ключи, ссылаясь на родительскую таблицу. При наличии 200 нечетных таблиц вставки уже выполняются медленно, поскольку все ограничения внешнего ключа относятся к родительскому элементу bookekeepingparent, и каждый объект, когда он сохраняется впервые, вставляется в родительскую таблицу учета. Я полагаю, что проверяется около 150 странных ограничений.

Итак, вот мои вопросы: почему JPA это делает? Это стандартное поведение JPA? (Я использую EclipseLink) Если я вручную изменю схему БД, стоит ли ожидать их каких-либо ошибок?

Это мой первый вопрос по Stackru, я старался изо всех сил искать любые существующие ответы. Извиняюсь, если я что-то пропустил. Благодарю.

1 ответ

Вы используете объединенное наследование, что означает, что для каждого класса bookkeepingparenttable является главной таблицей, а любая таблица подкласса является вторичной. Первичный ключ для подклассов наследуется от родительского, а внешние ключи должны ссылаться на идентификатор, поэтому все они будут ссылаться на идентификатор в bookkeepingparenttable по своему замыслу. Разные провайдеры разрешают ссылаться на поля, отличные от pk, но это может вызвать проблемы, поскольку для разрешения ссылок может потребоваться обращение к базе данных вместо использования кэша.

Ограничения базы данных не связаны с JPA, поэтому вы можете изменять их по мере необходимости и не влиять на приложение, пока вставка обновлений и удалений будет соответствовать.

Другие вопросы по тегам