В иерархии сущностей 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, поэтому вы можете изменять их по мере необходимости и не влиять на приложение, пока вставка обновлений и удалений будет соответствовать.