반응형
JPA 게시글은 대부분 인프런의 김영한님의 강의인 '자바 ORM 표준 JPA 프로그래밍' 기반으로 내용을 정리했습니다.
단방향 연관관계
예제 시나리오
- 회원과 팀이 존재한다.
- 회원은 하나의 팀에만 소속될 수 있다.
- 회원과 팀은 다대일 관계이다.
객체를 테이블화한 모델링
객체 클래스 생성(Member)
@Entity
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;
...getter/setter 생략
}
객체 클래스 생성(Team)
@Entity
public class Team {
@Id
@GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
...getter/setter 생략
}
실행 클래스
...생략
// 팀 저장
Team team = new Team();
team.setName("Team A");
em.persist(team);
// 회원 저장
Member member = new Member();
member.setUsername("member1");
member.setTeamId(team.getId()); // 이 부분이 애매하다.
em.persist(member);
// 조회
Member findMember = em.find(Member.class, member.getId());
Long findTeamId = findMember.getTeamId();
Team findTeam = em.find(Team.class, findTeamId);
tx.commit();
...생략
테이블에 맞춰 코드를 작성하면 객체지향스럽지 않다. 그리고 불필요하게 DB에 계속 접근하게 된다. 이렇게 불편하게 코딩하는 이유는 연관 관계가 없기 때문이다. 연관 관계가 없는 이유는 데이터 중심으로 모델링하여 협력 관계를 만들 수 없기 때문이다.
- 테이블은 외래 키로 조인을 사용해서 연관된 테이블을 찾는다.
- 객체는 참조를 사용해서 연관된 객체를 찾는다.
- 테이블과 객체 사이에는 이런 큰 간격이 있다.
이런 문제점들로 인하여 객체를 중심으로 연관 관계를 맺어 코딩하는 것이 더 좋다.
객체 지향 모델링
객체 클래스(Member)
@Entity
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;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
...getter/setter 생략
}
기존 Team 테이블과 연관된 필드인 teamId를 주석처리하고 대신 team 필드를 추가했다.
- @ManyToOne : 연관 관계를 표현한다. Member와 Team의 관계가 Member 입장에서 봤을 때 다대일이다. 고로 Member 필드에 ManyToOne 애노테이션을 붙인다.
- @JoinColumn : 객체 지향 모델링을 봤을 때 Member는 TEAM_ID를 외래키로 가져 연관 관계를 나타낸다. 그러므로 TEAM_ID로 Member와 Team 객체에 연관 관계를 맺어준다.
실행 클래스
...생략
// 팀 저장
Team team = new Team();
team.setName("Team A");
em.persist(team);
// 회원 저장
Member member = new Member();
member.setUsername("member1");
member.setTeam(team);
em.persist(member);
// JOIN 쿼리를 보기 위해
em.flush();
em.clear();
// 조회
Member findMember = em.find(Member.class, member.getId());
Team findTeam = findMember.getTeam();
tx.commit();
...생략
연관 관계가 없었던 맨 위에 코드와는 달리 조금 더 객체지향스럽게 느껴지는 코드이다. 위의 코드를 실행하면 다음과 같은 join 로그를 볼 수 있다.
Hibernate:
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=?
반응형