본문 바로가기
백엔드(Back End)/Spring

[TIL]20230821 - 엔티티 연관관계 설정

by tjsdn9803 2023. 8. 28.

테이블은 외래 키로 조인을 사용하여 연관된 테이블을 찾지만 객체는 참조를 사용해서 연관된 객체를 찾는다.

테이블과 객체사이에 이런 차이점 때문에 객체를 테이블에 맞추어 데이터 중심으로 모델링하면 협력 관계를 만들 수 없다.

때문에 연관관계를 설정해주어서 객체의 참조와 테이블의 외래키를 매핑해줄 수 있다.

1. 단방향 연관관계

 @Entity
 public class Member {
 	@Id 
 	@GeneratedValue
 	private Long id;
    
 	@Column(name = "USERNAME")
 	private String name;
    
 	private int age;
    
 	@ManyToOne
 	@JoinColumn(name = "TEAM_ID")
 	private Team team;
 }
//팀 저장
 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();
 
 // 새로운 팀B
 Team teamB = new Team();
 teamB.setName("TeamB");
 em.persist(teamB);
 
 // 회원1에 새로운 팀B 설정
 member.setTeam(teamB);

2. 양방향 연관관계

단방향 연관관계에서 멤버 엔티티에서 팀 엔티티로의 접근만 가능했던것과 달리 양방향 연관관계로 설정하면 팀 엔티티에서 멤버 엔티티로 접근도 가능하다.

// Member 엔티티는 동일

 @Entity
 public class Team {
 	@Id 
    @GeneratedValue
 	private Long id;
    
 	private String name;
    
 	@OneToMany(mappedBy = "team")
 	List<Member> members = new ArrayList<Member>();
 	…
 }

mappedBy속성은 양방향 매핑일 때 사용하며 반대쪽 매핑의 필드 명을 값으로 주면 된다.

 //조회
 Team findTeam = em.find(Team.class, team.getId());
 int memberSize = findTeam.getMembers().size(); //역방향 조회

3. 연관관계의 주인

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

객체가 양방향 연관관계를 맺는 방식은 2개의 단방향 연관관계를 맺는것이다

(팀 -> 멤버 / 멤버 -> 팀)

하지만 테이블의 연관관계는 외래키 하나로 두 테이블의 연관관계를 맺어 조인을 함으로써 두 테이블 간 참조가 가능하다.

ORM은 결국 객체를 관계형 데이터베이스에 매핑시키는것이기 때문에 객체의 2개의 연관관계 중 하나로 외래키를 관리해주어야 한다.

3.2 연관관계의 주인

양방향 매핑 규칙

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

그렇다면 두 연관관계 중 어떤 연관관계를 주인으로 정해야할까

외래키가 있는 곳을 주인으로 정해야한다.

양방향 매핑 정리

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