hayu's 개발 일지

[TIL]240321 엔티티(Entity) 연관관계 매핑(2) 본문

프레임워크/spring

[TIL]240321 엔티티(Entity) 연관관계 매핑(2)

hayu00 2024. 3. 21. 21:47

일대다(1:N) 단방향 관계

  • 일대다 관계는 @OneToMany이다.
  • 다대일 관계에서는 @JoinColumn을 둔 엔티티에 외래키가 생성되고 관리한다. 하지만 일대다 단방향 관계에서는 team 엔티티의 반대편인 member엔티티에 외래키가 생성되고 관리된다. 일반적으로 일대다 단방향 관계 매핑은 권장되지 않는다.
  • 연관관계의 주인 엔티티에서 외래키를 관리하지 않고 반대편 엔티티에서 외래키를 관리하기 때문에 관리가 부담스럽다.(1:N에서 N이 관리한다.)

→ 단방향으로 할때는 일대다 보다는 다대일 단방향으로 하는 것이 좋다.

일대다(1:N) 양방향 관계

  • 일반적으로 일대다 양방향 관계는 존재하지 않는다.
  • 일대다 관계의 주인은 항상 다(N)이기 때문에 일대다 양방향이나 다대일 양방향은 같은 말이다.

다대다(N:M) 단방향 관계(실무에서는 잘 사용 안함)

  • 관계형 데이터 베이스에서 다대다를 2개의 테이블로 표현할 수 없다.
  • 다대다 관계에서는 중간에 관계 테이블을 두고 관계를 맺는다.
  • 하지만 객체는 테이블과 달리 2개의 객체로 다대다 관계를 표현할 수 있다. @ManyToMany를 사용하여 표현한다.
 @Entity
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<>();
    }

    @Entity
    public class User {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String name;
    }

@JoinTable: 연결 테이블을 지정하는 것이다.

name: 연결 테이블을 지정한다.

joinColumns: 현재 위치의 객체와 매핑할 조인 컬럼 이름

inverseJoinColumns: 반대편 객체와 매핑할 조인 컬럼 이름

  • 이렇게 엔티티를 구설할 경우 3개의 테이블이 생성된다.

다대다(N:M) 양방향 관계(실무에서는 잘 사용 안함)

  • 다대다 양방향은 연관 주인 반대편 객체에도 @ManyToMany를 붙여준다. 그리고 연관 주인이 아닌 객체에 mappedBy를 붙여준다.
@Entity
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<>();
    }

    @Entity
    @Table(name = "users")
    public class User {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String name;

        @ManyToMany(mappedBy = "userList")
        private List<Food> foodList = new ArrayList<>();
    }

@ManyToMany를 사용하면 중간 연결 테이블을 자동으로 관리하고 생성해주므로 편리하다. 하지만 일반적으로 실무에서는 연결 테이블에 외래키를 담지 않고 추가적인 컬럼이 들어간다.

추가적인 컬럼이 틀어갈 경우 @ManyToMany는 더이상 사용할 수 없다.

직접 연결 엔티티를 만든 코드

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

    @OneToMany(mappedBy = "food")  //Order엔티티와 일대다 관계
    private List<Order> orderList = new ArrayList<>();
}

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @OneToMany(mappedBy = "user") //Order엔티티와 일대다 관계
    private List<Order> orderList = new ArrayList<>();
}

중간 연결 테이블

 @Entity
    public class Order {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;

        @ManyToOne
        @JoinColumn(name = "food_id")
        private Food food;

        @ManyToOne
        @JoinColumn(name = "user_id")
        private User user;
    }

 

 

참고 자료

 https://cjw-awdsd.tistory.com/47

- https://velog.io/@daydream/Spring-JPA-Entity-%EC%97%B0%EA%B4%80-%EA%B4%80%EA%B3%84-%EB%A7%A4%ED%95%91

- https://colabear754.tistory.com/142

- https://velog.io/@zenon8485/2.-%EC%97%94%ED%8B%B0%ED%8B%B0-%EB%A7%A4%ED%95%91-%EC%97%B0%EA%B4%80%EA%B4%80%EA%B3%84-%EB%A7%A4%ED%95%91