2021. 2. 4. 18:31ㆍ프로그래밍 언어/Spring Framework
[인프런 김영한] 연관관계 매핑 기초 - 단방향 연관관계
해당 글은 인프런 김영한강사님의 영상을 보고 정리한 글입니다.
Spring Boot, Spring Data JPA를 사용해 실습하였습니다.
김영한 인프런 : www.inflearn.com/users/@yh
▣ Goal
1. 객체와 테이블 연관관계의 차이를 이해
2. 객체의 참조와 테이블의 왜래 키를 매핑
▣ 다대일[N:1]
| 테이블 연관관계로 Member 테이블에 Team의 FK가 있다.
이 때의 주인은 Member가 된다.
◈ 객체를 테이블에 맞추어 모델링
(참조 대신 왜래키를 그대로 사용(Long TeamId)하는 방법, 하면 안되요!)
▣ 코드
@Entity
@Setter
@Getter
public class Team {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
}
@Entity
@Setter
@Getter
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME")
private String username;
@Column(name = "TEAM_ID")
private Long teamId; //team_id
}
| Team을 참조하는게 아닌, Team의 id의 값을 참조하는 방식.
▣ 예제
@SpringBootApplication
public class JpatestApplication {
private static TeamRepository teamRepository;
private static MemberRepository memberRepository;
public JpatestApplication(TeamRepository teamRepository, MemberRepository memberRepository) {
this.teamRepository = teamRepository;
this.memberRepository = memberRepository;
}
public static void main(String[] args) {
SpringApplication.run(JpatestApplication.class, args);
Team team = new Team();
team.setName("TeamA");
teamRepository.save(team);
Member member = new Member();
member.setUsername("member1");
member.setTeamId(team.getId()); // ??? 왜래키 식별자를 그대로 사용함.
memberRepository.save(member);
Member findMember = memberRepository.findById(member.getId()).get();
Long findTeamId = findMember.getTeamId();
Team findTeam = teamRepository.findById(findTeamId).get();
...
}
}
| Team의 Id값만 있기 떄문에 Team에 대한 값을 바로 가지고오지 못하며, Member에서 TeamId를 찾고 다시 TeamId로 Team을 찾아야하는 번잡스러운 과정이 있다.
연관관계라는게 없기 때문에 계속 DB에 물어봐야 하고 객체지향스럽지 않다.
| 실제로 값을 insert해 보면 테이블 관계에서는 맞다.
※TEAM_ID 값이 1이고, MEMBER_ID값이 2인 이유
- H2 DB에서는 create sequence hibernate_sequence start with 1 increment by 1 쿼리로 인해 테이블 공용으로 사용.
※ 문제
객체를 테이블에 맞추어 데이터 중심으로 모델링 하면, 협력관계를 만들 수 없다.
-> 테이블은 왜래키로 조인을 사용해서 연관된 테이블을 찾는다.
-> 객체는 참조를 사용해서 연관된 객체를 찾는다.
-> 테이블과 객체 사이에는 이런 큰 간격이 있다.
◈ 객체를 테이블에 맞추어 모델링 -> 객체 지향 모델링으로 변경
▣ 코드
@Entity
@Setter
@Getter
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME")
private String username;
// @Column(name = "TEAM_ID")
// private Long teamId; //team_id
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
}
| Long teamId가 아닌, Team을 그대로 참조한다.
▣ 예제
@SpringBootApplication
public class JpatestApplication {
public static void main(String[] args) {
SpringApplication.run(JpatestApplication.class, args);
}
private static TeamRepository teamRepository;
private static MemberRepository memberRepository;
public JpatestApplication(TeamRepository teamRepository, MemberRepository memberRepository) {
this.teamRepository = teamRepository;
this.memberRepository = memberRepository;
Team team = new Team();
team.setName("TeamA");
teamRepository.save(team);
Member member = new Member();
member.setUsername("member1");
// member.setTeamId(team.getId());
member.setTeam(team);
memberRepository.save(member);
// 조회
// 기존) member를 찾고 member의 teamid를 찾아서 team을 찾았음.
// 이후) member를 찾고 member의 team을 찾음
Member findMember = memberRepository.findById(member.getId()).get();
Team findTeam = findMember.getTeam();
System.out.println("findTeam = " + findTeam.getName());
}
}
````````````````````````````````````````````````````````````````````````````
// 결과 (SQL문)
select
member0_.member_id as member_i1_0_0_,
member0_.team_id as team_id3_0_0_,
member0_.username as username2_0_0_,
team1_.team_id as team_id1_1_1_,
team1_.name as name2_1_1_
from
member member0_
left outer join
team team1_
on member0_.team_id=team1_.team_id
where
member0_.member_id=?
findTeam = TeamA
| 결과를 보면 left outer join을 이용해 select하는것을 확인할 수 있다.
'프로그래밍 언어 > Spring Framework' 카테고리의 다른 글
[인프런 김영한] JPA - 데이터베이스 스키마 자동생성 (0) | 2021.02.07 |
---|---|
[인프런 김영한] JPA 연관관계 - 다양한 연관관계 (N:1, 1:N, 1:1, N:M) (0) | 2021.02.05 |
[인프런 김영한] 연관관계 매핑 기초 - 양방향 연관관계 매핑시 가장 많이 하는 실수 (0) | 2021.02.04 |
[인프런 김영한] 연관관계 매핑 기초 - 양방향 연관관계 (0) | 2021.02.03 |
스프링 AOP 용어 , 스프링 네임스페이스 (0) | 2018.01.18 |