JPA 관계형 DB 연관관계 매핑하기

송은혜·2022년 4월 5일
0

spring

목록 보기
4/5

연관관계 매핑을 하는 방법에 대해서 간단하게 정리를 해보았다.

연관관계 매핑

우리는 JPA를 사용하므로써 entity들의 연관 관계를 매핑해두고 필요할 때 해당 entitiy와 연관된 entitiy를 사용하며 좀 더 객체 지향적인 프로그래밍을 할 수 있다.

→ JPA는 ORM을 이용하고 , ORM은 관계형 데이터 베이스를 연결시켜주는 것이니까 객체 (entity)마다 연결을 할 수 있는 것.

매핑의 종류

  • 일대일 (1:1) @OneToOne
  • 일대다 (1:N) @OneToMany
  • 다대일 (N:1) @ManyToOne
  • 다대다 (N:N) @ManyToMany

우리가 일대일,다대일 이런 단어를 들었을때 상식적으로 생각하는 방향 그대로 사용하면 된다.

앞에 오는 말이 해당 어노테이션을 입력하는 객체에 해당되고 뒤에 붙는 말이 관계를 맺어줄 다른 테이블이다.

ex) 상품과 장바구니 테이블이 있을 때, 장바구니에는 상품이 여러개 담길 수 있다 = 여러개의 상품은 하나의 장바구니에 들어간다.

→ 장바구니 클래스에 @OneToMany 를 적용할 수 있고, (one ⇒ 장바구니 , many ⇒ 상품. )

상품에는 @ManyToOne을 사용할 수 있다. (many ⇒ 상품 , one ⇒ 장바구니)

방향성

한쪽에서만 다른 한쪽을 참조할 것이냐, 서로가 서로를 참조할 것이냐를 고려해야한다.

  • 단방향

  • 양방향

  • 일대일 (1:1) @OneToOne

    한 게시물에 댓글을 딱 하나만 달 수 있는 상황 / 한 게시물에 이미지를 하나만 올릴 수 있는 상황 등...

    • 단방향

      두 테이블 중 더 주되다고 생각하는 테이블에만 @OneToOne 을 입력해서 단방향 관계를 맺는다.

      publi class Post {
      
      ...
      ...
      @OneToOne
      @JoinColumn(name = "image_id") //매핑할 외래키를 지정해주는 어노테이션.
      private Image image;
    • 양방향

      단방향과 동일하게 작성하되, 양쪽 모두에 해주고, 주된 테이블이 되지 않는 쪽에 mappedBy 만 지정해주면 된다.

      mappedBy 는 주된 키가 아닌 쪽에 사용한다. (외래키를 갖지 않는 쪽에.)

      publi class Image{
      
      ...
      ...
      @OneToOne(mappedBy = "image") 
      private Post post;
      //나는 주인이 아니에요.주인은 image_id이라는 이름으로 나를 참조하고 있을거에요

      외래 키를 Post에서 관리하는 게 좋을 것인지, Image에서 관리하는 게 좋을 것인지 생각을 해봐야합니다. 즉 테이블에 어디에 둘 것 인지를 생각해야합니다.

      테이블은 한 번 생성되면 보통 굳어집니다. 변경이 어렵다는 얘기입니다.그러나 비즈니스는 언제든 바뀔 수 있습니다.게시글이 여러 개의 첨부파일을 첨부할 수 있도록 비즈니스가 변경되면 어떨까요?

      그러면 다(N)쪽인 Image테이블에 외래 키가 있는 것이 변경에 유연합니다
      그러면 다(N)가 될 확률이 높은 테이블에 외래 키를 놓는게 무조건 좋을까요?

      신중히 생각하고 구현해야할 부분이다.


  • 일대다 (1:N) @OneToMany 한 게시판에 여러개의 댓글이 달릴 때 / 메뉴판에 음식이 여러개 등록될 때 등... 일대다 방식을 일대다 단독으로 단방향을 하는 것은 실무에서 거의 사용하지 않는다고함. 일대다 양방향은 공식적으로 존재하지 않고, 일대다&다대일 양방향관계를 보면 될 것이다.
    • 단방향

      데이터베이스 입장에서는 무조건 다(N)쪽에서 외래키를 관리합니다.

      public class Post {
      
      ..
      ...
      @OneToMany
      @JoinColumn(name= "Comment_ID")
      private List<Comment> comment = new ArrayList<>();
      //일대다 단방향은 joincolumn 필수. 보통 many쪽에서 외래키를 관리하는데, 단방향이므
      //이 테이블을 외래키롤 참조하는 테이블이 없으니까 joincolumn 으로 조인을 시킨다.

  • 다대일 (N:1) @ManyToOne 여러개의 댓글을 한 게시판에 등록할 수 있을 때 / 메뉴판 하나에 여러가지 메뉴들이 들어가는 경우 / 여러가지 상품들이 하나의 장바구니에 들어 갈 때 등등 ....
    • 단방향

      데이터베이스 입장에서는 무조건 다(N)쪽에서 외래키를 관리합니다.

      public class Comment{
      
      ..
      ...
      @ManyToOne
      @JoinColumn(name= "POST_ID")
      private Post post;
      //단방향이므로 참조하는 post테이블에는 comment 를 참조시키지 않음.
    • 양방향

      다대일 이므로 양방향은 일대다와 사용할 수 있다.

      데이터베이스 입장에서는 무조건 다(N)쪽에서 외래키를 관리합니다.

      public class Comment{
      
      ..
      ...
      @ManyToOne
      @JoinColumn(name= "POST_ID") 
      private Post post;
      //"다" 쪽 테이블이 외래키를 받기때문에 JoinColumn으로 매핑한다.
      
      -------------------
      
      public class Post {
      
      ..
      ...
      @OneToMany(mappedBy = "post")
      private Comment comment;
      //"다"쪽에서 외래키를 관리하기 때문에 "일" 인 테이블은 JoinColumn하지않고, 
      //mappedBy을 사용하여 스스로가 관계의 주인이 아님을 증명한다.


다대다 (N:N) @ManyToMany 방식은 실무에서 사용하지 않는다고 함.

  • 중간 테이블이 숨겨져 있기 때문에 자기도 모르는 복잡한 조인의 쿼리(Query)가 발생하는 경우가 생길 수 있기 때문입니다.
  • 다대다로 자동생성된 중간테이블은 두 객체의 테이블의 외래 키만 저장되기 때문에 문제가 될 확률이 높습니다. JPA를 해보면 중간 테이블에 외래 키 외에 다른 정보가 들어가는 경우가 많기 때문에 다대다를 일대다, 다대일로 풀어서 만드는 것(중간 테이블을 Entity로 만드는 것)이 추후 변경에도 유연하게 대처할 수 있습니다.

다대다 방식을 사용하지 않는 이유에 대한 출처:

https://jeong-pro.tistory.com/231

[기본기를 쌓는 정아마추어 코딩블로그]

0개의 댓글