Несколько наборов @ManyToMany из одной таблицы соединений - PullRequest
1 голос
/ 19 ноября 2009

Я сопоставляю частную базу данных с Hibernate для использования с Spring. В нем есть пара объединяемых таблиц, которые для сущности A и сущности B имеют следующую схему:

CREATE TABLE AjoinB (
  idA int not null,
  idB int not null,
  groupEnum enum ('groupC', 'groupD', 'groupE'),
  primary key(idA, idB, groupEnum)
);

Как видите, это указывает на то, что может быть несколько отношений A-B, которые помещают их в разные группы. Я хотел бы закончить, первая строка для сущности A и вторая для сущности B, следующие наборы

Set<B> BforGroupC, BforGroupD, BforGroupE;
Set<A> AforGroupC, AforGroupD, AforGroupE;

Пока мне удалось собрать их в один набор и не обращать внимания на атрибут отношения groupEnum:

@ManyToMany(targetEntity=B.class, cascade={ CascadeType.PERSIST, CascadeType.MERGE } )
@JoinTable(name="AjoinB", joinColumns=@JoinColumn(name="idA"), inverseJoinColumns=@JoinColumn(name="idB") )
private Set<B> BforAllGroups;

и

@ManyToMany( mappedBy = "BforAllGroups", targetEntity = A.class )
private Set<A> AforAllGroups;

Как я могу сделать несколько наборов, где они принадлежат либо в groupC, groupD или groupE?

Приветствия

Nik

Ответы [ 3 ]

3 голосов
/ 19 ноября 2009

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

Если вы связаны устаревшей базой данных и не можете изменить структуру этой таблицы, я бы

  1. Сначала рассмотрим решение Скаффмана (+1, кстати). В зависимости от вашей целевой базы данных вы можете написать триггер для ваших представлений, который вставил бы адекватное значение «дискриминатора».

  2. Если вышеперечисленное невозможно в вашей БД, другое решение - использовать пользовательский SQL для операций CRUD для ваших коллекций. Имейте в виду, что это будет НЕ работать (например, ваше «значение дискриминатора» не будет применяться) для сложных запросов HQL, включающих вашу связь как часть условия. Вы также можете смешивать / сочетать это с выше - например, использовать представления и использовать пользовательский SQL для вставки / удаления.

  3. Если оба вышеперечисленных не удаются, используйте «объединение как отдельную сущность», как предложено framer8. Это будет довольно уродливо (поскольку мы предполагаем, что вы не можете изменить свои таблицы) из-за составных ключей и всего постороннего кода. На самом деле это может быть невозможно, если любая из ваших ассоциаций допускает дублирование.

3 голосов
/ 19 ноября 2009

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

Возможно, вам удастся определить дополнительные представления в таблице, отображающие каждую из групп?

0 голосов
/ 19 ноября 2009

Я думаю, что в любое время, когда вам нужно получить доступ к полю в таблице ссылок, рекомендуется сделать таблицу ссылок объектом и спящим объектом самостоятельно. A будет иметь набор объектов AtoB, а AtoB будет иметь набор объектов B. У меня такая же ситуация, когда в таблице ссылок есть пользователь, связанный с этой ссылкой.

select joinTable.b from A a 
left join a.AtoB joinTable
where joinTable.group = 'C'

Это не так элегантно, как неявное соединение в hibernate, но оно дает вам необходимый контроль.

...