Преобразовать связь сущностей ManyToMany в ManyToOne
У меня есть три таблицы, Блюдо,Информация о Блюде и Категория,которые созданы в базе следующим образом:
dishes
CREATE TABLE restaurant_schema.dishes
(
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(64) NOT NULL,
price NUMERIC(7, 2) NOT NULL,
dish_info_id BIGINT NOT NULL UNIQUE REFERENCES restaurant_schema.dish_info
);
dish_info
CREATE TABLE restaurant_schema.dish_info
(
id BIGINT AUTO_INCREMENT PRIMARY KEY,
category_id BIGINT REFERENCES restaurant_schema.categories (id),
weight INT NOT NULL,
recipe_id BIGINT REFERENCES warehouse_schema.recipes (id)
);
categories
CREATE TABLE restaurant_schema.categories
(
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(128)
);
Мне не нравится структура связей, с одной стороны мне кажется не до конца логичным что в категории(categories) хранится информация о блюде(dish_info), а не само блюдо(dish).
Также я бы хотел видеть связь между блюдом и категорией в виде ManyToOne, а не ManyToMany, поэтому я думаю создать промежуточную сущность, но проблема в том что в результате получится что в этой сущности будут хранится просто два ключа, что тоже мне кажется не до конца логичным.
Пока что моя объектная модель выглядит следующим образом:
Dish
public class Dish {
@Id
@Column(name = "id")
Long id;
@Column(name = "name")
String name;
@Column(name = "price")
BigDecimal price;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "dish_info_id")
DishInfo dishInfo;
}
DishInfo
public class DishInfo {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
@Column(name = "weight")
Integer weight;
@OneToMany
@JoinColumn(name = "category_id")
List<Category> categories;
@OneToOne
@JoinColumn(name = "recipe_id")
Recipe recipe;
}
Category
public class Category {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
@Column(name = "name")
String name;
}
Как в моем случает можно улучшить объектную и реляционную модель?
Как бы вы организовали связи?
Буду благодарен любому совету
Ответы (1 шт):
Вы говорите:
@Smetana Po Aktsii:
хотел видеть связь между блюдом и категорией в виде ManyToOne, а не ManyToMany
, во избежание чего хотите
@Smetana Po Aktsii:
создать промежуточную сущность, ... в которой будут хранится просто два ключа
Смею заметить, что создавая промежуточную сущность с двумя ключами Вы по факту создаете ничто иное как связь MANY_TO_MANY, просто вы её оборачиваете сущностью... в остальном же она будет играть ту же самую роль что и таблица, создаваемая при определении данной связи, которая просто хранит два ключа.
Тут вам стоит самому подумать, понять и решить:
может быть отношение к MANY_TO_MANY было предвзятым и желание избавиться от него любой ценой просто заблуждение?
Также хочу отметить что чисто функционально MANY_TO_MANY и ONE_TO_MANY отличаются.
И данные связи имеют совершенно разные возможности.
И тут стоит отталкиваться не столько от желаний, сколько от реальных потребностей.
- Может ли у Вас одно и то же блюдо одновременно находиться в двух разных категориях?
- В будущем такое Вы тоже не планируете?
Если так то делайте ONE_TO_MANY.
В противном случае придется делать MANY_TO_MANY.
Также хочу отметить следующее:
на данный момент таблица restaurant_schema.dish_info НЕ СООТВЕТСТВУЕТ классу DishInfo.
В таблице у Вас MANY_TO_ONE, а в классе ONE_TO_MANY...
Это ошибка ... с такой таблицей в классе у вас должно быть
@ManyToOne
Category сategory;
Также я присоединюсь к комментарию @Alex Krass о том, что на данный момент не вижу необходимости в разделении Dish и DishInfo на два класса.
Возможно, Вы нам не все рассказали, но из того что мы видим - необходимости в данном разделении нет.
Я искренне надеюсь, что это не я Вас подтолкнул к действиям.
Больше сущностей не всегда значит лучше, и в том же ответе в другом кейсе я наоборот старался перенести поле в существующий класс, вместо того чтобы создавать ненужную сущность.
С опытом у Вас получится лучше чувствовать такие моменты:
пока же просто держите в голове, что для создания новой сущности нужно очень хорошо понимать для чего именно Вы это делаете.
Если Вы не можете уверенно ответить на этот вопрос, то стоит задуматься...