본문 바로가기

Spring/JPA

JPA 연관관계 매핑 -양방향 매핑

양방향 연관관계

객체에서 Member에서 Team으로 이동하고, Team에서 Member를 불러올 수 있도록 만들고 싶다. 좀 더 객체 지향적으로! 단 DB 바뀌지 않는다. DB는 방향x

Member에 Team team을 만들고 Team에 List members를 만든다. (1대 다니까)

@Entity
public class Team{
	@Id @generatedValue(strategy=GenerationType.AUTO)
	private Long id;

	private String name;
	
	@OneToMany(mappedBy = "team")
	List<Member> members = new ArrayList<Member>();
	...
}

반대의 일을 할 수 있음!

다시 Main으로 와서 코드를 짜보자.

Team findTeam = em.find(Team.class, team.getId());
List<Member> members = findTeam.getMembers();
for(Member member1 : members){
    System.out.println("member1 = "+ member1);
}

역방향으로 조회가 가능하게 되었다!

이 모든 과정을 JPA없이 직접 짠다고 생각해보면.. 4개의 쿼리문 작성하는 작업이 필요하겠군... ? 이 과정을 JPA가 작성해준다.

연관관계의 주인과 mappedBy

@OneToMany(mappedBy= "team")
private List<Member> members = new ArrayList<>();

-mappedBy 왜? 객체와 테이블의 연관 관계를 이해해야 한다.

객체는 두 개로 연관 관계를 맺고, 테이블은 한 개로 맺는다.

객체 연관 관계 회원→팀 연관 관계 1개 (단방향) 팀→회원 연관 관계 1개 (단방향)

테이블 연관 관계

회원↔팀 연관 관계 1개로 관리 가능(양방향)

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

따라서 객체를 양방향으로 참조하려면 단방향 연관관계를 2개 만들어야 한다.


Member객체와 MEMBER테이블 연관 관계 매핑 해뒀음.

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

여기서 Member의 Team team의 값을 넣으면? ok 연관관계 있고, 테이블에도 값 들어가서 Team 객체에 들어간다. 테이블도 그렇게 들어가. 그럼 반대로 Team에 값을 넣으면??? 그럼 마찬가지로 Member도 업데이트 되어 줘야 하지 않겠어?

객체 지향이잖아. 혼자 있으면 의미가 없어. 양방향 할꺼면 모든 데이터에 값이 있어야 해. Member → Team이든 Team →Member든 값이 들어가줘야 해. 그래야 Member ↔Team이 되는거지

즉, 서로가 서로에게 영향을 줄 수 있음...

Member 테이블 입장에서는 Member객체 업데이트가 일어나도, 아-업데이트 됐네! Team객체 업데이트가 일어나도, 아-! 업데이트 됐네! (왜냐하면 Team안에 List members안에 Member객체에 Team team이 테이블의 TEAM_ID(FK)랑 연관 관계 매핑이 되어 있을 거기 때문에 2연관 관계 매핑이 2번 됨)

둘 중 하나로 외래 키를 관리해야 한다.

이상하네?? 그래서 둘 중 하나로 외래 키를 관리하자.

연관 관계의 주인 (Owner) 개념

양방향 매핑 규칙 -객체의 두 관계중 하나를 연관 관계의 주인으로 지정! -연관관계의 주인만이 외래 키를 관리(등록, 수정) -주인이 아닌 쪽은 읽기만 가능(조회만 가능합니다! 값 업데이트 x) -주인은 mappedBy 속성 사용x -주인이 아니면 mappedBy 속성으로 주인 지정 (mappedBy = "team" Member객체의 team에 의해서 매핑이 된 상태이다~ 그러니 또 내 안의 내용 매핑하지 말어라~ 라는 의미로 쓰인다)

연관 관계 주인의 경우에만 테이블의 값을 업데이트 하게 했다.

결국 DB값 업데이트는 한 곳에서만 된다.

고민이 시작된다..

누구를 주인으로 해야하지?

외래키가 있는 곳을 주인으로 정해라

개발자가 인지하고 있어야 함.. 헷갈리게 됨... Team객체 업데이트 했는데? 왜?? MEMBER가 값이 바뀌지? 이런 불상사가;;

★추천★

순환 참조.. 양방향 연관 관계 말고, 단 방향 연관 관계로 조회할 수 있도록 만드는 게 훨씬 simple하고 good. 단 방향 연관 관계로 기본적으로 다 셋팅 해놓고... 만들어! 그러다가 어??? 반대로 조회 해야 할 것 같습니다. TEAM에서도 MemberList가 조회 되어야 할 것 같네요!!(충분히 그럴 수 있지. Team으로 Member 모아볼 수도 있고) 그럼 양방향 연관 관계로 바꿔. 어짜피 db에 영향 안 줘. 그저 자바 코드 몇 줄 추가하면 되잖아.

단 방향 연관 관계만으로도 이미 ORM 잘 되고 있어. 양 방향 연관 관계는 필요할 때만 써

양방향 매핑시 가장 많이 하는 실수

연관 관계의 주인에 값을 입력하지 않음.

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

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

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

em.persist(member);

주인이 아닌 곳에 값을 넣었어... 결과는?

TEAM_ID에 값이 안 들어감; 연관 관계 주인이 아니거든! mappedBy주어졌거든!

양방향 매핑의 장점

-단방향 매핑만으로도 이미 연관관계 매핑은 완료 -양방향 매핑은 반대 방향으로 조회(객체 그래프 탐색) 기능이 추가된 것 뿐 -JPQL에서 역방향으로 탐색할 일이 많음 -단방향 매핑 잘하고 양방향 필요할 때 추가하셈(DB영향 x) 그리고 양방향 매핑도 많이 쓰게 될 것

해당 포스팅은 T아카데미에서 진행한 김영한 강사님의 JPA 유튜브 강의를 듣고 정리한 것입니다 : ) https://www.youtube.com/watch?v=WfrSN9Z7MiA&list=PL9mhQYIlKEhfpMVndI23RwWTL9-VL-B7U

반응형

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

JPA 객체지향쿼리 - JPQL  (0) 2021.04.12
JPA 내부 구조. 영속성 컨텍스트  (0) 2021.04.12
JPA 연관관계 매핑-단방향 매핑  (0) 2021.04.11
JPA 필드와 칼럼 매핑  (0) 2021.04.11
JPA persistence.xml과 라이브러리 설정  (0) 2021.04.11