
spring.datasource.url=jdbc:mysql://localhost:3306/orderapp
spring.datasource.username=root
spring.datasource.password=${DB_PASSWORD}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
create database orderapp;
user orderapp;
create table users
(
id bigint not null auto_increment,
name varchar(255),
primary key (id)
);
create table food
(
id bigint not null auto_increment,
name varchar(255),
price float(53) not null,
primary key (id)
);
🤵한 명의 고객은 여러 음식을🍗🍕🍔 주문할 수 있다.
### 불필요하게 중복된 값(고객 이름)을 가지게 된다.
ALTER TABLE food ADD user_id bigint;
INSERT INTO users (name, food_id) VALUES ('Robbie', 1);
INSERT INTO users (name, food_id) VALUES ('Robbert', 1);
INSERT INTO users (name, food_id) VALUES ('Robbie', 2);
🍗하나의 음식은 여러 고객에게👩💼🙋🏻🤵 주문될 수 있다.
### 불필요하게 중복된 값(음식 이름)을 가지게 된다.
ALTER TABLE food ADD user_id bigint;
INSERT INTO food (name, price, user_id) VALUES ('후라이드 치킨', 15000, 1);
INSERT INTO food (name, price, user_id) VALUES ('후라이드 치킨', 15000, 2);
INSERT INTO food (name, price, user_id) VALUES ('양념 치킨', 20000, 1);
고객과 음식은 N:M (多:多) 관계가 된다.
고객-음식
음식-고객
이는 하나의 같은 정보(고객-음식 연관관계)가 양쪽 테이블에 중복되어 분산되어있음을 의미한다.
이 중복을 해결하기 위해 양쪽에 테이블에 데이터를 추가하는 대신, 하나의 개념(주문) 테이블에 담아준다.
create table orders
(
id bigint not null auto_increment,
user_id bigint,
food_id bigint,
order_date date,
primary key (id)
);
주문과 고객/음식은 1:N (1:다多) 관계가 된다.
고객:주문 = 1:N
음식:주문 = 1:M
DB에서는 어떤 테이블을 기준으로 하든 원하는 정보를 JOIN을 사용하여 조회할 수 있기 때문에 테이블 간에는 방향이 없다.
# users 테이블에서 food 테이블을 참조
SELECT u.name as username, f.name as foodname, o.order_date as orderdate
FROM users u
INNER JOIN orders o on u.id = o.user_id
INNER JOIN food f on o.food_id = f.id
WHERE o.user_id = 1;
# food 테이블에서 users 테이블을 참조
SELECT u.name as username, f.name as foodname, o.order_date as orderdate
FROM food f
INNER JOIN orders o on f.id = o.food_id
INNER JOIN users u on o.user_id = u.id
WHERE o.user_id = 1;
JPA 에서는 이러한 Entity간의 연관 관계를 어떻게 표현하고 있을까?
Entity 상태에서 다른 Entity를 참조하기 위해
하나의 엔티티가 다른 엔티티 타입의 필드를 포함하는 형태로 표현된다.
(이 관계가 DB 테이블에 실제 컬럼으로 존재하지는 않는다.)
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// Java 컬렉션을 사용하여 多관계를 표현
@OneToMany(mappedBy = "user")
private List<Food> foodList = new ArrayList<>();
}
@Entity
@Table(name = "food")
public class Food {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
// User 엔티티를 포함
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
}
음식 Entity와 고객 Entity는 서로를 참조하고 있는데,
이러한 관계를 양방향 관계라 부른다.
User는 다른 엔티티를 포함하지 않는다.
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
Food는 User를 포함한다.
@Entity
@Table(name = "food")
public class Food {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
}
음식 Entity에서만 고객 Entity를 참조할 수 있다.
이러한 관계를 단방향 관계라고 부른다.