강의 출처:
https://www.inflearn.com/course/ORM-JPA-Basic#curriculum
자바 ORM 표준 JPA 프로그래밍 - 기본편 강의 - 인프런
K-개빈 킹 이 수식어가 어울리는 강사, 대한민국에서 사투리가 가장 섹시한 강사, 내 프로젝트에 의존성으로 추가하고 싶은 강사 강의결제를 고민하는 분들께 1) 너무 훌륭한 강의입니다. 무엇보
www.inflearn.com
해당 강의는 Inflearn에 등록된 김영한님의 Spring Boot 강의입니다.
이번장에는 객체간의 연관관계 설정에 대해 설명하겠다.
1. 연관 관계가 필요한 이유
연관관계가 필요한 이유는 한 테이블에서 다른 테이블의 정보도 조회가 필요할 경우를 예로 들 수 있다.
예제 시나리오
- 회원과 팀이 있다.
- 회원은 하나의 팀에만 소속될 수 있다.
- 회원과 팀은 다대일 관계이다.
왼쪽 사진과 같이 회원 객체
에 팀 객체의 기본키
를 외래키
로 등록했다 가정하자. 이렇게 멤버에는 팀의 기본키를 외래키로써 필드에 추가 한다 하더라도 팀
에서는 해당 Team의 id를 조회할 수 없다.
(멤버에서는 팀이라는 속성을 값을 setting 했다 하더라도 ORM을 한 후 Team 테이블에서는 멤버
의 값을 setting
안해줬기 때문이다.)
즉, 객체(Member)에는 DB 테이블(MEMBER) 처럼 외래키 등록 방법은이 다르다.(왼쪽 사진과 같이 DB테이블은 다른 테이블의 기본키를 등록하고 1:N 등만 표시하면 자동으로 외래키를 등록한다.)
2. 단방향 연관관계
우선 id
,name
2개의 속성을 가진 Team
객체 를 만들어보자.
@Entity //jpa가 관리하는 객체로 annotation
public class Team {
@Id
@GeneratedValue
@Column(name="Team_ID")
private Long id;
private String name;
...getter,setter
다시 본론으로 돌아가서 회원
이 가입된 팀
을 조회 한다고 해보자.
그러면 객체
에서 다대일
연관관계
는 매핑
은 어떻게 할까? 자바에서는 늘 그랬듯이 annotation
으로 명시하기만 하면 된다.
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
@Column(name = "USERNAME")
private String name;
private int age;
//단방향 연관관계 매핑->@ManyToOne annotation이용. 멤버(N):Team(1)
@ManyToOne
@JoinColumn(name="TEAM_ID") //참조할 객체에 TEAM_ID로 참조 할것임을 annotaion
private Team team;
...getter,setter 생성
코드 설명
아까와 달리 회원객체에 팀 객체를 외래키
로 등록하면된다. (Team team)
그리고 두개의 annotation
을 추가해야한다.
- @ManyToOne: 다대일(본인 객체 -> 다른 객체)
- @Joincolumn: JPA에서 해당 객체의 기본키를 외래키 등록하겠다고 명시
(+a: 회원 객체에 age라는 속성도 추가했고, getter,setter도 재설정해야 한다.)
3. 양방향 연관관계
단방향 매핑을 통해 Member가 Team에대한 연관관계를 설정했다. 덕분에 멤버에서는 본인이 속한 팀을 조회 할 수 있게 됐다.여기서 주의 할 점이 팀쪽에서는 멤버를 조회 할 수 있을까? 만약 멤버에서만 저렇게 외래키를 등록 했다고 팀 객체에서도 자동으로 연관관계가 자동으로 설정되면 좋겠지만 아쉽게도 그러하진 않다.
즉, Team객체에서도 Member객체를 setting해야한다. 이때 외래키로 등록은 아니다.
위 이미지를 보면 Team 객체에서 member 객체를 불러왔다. 하지만 테이블간에서는 Team 테이블에서는 안보인다. 위 이미지대로 객체에서는 서로에 대한 객체를 설정해야 연관관계가 설정된다.
@Entity //jpa가 관리하는 객체로 annotation
public class Team {
@Id
@GeneratedValue
@Column(name="Team_ID")
private Long id;
private String name;
//★★★★★★
@OneToMany(mappedBy = "team") //★★멤버 클래스에 선언되어있는 객체변수 이름.
private List<Member> members= new ArrayList<>(); //★★보통 리스트 선언시 arrayList로 초기화 하는 것은 관례이다.
...getter,setter
위 이미지를 토대로 Team 객체에 List 형태의 members 객체를 생성했다.
이때 @OneToMany(mappedBy="team") 라고 되어있다. 아래 코드는 Member에서 Team을 외래키로 등록하는 과정이다.
//단방향 연관관계 매핑->@ManyToOne annotation이용. 멤버(N):Team(1)
@ManyToOne
@JoinColumn(name="TEAM_ID") //참조할 객체에 TEAM_ID로 참조 할것임을 annotaion
private Team team;
Team 객체에서 Member 객체와 연관관계 매핑을 위해서는 Member에서 등록한 외래키인 Team객체의 객체변수 이름
으로 매핑하면 된다. <- 이것만 이해가 되면 연관관계의 절반은 이해가 간것이다.
4. 연관관계 주인
다음 차례로는 연관관계의 주인은 누구로 정하는가 이다. 이것을 왜 정하면 mappedBy
속성을 써야 하기 때문이다. 객체에서의 연관관계는 한 객체를 주인으로 만들고 그것과 연관관계를 갖는 다른 객체는 mappedBy
를 사용하여 양방향 연관관계를 만들기 때문이다.
다음은 양방향 매핑 규칙이다.
대부분 N쪽을 주인으로 정하고, 외래키를 지정한다. 1쪽에 mappedBy를 쓰면된다.
다음은 연관관계 주인이 외래키를 등록하여 실제로 매핑
하는 방법이다. 2가지단계
를 따른다.
1. 주인쪽(N)에서 연관관계 편의 메서드를 생성한다.
public void setTeam(Team team) {
this.team = team;
//★★★순수 객체 상태를 고려해서 항상 양쪽에 값을 설정하는게 좋다★★★
//팀에 멤버를 소속 시킴.
team.getMembers().add(this); //이러면 양쪽 다 값 세팅 가능.
}
2.. main함수에서 연관관계 메서드 호출
다음과 같은 코드를 main함수의 try문 안에 집어 넣고 실행
Team team = new Team();
team.setName("TeamA");
em.persist(team);
Member member = new Member();
member.setName("member1");
//연관관계 편의 메서드 사용
member.setTeam(team); //★★★ 멤버에 팀을 소속 시킴 ★★★
em.persist(member);
결과
위의 콘솔창에서 확인해보니 Member테이블에 FK로 team의 기본키인 team_id가 들어갔다.
H2 db에서도 마찬가지로 위의 두 쿼리를 실행해보니 Member테이블엔 team_id 속성이 들어가 있고, Team에는 members 객체가 없다. 이로써 객체간의 연관관계를 테이블간의 연관관계로 매핑 해 보았다.
여기서 한번더 정리를 추가해보겠다.
- 연관관계 주인은 외래키를 갖는 쪽으로 설정하고 반대편은
mappedBy
를 통해서 매핑하면 된다. - 실제로 연관관계가 시작되는 시점은 사용자가 연관관계 편의메서드를 주인쪽에서 만들고, 그 편의 메서드를 부르는 시점이다.
- 연관관계 편의 메서드는 다음과 같이 주인쪽 클래스에서 설정하면 된다.
public void set주인이 아닌 클래스(주인이 아닌 클래스 주인이 아닌 객체) {
this.주인이 아닌 객체 = 주인이 아닌 객체;
주인이 아닌 객체.get주인객체().add(this);
}
주인이 아닌 객체.get주인객체().add(this);
'Spring Boot > Spring Boot JPA-기본편 강의 정리(김영한)' 카테고리의 다른 글
[SpringBoot-JPA 기본편] 자바 ORM 표준 JPA 프로그래밍 - 기본편: 7. 고급 매핑 (1) | 2024.02.25 |
---|---|
[SpringBoot-JPA 기본편] 자바 ORM 표준 JPA 프로그래밍 - 기본편: 6. 다양한 연관관계 매핑 (0) | 2024.02.25 |
[SpringBoot-JPA 기본편] 자바 ORM 표준 JPA 프로그래밍 - 기본편: 3. 영속성 관리 (0) | 2024.02.23 |
[SpringBoot-JPA 기본편] 자바 ORM 표준 JPA 프로그래밍 - 기본편: 2. JPA 시작 (1) | 2024.02.23 |
[SpringBoot-JPA 기본편] 자바 ORM 표준 JPA 프로그래밍 - 기본편: 1. JPA 소개 (0) | 2024.02.23 |