JPA 스터디 4주차

반응형
반응형

크게 JPA에서 연관관계는 3가지로 구분이 되어진다.

다대일 // 다 : 1

일대다 // 1 : 다

다대다 // 다 : 다

여기서 다대다는 사용을 금지하고 있다. 그러니까 굳이 사용하지 않아도 된다는 뜻이다.
애초에 다대다라는게 다대일과 일대다를 하나로 묶는 방법이라
다대다로 만든다고 한들 결과는 같기 때문이다.
그러면 어째서 다대다를 사용하지 말고 일대다 + 다대일을 합쳐서 사용해야 하는 것일까?

이건 내 생각인데 다대다로 묶게 되면 내가 생성하지 않는 테이블이 만들어진다.
그 테이블은 내가 관리할 수 없다. 그렇기 때문인가 아닐까 라는 조심스런 추측을 해본다.

@Entity
public class Team {
  @Id @GeneratedValue
  private Integer teamIdx;
  private String teamName;
  @ManyToMany
  @JoinColumn(name = "MEMBER_IDX")
  private List<Member> members = new ArrayList<>();
}
@Entity
public class Member {
  @Id @GeneratedValue
  private Integer memberIdx;
  private String memberName;
}

요런 식으로 대충 만들었다. 사실 비지니스 관점으로 본다면 좀 말이 안되는 엔티티이지만;;
사실 그런거 신경 안쓰고 만들었다. 
이것을 실행해보자.

Hibernate: 
    
    create table Member (
       memberIdx integer not null,
        memberName varchar(255),
        primary key (memberIdx)
    )
Hibernate: 
    
    create table Team (
       teamIdx integer not null,
        teamName varchar(255),
        primary key (teamIdx)
    )
Hibernate: 
    
    create table Team_Member (
       Team_teamIdx integer not null,
        members_memberIdx integer not null
    )
Hibernate: 
    
    alter table Team_Member 
       add constraint FKfyo4i5do4le1bcxsiro1fdppc 
       foreign key (members_memberIdx) 
       references Member

(솔직히 칼럼 이름도 그렇게 까지 마음에 들지 않는다.)

그럼 요런 식으로 나오는데 애초에 나는 Team_Member라는걸 만들지 않았다. 이게 만들어진 이유는 내가 팀 쪽에 다대다를 설정해 놓았기 때문이다. 근데 만약에 내가 Team_Member라는 곳에 칼럼을 추가하고 싶다고 해보자. 솔직히 말하면 방법이 없다.
왜냐하면 이건 JPA에서 만들어준것이기 때문이다.
더욱 놀라운 사실은 Team쪽에 세팅을 해놨는데 실제로 Team테이블에는 해당 칼럼이 생기지 않았다.
또 팀에서 맴버를 추가하는데 반대인 경우는 없다.
그래서 추가해 봤다.
새로운 테이블이 하나더 추가 되었다.
이상하다. 이게 아닌것 같다는 느낌이 강하게 든다.

Hibernate: 
    
    create table Member_Team (
       Member_memberIdx integer not null,
        teams_teamIdx integer not null
    )

사실 Team_Member나 Member_Team이나 같은 테이블이다. 그런데 한쪽으로만 데이터가 축척이 된다는게 나로써는 이해가 되지 않는다. 이해가 되지 않을 것 같아 이것을 그림으로 그려보면


나는 요런식으로 데이터를 저장할려구 한다.
근데 이것을 어떻게 저장하지?
다쪽에서 외래키를 관리한다고 알고 있는데 이렇게 되면 어디서 외래키를 어디서 관리하지?
이건 확실치 않아 반대인 경우도 생각해보면 일인 쪽에서 외래키를 관리한다고 하지만, 둘다 일이 아닌데 어디서 관리한다는 걸까?
그래서 테이블 같은 경우는 중간에 테이블을 하나 추가해준다.

요런식으로 

즉 Team_Meamber라는 곳에서 이 둘을 관리한다고 생각하면 쉽다.
그런데 JPA에서 이것을 만들게 되면 다음처럼 만들어진다.

Team_Member나 Member_Team이나 같은 테이블인데
Team쪽에서 member을 추가 하게되면 Team_Member에 저장이 되구
Member쪽에서 Team을 추가 하게되면 Member_Team에 저장이 된다.

내 생각엔 이건 진짜로 말이 안된다고 생각한다.
그래서 다음처럼 코드를 바꿔보자.

@Entity
public class Mix {

  @Id @GeneratedValue
  private Integer mixIdx;

  @ManyToOne
  @JoinColumn(name = "TEAMIDX")
  private Team team;
  
}


그리고 나머지는 건드리지 않았다. 애초에 이 테이블같은 경우는 조작되지 않기 때문에 굳이 양방향으로 만들 필요는 없다고 생각이든다.
이제 Member쪽도 비슷하게 적용하면 될것 같다.

그럼 요런 식으로 테이블이 생성된다.

Hibernate: 
    
    create table Member (
       memberIdx integer not null,
        memberName varchar(255),
        primary key (memberIdx)
    )
Hibernate: 
    
    create table Mix (
       mixIdx integer not null,
        MEMBERIDX integer,
        TEAMIDX integer,
        primary key (mixIdx)
    )
Hibernate: 
    
    create table Team (
       teamIdx integer not null,
        teamName varchar(255),
        primary key (teamIdx)
    )

위에서 본 쿼리랑 매우 유사하다는 것을 확인했다.
복합키로 만드는 방법은 @Idclass랑 @EmbeddedId 이렇게 2개가 있는데 다음장에서 더 자세히 배운다고 하니 일단 넘어가자.
책에서 추천하는 방법은 위 코드 처럼 대리키를 사용해서 등록하는 방법이다.
왜냐하면 영구히 사용할 수 있기 때문이라고 한다.

그림을 그려보면

요렇게 만들어진다는 것을 알 수 있다.

두 개를 놓고 비교해보면
ManyToMany로 해도 되긴하는데 이것 같은 경우는 
2가지 문제가 있다는 것을 알 수 있다.
1. 개발자가 따로 조작할 수 없다.
2. 칼럼이 자기 마음대로 인서트 된다.

이 두 가지 문제점 때문에 연결 테이블을 만들어주는 것이 더 좋은 방법이 아닐까 생각이 든다.

반응형

'JPA' 카테고리의 다른 글

JPA 스터디 6주차  (1) 2022.02.20
JPA 스터디 5주차  (0) 2022.02.11
JPA 스터디 3주차  (0) 2022.01.26
JPA 스터디 2주차  (0) 2022.01.20
JPQL 중급 문법  (0) 2021.12.26

댓글

Designed by JB FACTORY