본문 바로가기
JPA

연관관계 매핑

by bloodFinger 2020. 5. 25.

해당 내용은 개발자 김영한 님의 강의 내용입니다. 참고 부탁드립니다.

 

 


 

 

보통 DTO나 VO를 개발은 이렇게 한다.

public Class Member {
    private String id;
    private Long teamId;
    private String userName;
}


public Class Team {
    private Long teamId;
    private String name;
}

 

만약에 객체적인 모델링으로 개발을 한다면...

Class Member {
   String id;
   Team team;      
   String userName;
   
   Team getTeam() {
   		return team;
   }
}


Class Team {
    Long id;
    String name;
}

 

String TEAM_ID = member.getTeam().getId();

 

- 데이터 삽입 

INSERT INTO MEMBER(MEMBER_ID , TEAM_ID , USERNAME ) VALUES ...

 

- 데이터 검색

SELECT M.* , T.*

FROM MEMBER M

JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID

 

public Member find(String memberId) {
    //SQL 실행
    Member member = new Member();
    Team team = new Team();
    
    member.setTeam(team);
    return member;
}

 

-> 코드양이 굉장히 많아지고 버그확률이 높아진다

 

 

 


 

단방향 매핑

Team team = new Team();
team.setName("boot");
em.persist(team);

Member member = new Member();
member.setName("양재우");
member.setAge(27);
member.setMemberType(MemberType.ADMIN);
member.setTeamId(team.getId());
em.persist(member);

//조회
Member findMember = em.find(Member.class , member.getId());
Long teamId = findMeber.getTeamId();

//연관관계 없다
Team findTeam = em.find(Team.class , teamId );

//그렇기에 하나하나 들고와야한다 , 데이터지향적인 방법이다.

                    [객체 연관관계] - Team에서는 member를 가지고 올수 없다...

Member               --->              Team

-id                                             -id

-Team team                              -name

-username

 

 

                   [테이블 연관관계] - 외래키 하나로 양쪽으로 움직일수있다.

  MEMBER                          --->             TEAM

-MEMBER_ID(PK)                                 -TEAM_ID(PK)

-TEAM_ID(FK)                                      -NAME

-USERNAME

 

 

즉 , 테이블 연관관계처럼 MEMBER에서 TEAM으로 TEAM에서  MEMBER로 갈수있게 하는것이다.

 

코드로 보자

public class Member{

...

@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team


}

이렇게 매핑을 한다면 Member 클래스의 team변수가 TEAM_ID(FK)와 매핑 ~~~> 연관관계 매핑

//팀 저장
Team team = new Team();
team.setName("teamA");
em.persist(team);

//회원저장
Member member = new Member();
member.setName("member1");
member.setTeam(team); //단방향 연관관계 설정 , 참조 저장
em.persist(member);

//조회
Member findMember = em.find(Member.class , member.getId());
//참조를 사용해서 연관관계 조회
Team findTeam = findMember.getTeam();

 

 

 


 

 

 

양방향 매핑

[양방향 객체 연관관계]

Member              < --->              Team

-id                                             -id

-Team team                              -name

-username                                -List members

 

[DB]  //변경되는 부분이 없다.

  MEMBER                          --->             TEAM

-MEMBER_ID(PK)                                 -TEAM_ID(PK)

-TEAM_ID(FK)                                      -NAME

-USERNAME

 

@Entity
public class Team {
	@Id @GeneratedValue
    private Long id;
    private String name;
    
    @OneToMany(mappedBy = "team")
    List<Member> members = new ArrayList<Member>();  
	...
} 
//조회
Team findTeam = em.find(Team.class , team.getId());
//역방향 조회
int memberSize = findTeam.getMembers().size();

 

mappedBy ?

객체와 테이블간의 연관관계를 맺는 차이 ? 

-객체 연관관계

 회원 -> 팀                  연관관계 1개 (단방향)

 팀 -> 회원                  연관관계 1개 (단방향)

 

-테이블 연관관계

회원 <->팀                  연관관계 1개(양방향)

 

객체는 사실 양방향 관계는 사실 양방향 관계가 아니라 서로 다른 단방향 관계 2개다.

참조를 2개를 섞어 양방향 처럼 보인것이다.

 

-테이블은 외래키 하나로 두 테이블의 연관관계를 관리

-MEMBER.TEAM_ID 외래키 하나로 양뱡향 연관관계 가짐(양방향 조인 가능)

select  * from MEMBER M

join TEAM t ON m.TEAM_ID = t.TEAM_ID

select * from TEAM t

join MEMBER m ON t.TEAM_ID = m.TEAM_ID

 

이러한 테이블의 모습을 객체에서 표현하려다 보니 애매한 상황이 발생한다.

 

즉, 양방향 매핑 규칙을 따르지 않으면 문제가 생긴다.

  • 객체의 두 관계중 하나를 연관관계의 주인으로 지정한다.
  • 연관관계의 주인만이 외래 키를 관리(등록 , 수정) 한다.
  • 주인이 아닌쪽은 읽기만 가능하다.
  • 주인은 mappedBy 속성 사용을 하면 안된다
  • 주인이 아니면 mappedBy 속성으로 주인을 지정한다.

 

객체와 DB가 다름을 인지하게 되면 이 문제를 알수있다.

Team team = new Team();
team.setName("TeamA");
em.persist(team);

Member member = new Member();
member.setName("member1");

//역방향(주인이 아닌 방향)만 연관관계 설정
team.getMember().add(member);

em.persist(member);

 

 

 

 

마지막으로 양뱡향 매핑의 장점? 

  • 단방향 매핑만으로도 이미 연관관계 매핑은 완료
  • 양방향 매핑은 반대방향으로 조회(객체 그래프 탐색) 기능이 추가된 것 뿐
  • JPQL에서 역방향으로 탐색할 일이 많이 있다.
  • 단방향 매핑을 잘 하고 양방향은 필요할 때 추가해도 된다.(테이블에 영향을 주지 않는다.)

'JPA' 카테고리의 다른 글

Spring Data JPA & QueryDSL  (0) 2021.01.07
JPA 내부구조 알아보기  (0) 2020.09.14
JPA 사용시 주의사항 정리  (0) 2020.08.22
JPA 매핑 어노테이션  (0) 2020.05.24
이제는 Mybatis 에서 JPA로 넘어가자  (0) 2020.04.17