Как иметь 2 коллекции одного типа в JPA?
У меня есть два объекта в JPA: запись и комментарий. Запись содержит две коллекции объектов Comment.
@Entity
public class Entry {
...
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@IndexColumn(base = 1, name = "dnr")
private List<Comment> descriptionComments = new ArrayList<Comment>();
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@IndexColumn(base = 1, name = "pmnr")
private List<Comment> postMortemComments = new ArrayList<Comment>();
...
}
Для хранения таких объектов JPA + Hibernate создает таблицу "Entry", таблицу "Comment" и SINGLE "Entry_Comment":
create table Entry_Comment (Entry_id integer not null, postMortemComments_id integer not null, pmnr integer not null, descriptionComments_id integer not null, dnr integer not null, primary key (Entry_id, dnr), unique (descriptionComments_id), unique (postMortemComments_id))
Сохранение объектов не выполняется, поскольку descriptionComments_id
и postMortemComments_id
не могут быть "не равными нулю" одновременно.
Как хранить объект, содержащий две коллекции одного и того же типа, используя JPA + Hibernate?
Ответы
Ответ 1
Это одна из многих ошибок Hibernate (HHH-3410, если быть точным).
Мне удалось исправить это, добавив @JoinTable
аннотации к отношениям @OneToMany
, каждый из которых имеет собственное имя таблицы.
В вашем случае это будет выглядеть так:
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name="entity_descriptioncomments")
@IndexColumn(base = 1, name = "dnr")
private List<Comment> descriptionComments = new ArrayList<Comment>();
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name="entity_postmortemcomments")
@IndexColumn(base = 1, name = "pmnr")
private List<Comment> postMortemComments = new ArrayList<Comment>();
Примечание: вы должны добавить аннотацию @IndexColumn
(из-за другой проблемы с гибернацией с несколькими пакетами EAGER: HHH-1718/EJB-346).
Ответ 2
Чтобы сохранить 2 коллекции, подобные JPA с помощью DataNucleus (http://www.datanucleus.org), вы сделали бы точно так, как вы это сделали. У вас нет аннотации @JoinTable
, поэтому FK следует поместить в Comment
для каждой из коллекций. Если у вас на самом деле есть @JoinTable
где-нибудь (или эквивалент XML), то установка имен соответствующих таблиц соединений (по одному для каждой коллекции) тоже будет работать (поэтому у них есть своя таблица соединений). В DataNucleus также имеется общая таблица соединений между 2 коллекциями, но это не стандартная JPA, а расширение поставщика.
Как это сопоставляется с Hibernate, я понятия не имею, но тогда это JPA, поэтому должно быть последовательным, так как это означает, что имеет спецификацию; -)
Ответ 3
Существует ошибка с текущим сопоставлением с точки зрения модели данных/модели домена: у вас есть отношения single @OneToMany между Entry и Comment. Объект Comment должен иметь еще один атрибут, называемый типом, который принимает 2 значения: "описание" или "postMortem".
Чтобы быть встроенным в вашу текущую реализацию объекта Entry, вы можете захотеть разбить объект Comment на 2 разных объекта (возможно, используя функции наследования JPA) и используя аннотацию @JoinTable в Entry.
Ответ 4
Если все, о чем вы заботитесь, это упорядочивание, как насчет того, чтобы настроить два определения столбцов индекса на одно и то же имя?