Разница между использованием @OneToMany и @ManyToMany

у меня возникли некоторые проблемы с пониманием разницы между @OneToMany и @ManyToMany. Когда я использую @OneToMany по умолчанию создается объединяемая таблица, и если вы добавите атрибут mappedBy, у вас будет двунаправленная связь между двумя сущностями.

у меня есть Question это может принадлежать многим Categories и один Category может принадлежать многим Questions. Я не понимаю, если я должен использовать @ManyToMany или @OneToMany потому что для меня это кажется точно таким же, но это, вероятно, не так.

может кто-нибудь объяснить это?

3 ответов


Ну, разница в дизайне, вы пытаетесь отразить с помощью объектов.

в вашем случае, каждый Question может быть назначено несколько Categories - так это знак @*ToMany отношения. Теперь вы должны решить, если:

  • каждого Category может быть только один Question присваивается ему (это приведет к уникальный ограничение, которое означает, что никакая другая категория не может ссылаться на тот же вопрос) - это будет @OneToMany отношения,
  • каждого Category может иметь несколько Questions назначенный ему (в Category "таблица") - это будет @ManyToMany отношения.

@OneToMany (Вопрос -> Категория)

это отношение может быть представлено таблицей join, только если вы явно определяете это, используя @JoinTable это однонаправленный отношения, в которых владеющая сторона является "одной" стороной (это означает что в Question сущности, у вас есть коллекция Categories, но в Categories у вас нет никакой ссылки на Question).

если вы думаете об этом, кажется вполне разумным, что используется таблица join. Нет другого способа, которым СУБД могла бы сохранить соединение между одной строкой в Question таблица с несколькими строками в Categories таблица.

однако, если вы хотите смоделировать двунаправленное отношение, вам нужно указать, что Category ('много' сторона) является ведомой стороне. В этом случае СУБД может создать столбец соединения с внешним ключом в Category таблица, потому что каждый Category строка может быть связана только с одним Question.

таким образом, у вас нет никакой таблицы соединений, кроме простых внешних ключей (тем не менее, как указано в начале, вы можете заставить создать таблицу соединений с помощью @JoinTable).

@ManyToMany

эта связь должна быть представлена в таблице. Он в основном работает очень похоже на однонаправленный @OneToMany отношения, но в этом случае у вас может быть несколько строк из Question соединено с несколькими строками из Categories.


@ManyToMany отношения имеют взаимно ссылочные внешние ключи с обеих сторон отношений. Иногда эта связь опосредуется соседней таблицей.

@OneToMany отношения имеют внешний ключ на стороне "один", а не на стороне" много". В отношениях @OneToMany один объект является "родительским", а другой - "дочерним". Родитель контролирует существование ребенка.

помните, что двунаправленное отношение @ManyToMany не обязательно должно быть симметрично!


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

@Entity
public class Question implements Serializable {
    ...
    @ManyToMany
    private List<Category> categories;
    ...
}

@Entity
public class Category implements Serializable {
    ...
    @ManyToMany
    private List<Question> questions;
    ...
}

Если вы используете отношение @OneToMany для своих вопросов и категорий (скажем, категория С одной стороны и вопросы на другое), это означает ,что" вопрос может принадлежать только к одной категории "и"категория может содержать много вопросов одновременно". Для хранения сопоставления не требуется новая таблица. Вместо этого новое поле будет автоматически создано во многих сторонах для записи идентификатора одной стороны. Ваш код будет выглядеть так:

@Entity
public class Question implements Serializable {
    ...
    @ManyToOne
    private Category theCategory;
    ...
}

@Entity
public class Category implements Serializable {
    ...
    @OneToMany(mappedBy="theCategory")
    private List<Question> questions;
    ...
}