JPA(연관관계 매핑)

김영환·2023년 10월 11일
0

JPA

목록 보기
4/4

1. 연관관계 매핑 기초

  • 객체와 테이블 연관관계의 차이를 이해
  • 객체의 참조와 테이블의 외래키를 매핑
  • 용어 이해

    -> 방향(Direction) : 단방향, 양방향
    -> 다중성(Muliplicity) : 다대일(N:1), 일대다(1:N), 일대일(1:1), 다대다(N:N)
    -> 연관관계 주인(Owner) : 객체 양방향 연관관계는 관리하는 주인이 필요

#가정
1. 회원과 팀이 있다.
2. 회원과 팀은 다대일 관계이다.

객체 테이블에 맞추어 모델링

회원과 팀 클래스

@Entity
@Getter @Setter
public class Member {

	@Id
	@GeneratedValue
	@Column(name = "MEMBER_ID")
	private Long id;
	private String username;
    @Column(name = "TEAM_ID")
  	private Long teamId;
}
-------------------------------------
@Entity
@Getter @Setter
public class Team {

	@Id
	@GeneratedValue
	@Column(name = "TEAM_ID")
	private Long id;
	private String name;
}

팀과 회원 저장하는 코드

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

//회원 저장
Member member = new Member();
member.setName("userA");
member.setTeamId(team.getId());
em.persist(member);

회원의 팀을 찾는 코드

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

Long findTeamId = findMember.getId();
Team findTeam = em.find(Team.class, findTeamId);

연관관계가 없다면 위처럼 객체 지향스럽지 안은 코드가 된다.
하지만 연관관계를 맺게 되면

달라진 회원과 팀 클래스

@Entity
@Getter @Setter
public class Member {

	@Id
	@GeneratedValue
	@Column(name = "MEMBER_ID")
	private Long id;
	private String username;
    @ManyToOne
  	@JoinColumn(name = "TEAM_ID")
  	private Team team;
}
-------------------------------------
@Entity
@Getter @Setter
public class Team {

	@Id
	@GeneratedValue
	@Column(name = "TEAM_ID")
	private Long id;
	private String name;
}

연관관계 저장

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

//회원 저장
Member member = new Member(); 
member.setName("userA");
member.setTeam(team);  
em.persist(member);

조회

//조회
Member findMember = em.find(Member.class, member.getId());
//참조를 사용해서 연관관계 조회
Team findTeam = findMember.getTeam();

단방향, 양방향에 쓰이는 어노테이션
@ManyToOne(단방향) : 다대일 관계라는 매핑 정보
@JoinColumn : 외래 키를 매핑할 때 사용
@OneToMany(양방향) : 괸계 주인의 정보를 조회할 수 있도록 하는 양방향 매핑 코드

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

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

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

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

2-2. 연관관계 주인(Owner)

  • 양방향 매핑 규칙

  • 객체의 두 관계 중 하나를 연관관계의 주인으로 지정

  • 연관관계 주인만이 외래 키를 관리(등록, 수정)

  • 주인이 아닌 쪽은 읽기만 가능

  • 주인은 mappedBy 속성이 사용되지 않은 쪽이 주인이다.
    -> 내가 누군가에게 의해서 mapping이 되었다 라는 뜻

  • 주인이 아니면 mappedBy 속성으로 주인을 지정

  • mappedBy가 적힌 곳은 읽기만 가능하다. 값을 넣어봐야 아무일도 벌어지지 않는다. 대신 조회는 가능

    2-3. 주의사항

  • 영속성 컨텍스트 영역 사용시 team을 중심으로 member의 조회가 되지 않는다.

  • 순순 객체 상태를 고려해서 항상 양쪽에 값을 설정하자
    -> 연관관계 편의 메서드를 생성하자

  • 양방향 매핑시 무한 루프를 조심하자
    -> toString(), lombok

3. 양방향 매핑 정리

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

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

  • 비지니스 로직을 기준으로 연관관계 주인을 선택하면 안됨
  • 연관관계의 주인은 외래 키의 위치를 기준으로 정해야함
profile
개발

0개의 댓글