본문 바로가기
Spring/JPA

연관관계 매핑

by o3oppp 2023. 12. 19.

객체 연관관계 (2개)

  • 회원 -> 팀 연관관계 1개(단방향)
  • 팀 -> 회원 연관관계 1개(단방향)
  • 객체의 양방향 관계는 서로 다른 단방향 관계 2개
  • 객체는 참조를 사용해서 연관된 객체를 찾음
  • 객체를 양방향으로 참조하려면 단방향 연관관계 2개를 만들어야 함

테이블 연관관계 (1개)

  • 회원 <-> 팀 연관관계 1개(양방향)
  • 테이블 양방향 연관관계는 외래키 하나로 두 테이블의 연관관계를 관리
  • 테이블은 외래키로 조인을 사용해서 연관된 테이블을 찾음

단방향

  • @ManyToOne : 해당 클래스가 N, 연관된 클래스가 1

양방향

  • @OneToMany(mappedBy = "연결된 엔티티의 연결된 변수명")
    • mappedBy : 나는 매핑이 되었다는 뜻으로 주인인이 아님을 명시

연관관계 주인

  • 객체 양방향 연관관계는 관리 주인이 필요
  • 객체의 두 관계 중 하나를 연관관계 주인으로 지정
  • 연관관계 주인만이 외래키를 관리(등록, 수정). 즉, 외래키가 있는 곳이 주인
  • 주인은 mappedBy 속성을 사용하지 않음
    • 주인이 아닌쪽은 읽기만 가능
    • 주인이 아니면 mappedBy 속성 사용
    • 주인이 아닌 방향만 연관관계를 설정하면 안됨
  • 양방향 매핑 시 무한 루프 주의
  • 주인에는 값을 입력해야 하나 그냥 항상 양쪽에 값을 설정
Team team = new Team();
team.setName("A");
em.persist(team);

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

//주인이 아닌 방향에만 연관관계 설정 : MEMBER TABLE 조회 시 TEAM_ID는 null
team.getMembers().add(member);

//연관관계 주인 또한 값 설정
member.setTeam(team);

em.persist(member);
  • 연관관계 없는 경우
@Entity
public class Member {

 @Id @GeneratedValue
 private Long id;

 @Column(name = "USERNAME")
 private String name;

 // 참조 대신 외래키를 그대로 사용
 @Column(name = "TEAM_ID")
 private Long teamId;
 ...
}
...

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

// 회원 저장
Member member = new Member();
member.setName("user1");

// 외래키 식별자를 직접 다룸
member.SetTeamId(team.getId());

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

// 연관관계가 없음
Team findTeam = em.find(Team.class, team.getId());

고려사항

다중성

  • 다대다
    • @ManyToOne
    • '다'가 연관관계 주인
  • 일대다
    • @OneToMany
    • '일'이 연관관계 주인
  • 일대일
    • @OneToOne
    • 주 테이블이나 대상 테이블 중 외래키 선택 가능
    • 주 테이블에 외래키
      • 장점 : 주 테이블 조회 시 대상 테이블에 데이터 유무 확인 가능
      • 단점 : 값이 없으면 외래키에 null 허용
    • 대상 테이블에 외래키
      • 장점 : 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변경할 때 테이블 구조 유지
      • 단점 : 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩 됨
  • 다대다
    • @ManyToMany
    • 대체로 실무에서 사용하지 않음

단방향, 양방향

  • 테이블
    • 외래키 하나로 양쪽 조인 가능
  • 객체
    • 참조용 필드가 있는쪽으로만 참조 가능
    • 한쪽만 참조하면 단방향, 양쪽이 서로 참조하면 양방향

연관관계 주인

  • 테이블은 외래키 하나로 두 테이블이 연관관계를 맺음
  • 객체 양방향 관계는 A->B, B->A 처럼 참조가 2곳, 둘 중 테이블의 외래키를 관리할 곳을 지정
  • 외래키를 관리하는 클래스, 참조가 연관관계 주인
  • 주인의 반대편 : 단순 조회만 가능(읽기만 가능)
@Entity
public class Member {

 @Id @GeneratedValue
 private Long id;

 @Column(name = "USERNAME")
 private String name;

 // 참조 대신 외래키를 그대로 사용
 /*
 @Column(name = "TEAM_ID")
 private Long teamId;
 */

 // 객체의 참조와 테이블의 외래키를 매핑
 @ManyToOne
 @JoinColumn(name = "TEAM_ID")
 private Team team;
 ...
}
...

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

// 회원 저장
Member member = new Member();
member.setName("user1");

// 외래키 식별자를 직접 다룸
/*member.SetTeamId(team.getId());*/

// 연관관계 저장
member.setTeam(team); // 단방향 연관관계 설정, 참조 저장
em.persist(member);

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

// 연관관계가 없음
/*Team findTeam = em.find(Team.class, team.getId());*/

// 참조로 연관관계 조회 - 객체 그래프 탐색
Team findTeam = findMember.getTeam();

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

MappedSuperclass  (0) 2023.12.20
상속관계 매핑  (0) 2023.12.20
엔티티 매핑  (0) 2023.08.25
영속성 관리  (0) 2023.08.22
JPA(Java Persistence API)란  (0) 2023.08.17