양방향 연관관계

노건우·2023년 10월 11일
0

Spring

목록 보기
17/22
post-thumbnail

1. 양방향 연관관계

  • 현재 예제의 객체는 Member가 Team을 가졌으나, Team은 Member를 가지지 못했다.
    즉 단방형이다.

2. 객체와 테이블이 관계를 맺는 차이

2-1. 테이블 연관관계 = 1개

  • 회원 <-> 팀의 연관관계 1개(양방향)
    -> MEMBER 테이블 입장에서 TEAM테이블 조인 가능
    -> TEAM테이블 입장에서 MEMBER테이블 조인 가능

    2-2. 객체 연관관계 = 2개

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

  • 팀 -> 회원 연관관계 1개(단방향)
    -> 사실은 단방향 연관관계가 2개 있는 것이다.
    억지로 양방향이라고 말하는 것

변경된 Team

변경된 Member

//양방향 매핑
		Member findSideMember = em.find(Member.class, member.getId());
		List<Member> members= findSideMember.getTeam().getMember();
		for(Member m : members) {
			System.out.println("result = " + m.getUsername());
		}

메인단에서 양방향을 위한 메서드를 설정해준다.

✍️양방형이라는 사실을 알 수 있다.

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

  • Member에서 Team으로 가능 참고 값과 Team에서 Member로 가는 members 참고 값이 있다.
    -Member에서 Team값이 수정됐을 때 MEMBER table의 TEAM_ID가 수정이 되야 하는지, Team에 있는 members를 수정했을 때 member에 있는 TEAM_ID가 수정이 되야 하는지?
    => DB입장에서는 TEAM_ID만 update가 된다.

⭐DB는 양방향 관계를 모르기 때문에 JAVA단에서 양방향 관계를 관리한다.
우리는 Team, Member 두 테이블로 나눈다.
1)Member에서 Team으로 외래키 관리 하는 경우는 Member 엔티티를 저장할 때 team 필드를 설정하여 TEAM_ID 컬럼을 업데이트한다. 이 방법을 사용하려면 Member 엔티티에서 team 필드를 수정해야 한다.
2)Team에서 Members로 외래키 관리하는 경우는 Team 엔티티에 새로운 Member를 추가하면 TEAM_ID 컬럼이 업데이트된다. 이 방법을 사용하려면 Team 엔티티에서 member 리스트에 멤버를 추가하면 된다.

4. 연관관계의 주인(Owner)

  • 양방향 매핑 규칙
  • 객체 두 관계 중 하나를 연관관계의 주인으로 지정
  • 연관관계 주인만이 외래키를 관리할 수 있다.(등록,수정)
  • 주인이 아닌쪽은 읽기만 가능
  • 주인은 mappedBy 속성 사용되지 않은쪽이 주인이다.
    -> 내가 누군가에게 의해서 mapping이 되었다. 라는 뜻
  • 주인이 아니면 mappedBy 속성으로 주인을 지정
  • mappedBy가 적힌 곳은 읽기만 가능. 값을 넣어봐야 아무 일도 벌어지지 않는다. 대신 조회는 가능

코드를 보자. 무엇이 mappedBy가 적혀 있는가? Team이다. 팀 같은 경우 여러 멤버를 선택할 수 있다. 따라서 list를 이용해 매핑해준다.

@ManyToOne
	@JoinColumn(name = "TEAM_ID")//fk키 걸기
	@Setter(value = AccessLevel.NONE) //LOMBOK에서 자동 SETTER를 막는다.
	private Team team; //Team에서 mappedBy = "team"으로 일치시켜야 함

이 코드는 Member의 부분인데, @JoinColumn 어노테이션을 이용해서 TEAM_ID를 fk값으로 받아왔다. 또한 private Team team은 Team에서 mappedBy한 결과값과 같아야 한다.

4-1 연관관계에서의 Owner란

JPA에서는 양방향 관계에서 주 관계와 종속 관계를 설정할 수 있다. 주 관계는 외래 키 관리를 담당하며, 종속 관계는 읽기 전용이다. 일반적으로 데이터를 변경하는 엔티티가 주 관계가 되는 것이 좋다.

결국 Member가 주인이므로 주 관계가 된다.

5. 주의 사항

  • jpaMain2에 insert문만 실행되고, select문은 실행되지 않았음
  • team이 영속성 컨텍스트에 들어가 있는데, 현재는 member가 할당되지 않은 상태에서 team으로 검색을 하니 1차 캐시에 담겨있는 내용 그대로가 조회가 된 것.
  • 즉, 영속성 컨텍스트 영역 사용시 team을 중심으로 member의 조회가 되지 않는다.
  • 순수 객체 상태를 고려해서 항상 양쪽에 값을 설정하자
    -> 연관관계 편의 메서드를 생성하자
  • 양방향 매핑시에 무한 루프를 조심해야 한다.
    ->toString(),lombok
    🖊️양방향 매핑시 가장 많이 하는 실수 
    <Member member = new Member();
    	member.setUsername("member1");
    	em.persist(member);
    	Team team = new Team();
    		team.setName("TeamA");
    	team.getMember().add(member);
    		em.persist(team);
         

    어떤 부분이 문제일까? Member 엔티티와 Team 엔티티의 관계 설정에서 문제가 있었다.
    양방향 매핑에서는 Member 엔티티와 Team 엔티티 간의 관계를 상호 설정해야한다. 하지만 이 코드는 team 테이블에 team 엔티티를 설정하고 있지만,Team 엔티티의 member 리스트에 member 엔티티를 추가하지 않고 있기에 문제가 발생했다.

    Member member = new Member();
    member.setUsername("member1");
    em.persist(member);
    Team team = new Team();
    team.setName("TeamA");
    // 양방향 관계 설정
    team.getMember().add(member);
    member.setTeam(team);
    em.persist(team);

이것이 올바른 코드이다.

6. 연관관계 편의 메서드 생성

  • N(다)에 넣기 : Member에 추가
  • 1(일)에 넣기 : Team에 추가

7. 양방향 매핑 정리

  • 단방향 매핑만으로도 이미 연관관계 매핑은 완료
  • 양방향 매핑은 반대 방향으로 조회 기능이 추가된 것 뿐
  • 양방향 사용 이유 : jpql에서 역방향으로 탐색 할 일이 많음
  • 단방향 매핑을 잘 하고,양방향은 필요할 때 추가해도 됨
    (테이블에 영향을 주지 않음)

8. 연관관계의 주인을 정하는 기준

  • 비지니스 로직을 기준으로 연관관계 주인을 선택하면 안된다.
  • 연관관계의 주인을 외래키의 위치를 기준으로 정해야 함
profile
초보 개발자 이야기

0개의 댓글

관련 채용 정보