Я пытаюсь оптимизировать классы @Entity
. Возьмем общий случай отношения a User <-> Group
. Я также хочу сохранить дату, когда было установлено отношение. Раскладка таблицы:
USER GROUP_USER GROUP
------ ------------ -------
id user_id id
name group_id name
createdAt
Со следующими тремя классами:
-
User
с@OneToMany List<GroupUser>
-
GroupUser
с@ManyToOne User
и@ManyToOne Group
-
Group
с@OneToMany List<GroupUser>
Это работает, но это отстой для обычных случаев использования. Например: дайте мне все группы для User user
:
List<Group> groups;
for(GroupUser gu : user.getGroupUsers) {
groups.add(gu.getGroup());
}
Тогда идея использования Map
пришла мне в голову. Поэтому я создал следующие 3 класса:
@Entity
class User {
@Column(name="id")
UUID id;
@Column(name="name")
String name;
@ElementCollection
@CollectionTable(name="Group_User")
Map<Group, GroupUserRelationData> groups;
}
@Entity
class Group {
@Column(name="id")
UUID id;
@Column(name="name")
String name;
@ElementCollection
@CollectionTable(name="Group_User")
Map<User, GroupUserRelationData> users;
}
@Embeddable
class GroupUserRelationData {
@Column(name="createdAt")
DateTime createdAt;
}
Он делает, создавая 3 таблицы, как ожидалось, но столбцы внутри таблицы Group_User
являются странными:
USER GROUP_USER GROUP
------ ------------ -------
id User_id id
name users_KEY name
Group_id
group_KEY
createdAt
Я уверен, что мне не хватает некоторых вещей... Похоже, я должен указать JoinColumn. Но какой правильный путь?
Какая разница между @CollectionTable(joinColumns=...)
и @MapKeyColumn
и @MapKeyJoinColumn
. Должен ли я установить все из них?
Или мне нужно использовать @ManyToMany
вместо @ElementCollection
?
Я просто хочу получить ту же таблицу, что и наверху, используя java.util.Map
.
РЕДАКТИРОВАТЬ № 1: Кроме того, база данных должна иметь правильные ограничения для таблицы:
- Композитный первичный ключ (Group_id, User_id)
В настоящий момент он создает составную PK (Group_id, users_KEY), которая кажется мне довольно странной. И он также создает 4 (!!) индекса, по одному для каждого столбца User_id
, Group_id
, users_KEY
и groups_KEY
.
EDIT # 2: Я нашел веб-сайт, в котором рассказывается, когда использовать аннотации: http://kptek.wordpress.com/2012/06/26/collection-mapping/
Плохая вещь: я до сих пор не знаю ПОЧЕМУ...
Решение:
После нескольких попыток я придумал следующий код, который делает именно то, что я хочу. Я должен использовать все эти аннотации, иначе он создает дополнительные столбцы:
@Entity
class User {
@Column(name="id")
UUID id;
@Column(name="name")
String name;
@ElementCollection
@CollectionTable(name="Group_User",
[email protected](name="User_Id"))
@MapKeyJoinColumn(name="Group_Id")
Map<Group, GroupUserRelationData> groups;
}
@Entity
class Group {
@Column(name="id")
UUID id;
@Column(name="name")
String name;
@ElementCollection
@CollectionTable(name="Group_User",
[email protected](name="Group_Id"))
@MapKeyJoinColumn(name="User_Id")
Map<User, GroupUserRelationData> users;
}
@Embeddable
class GroupUserRelationData {
@Column(name="createdAt")
DateTime createdAt;
}
Мне все еще хотелось бы объяснить, что именно делают эти аннотации, и почему поведение по умолчанию создало четыре столбца и странный первичный ключ.