2016-08-08 2 views
0

У меня есть удобное отношение, в котором сущность имеет отношения «один ко многим» с другим и имеет много-к-одному с другим , Таким образом, у LISTING есть много LISTING_LINE_ITEMS, а те LISTING_LINE_ITEMS имеют один SERVICE_PERIOD, но SERVICE_PERIOD имеет много LISTING_LINE_ITEMS. Я попытался описать эту связь, используя @JoinTable JPA, как показано ниже:JPA Inverse Присоединиться к OneToMany, вызывающему более одной строки с данным идентификатором

LISTING

@OneToMany 
@JoinTable (name = "LISTING_LINE_ITEM", joinColumns = @JoinColumn (name = "listing_id"), inverseJoinColumns = @JoinColumn (name = "service_period_id")) 
Set<ServicePeriod>      servicePeriods; 

LISTING_LINE_ITEM

@ManyToOne (fetch = FetchType.EAGER) 
@JoinColumn (name = "listing_id", nullable = false) 
Listing     listing; 

@ManyToOne (fetch = FetchType.EAGER, cascade = CascadeType.PERSIST) 
@JoinColumn (name = "service_period_id") 
ServicePeriod    servicePeriod; 

SERVICE_PERIOD

@ManyToOne 
@JoinTable (name = "LISTING_LINE_ITEM", joinColumns = @JoinColumn (name = "service_period_id"), inverseJoinColumns = @JoinColumn (name = "listing_id")) 
Listing    listing; 

Очевидная цель состоит в том, чтобы иметь возможность легко получить список ServicePeriod s для Listing или один Listing для ServicePeriod. В настоящее время способ это установить, я получаю исключение:

org.hibernate.HibernateException: More than one row with the given identifier was found: 361951, for class: com.gonfind.entity.ServicePeriod 

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

+1

Вы говорите, что многие позиции могут иметь одинаковый период обслуживания, но вы пытаетесь моделировать косвенную связь между листингами по позициям и периодам обслуживания как «один ко многим», а не «многие ко многим». Правильно ли тогда заключить, что существует дополнительное ограничение: несколько позиций могут быть связаны с одним и тем же периодом обслуживания * при условии, что все они связаны с одним и тем же листом *? –

+0

@JohnBollinger да, это правильно. – lmerry213

+0

Имеет ли каждая позиция период обслуживания или могут быть позиции без периода (нулевого) обслуживания? –

ответ

1

У вас действительно есть проблемы. С технической/JPA стороны:

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

  • в JPA, двунаправленная связь принадлежит только одной стороне; другая сторона использует атрибут mappedBy аннотации отношений для ссылки на принадлежащую стороне.

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

  • функциональная зависимость между неключевыми полей, если список идентификатором не является частью ключа элемента строки , или иначе

  • Функциональная зависимость от подмножества ключа.

В первом случае ваши данные не могут быть в третьей нормальной форме; во втором случае они не могут быть даже во второй нормальной форме. Ваша проблема, связанная с этим с JPA, частично возникает из-за низкого уровня нормализации.

Нормализация ваших данных будет намного проще на нескольких уровнях. Для этого вам необходимо удалить прямую связь между списками и позициями и вместо этого связать их через периоды обслуживания.то Вы бы:

< Listing - один ко многим ->ServicePeriod < - один ко многим ->LineItem

Конечно, это будет иметь последствия для структуры вашего приложения, но это вероятно, будет долговременной победой в развитии и техническом обслуживании, и, возможно, даже победой в юзабилити, так как приложение будет согласовано с естественной структурой ваших данных. Если вы хотите, вы можете поместить методы на свой объект Listing, чтобы позволить ListingLineItem s управляться в некоторой степени, как если бы они принадлежали непосредственно Listing s и наоборот..

Эта организация данных будет выглядеть примерно так:

искать среди объявлений

@OneToMany(mappedBy = "listing", 
     fetch = FetchType.EAGER, 
     cascade = CascadeType.PERSIST) 
Set<ServicePeriod> servicePeriods; 

SERVICE_PERIOD

@ManyToOne(fetch = FetchType.EAGER) 
@JoinColumn(name = "listing_id") 
Listing listing; 

@OneToMany(mappedBy = "servicePeriod", 
     fetch = FetchType.EAGER, 
     cascade = CascadeType.PERSIST) 
Set<ListingLineItem> lineItems; 

LISTING_LINE_ITEM

@ManyToOne(fetch = FetchType.EAGER) 
@JoinColumn(name = "service_period_id") 
ServicePeriod servicePeriod; 

Если вы не можете реструктурировать свои данные примерно так или иначе, то вы застряли с помощью jerry-фальсификации, что нельзя полностью описать JPA. Я представляю отдельную таблицу соединений для Listing < ->ServicePeriod, ограничение FK без JPA для этой таблицы из таблицы сущностей для позиций и, конечно, правильную форму для различных двунаправленных отношений.

+0

Спасибо, это было очень полезно. Я не проектировал эту схему, и хотя я не очень разбираюсь в разработке данных и нормальных формах, это приложение еще не выпущено, и я считаю, что реорганизация схемы - это, вероятно, правильное решение. Я собираюсь сделать некоторое чтение, и, возможно, я опубликую свое окончательное решение. – lmerry213

Смежные вопросы