ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • OneToMany 단방향과 양방향 매핑
    BackEnd/JPA 2022. 7. 23. 23:32

    - 일대다 단방향

    - 일대다 양방향

    - 다대일 양방향 

     

    객체 매핑과는 무관하게 DB 설계는 동일하게 적용된다.

    Team Member
    member없음 team_id(fk)

     

    1. 일대다 단방향 매핑

    OneToMany 에서 One 이 연관관계의 주인이 된다는 의미이다.
    비지니스에서 만약 Team 에서는 List<Member> 정보가 필요하지만 , Member 에서는 Team 이 필요없는 상황.

    //일대다 단방향 매핑, 연관관계 주인 TEAM
    
    class Team 
        @OneToMany
        @JoinColumn(name = "member_id")
        private List<Member> member;
        
    class Member
    //Team 정보 없음

    > Team 의 Member List 를 수정할 때 Member update 쿼리가 자동으로 발생함 1+N

    그런 이유로, 일대다 단방향 매핑보다는 다대일 양방향 매핑 사용이 권장된다. 

    비지니스에서 Member 에서 team 으로 갈 일이 없더라도, 
    Many 인 Member 에서 연관관계의 주인으로 하는 것이 DB 에 설계를 맞춰 유지보수를 쉽게 한다.

    객체적으로 조금 손해를 보지만 트레이드 오프이다.


    2. 일대다 양방향 - JPA 지원안함 

    Member 에서 Team JoinColumn 에 insertable=false, updatable=false 를 줘서 읽기전용으로 만든다.

    //일대다 양방향 매핑, 연관관계 주인 TEAM
    
    class Team 
        @OneToMany
        @JoinColumn(name = "team_id")
        private List<Member> member;
        
    class Member
        @ManyToOne
        @JoinColumn(name = "team_id",insertable=false, updatable=false )
        private Team team;

     

    3. 다대일 양방향 

    //다대일 양방향 매핑, 연관관계 주인 Member
    
    class Team 
        @OneToMany(mappedBy=team)
        private List<Member> member;
        
    class Member
        @ManyToOne
        @JoinColumn(name = "team_id" )
        private Team team;


    * @JoinColumn
    연관관계의 주인은 FK 관리 객체 , 
    JoinColumn 은 FK 를 매핑 


    Board BoardImage
    image 정보 x board_id(fk) 

    위와 같은 이유로 

    Board 와 BoardImage 의 관계에서 다대일 양방향을 맺기 위해서는 

    BoardImage 가 연관관계의 주인이 되는 것이 바람직해 보인다.

    하지만 BoardImage 는 Board 작성 시 있을 수도, 없을 수도 있는 정보이며, BoardImage 가 없더라도 Board 는 항상 persist 되어야한다.

    또, Board가 삭제되면 BoardImage 가 삭제되어야하고, 수정도 마찬가지이다.

    그렇다면 연관관계의 주인의 여부와 무관하게 자식 엔티티에서 부모 엔티티의 영속화까지 책임지는 형태가 된다.

    이는 cascade 옵션으로 해결할 수 있다.

    class Board 
        @OneToMany(mappedby=board, cascade=CascadeType.ALL)
        private List<BoardImage> boardImages;
    
    class BoardImage
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name="board_id")
        private Board board;

    * Board 를 영속화할 때 BoardImage 도 영속화된다. 둘의 연관관계 세팅 메서드는 Board 에 두었다.

    //엔티티 Board
    public void addImage(final BoardImage image){
        this.boardImages.add(image);
        image.setBoard(this);
    }
    public void setImages(final List<BoardImage> images) {
        this.boardImages = images;
        for (BoardImage image :  images) {
            image.setBoard(this);
        }
    }

    mappedBy 와 casecade 옵션

    mappedBy 속성의 의미는 해당 필드는 데이터를 조회하는 기능만 갖게 된다는 것이다.
    해당 필드는 반대편 연관관계 주인을 비추며, 데이터를 insert, update 하는 기능을 상실한다.

    casecade 옵션은 적용된 필드가 자신이 바라보는 객체를 조작할 수 있도록 한다.
    이 필드의 객체가 변경되면, 관련 연관관계를 모두 데이터베이스에 반영한다.
    cascade 는 양방향이나 mappedby 와 관계가 없으며, A->B 가 cascade 되어 있을 때 
    A엔티티 persist 시 B엔티티도 persist 된다.

    예를 들어 board 와 boardCount 의 관계에서 

    Board 와 BoardCount 는 일대일 관계이며, Board 가 연관관계의 주인이다.

    DB 상 Board 에서 BoardCount의 FK 를 갖고 , BoardCount 에서는 Board 의 FK 를 갖고 있지 않는다.

    Board 가 BoardCount 에 대해 cascade 옵션을 갖고 있는데, 이는 Board 를 insert,update 할 때 BoardCount 

    board insert 전에 DB 에 반영되어 board 에 FK 로 들어갈 수 있도록 JPA 가 동작한다. 

    board board_count
    board_count_id (FK)  
    class BoardCount 
        @OneToOne(mappedBy = "boardCount")
        private Board board;
        
        
    class Board
        @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
        @JoinColumn(name = "count_id")
        private BoardCount boardCount;

     

     



    반응형

    'BackEnd > JPA' 카테고리의 다른 글

    JPA 강의 포인트  (0) 2021.12.15
    JPA > Fetch Join , BatchSize  (0) 2021.04.27
    JPA 경로표현식  (0) 2021.04.27
    JPA > JPQL, 프로젝션  (0) 2021.04.27
    JPA > 값 타입  (0) 2021.04.25
Designed by Tistory.