해당 내용은 개발자 김영한 님의 강의 내용입니다. 참고 부탁드립니다.
보통 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 |