Everyday Dev System

@ManyToMany 단방향 관계 이해하기 본문

내배캠 주요 학습/Spring 숙련

@ManyToMany 단방향 관계 이해하기

chaeyoung- 2023. 6. 21. 14:09

 

N : M 관계 단방향 코드: 

package com.sparta.jpaadvance.entity;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@Setter
@Table(name = "food")
public class Food {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private double price;

    @ManyToMany
    @JoinTable(name = "orders", // 중간 테이블 생성
            joinColumns = @JoinColumn(name = "food_id"), // 현재 위치인 Food Entity 에서 중간 테이블로 조인할 컬럼 설정
            inverseJoinColumns = @JoinColumn(name = "user_id")) // 반대 위치인 User Entity 에서 중간 테이블로 조인할 컬럼 설정
    private List<User> userList = new ArrayList<>();
}
package com.sparta.jpaadvance.entity;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

@Entity
@Getter
@Setter
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
}
package com.sparta.jpaadvance.relation;

import com.sparta.jpaadvance.entity.Food;
import com.sparta.jpaadvance.entity.User;
import com.sparta.jpaadvance.repository.FoodRepository;
import com.sparta.jpaadvance.repository.UserRepository;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.transaction.annotation.Transactional;

@Transactional
@SpringBootTest
public class ManyToManyTest {

    @Autowired
    UserRepository userRepository;
    @Autowired
    FoodRepository foodRepository;

    @Test
    @Rollback(value = false)
    @DisplayName("N대M 단방향 테스트")
    void test1() {

        User user = new User();
        user.setName("Robbie");

        User user2 = new User();
        user2.setName("Robbert");

        Food food = new Food();
        food.setName("후라이드 치킨");
        food.setPrice(15000);
        food.getUserList().add(user);
        food.getUserList().add(user2);

        userRepository.save(user);
        userRepository.save(user2);
        foodRepository.save(food);

        // 자동으로 중간 테이블 orders 가 create 되고 insert 됨을 확인할 수 있습니다.
    }
}

 

 

 

중요한 코드:

    @ManyToMany
    @JoinTable(name = "orders", // 중간 테이블 생성
            joinColumns = @JoinColumn(name = "food_id"), // 현재 위치인 Food Entity 에서 중간 테이블로 조인할 컬럼 설정
            inverseJoinColumns = @JoinColumn(name = "user_id")) // 반대 위치인 User Entity 에서 중간 테이블로 조인할 컬럼 설정
    private List<User> userList = new ArrayList<>();
        User user = new User();
        user.setName("Robbie");

        User user2 = new User();
        user2.setName("Robbert");

        Food food = new Food();
        food.setName("후라이드 치킨");
        food.setPrice(15000);
        food.getUserList().add(user);
        food.getUserList().add(user2);

        userRepository.save(user);
        userRepository.save(user2);
        foodRepository.save(food);

위 코드를 실행하면 JPA에서 orders라는 테이블을 새로 생성합니다.

생성하고 alter table을 통해 FK 설정을 해줍니다.

 

 

DB 결과 : 

 

Hibernate SQL query문 :

 

테스트를 하면 아래와 같이 Hibernate SQL query문이 출력된다.

Hibernate: 
    create table food (
        id bigint not null auto_increment,
        name varchar(255),
        price float(53) not null,
        primary key (id)
    ) engine=InnoDB
Hibernate: 
    create table orders (
        food_id bigint not null,
        user_id bigint not null
    ) engine=InnoDB
Hibernate: 
    create table users (
        id bigint not null auto_increment,
        name varchar(255),
        primary key (id)
    ) engine=InnoDB
Hibernate: 
    alter table orders 
       add constraint FK32ql8ubntj5uh44ph9659tiih 
       foreign key (user_id) 
       references users (id)
Hibernate: 
    alter table orders 
       add constraint FK5g4j2r53ncoltplogbnqlpt30 
       foreign key (food_id) 
       references food (id)
Hibernate: 
    /* insert for
        com.sparta.jpaadvance.entity.User */insert 
    into
        users (name) 
    values
        (?)
Hibernate: 
    /* insert for
        com.sparta.jpaadvance.entity.User */insert 
    into
        users (name) 
    values
        (?)
Hibernate: 
    /* insert for
        com.sparta.jpaadvance.entity.Food */insert 
    into
        food (name,price) 
    values
        (?,?)
Hibernate: 
    /* insert for
        com.sparta.jpaadvance.entity.Food.userList */insert 
    into
        orders (food_id,user_id) 
    values
        (?,?)
Hibernate: 
    /* insert for
        com.sparta.jpaadvance.entity.Food.userList */insert 
    into
        orders (food_id,user_id) 
    values
        (?,?)