테이블은 외래 키로 조인을 사용하여 연관된 테이블을 찾지만 객체는 참조를 사용해서 연관된 객체를 찾는다.
테이블과 객체사이에 이런 차이점 때문에 객체를 테이블에 맞추어 데이터 중심으로 모델링하면 협력 관계를 만들 수 없다.
때문에 연관관계를 설정해주어서 객체의 참조와 테이블의 외래키를 매핑해줄 수 있다.
1. 단방향 연관관계
@Entity
public class Member {
@Id
@GeneratedValue
private Long id;
@Column(name = "USERNAME")
private String name;
private int age;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
}
//팀 저장
Team team = new Team();
team.setName("TeamA");
em.persist(team);
//회원 저장
Member member = new Member();
member.setName("member1");
member.setTeam(team); //단방향 연관관계 설정, 참조 저장
em.persist(member);
//조회
Member findMember = em.find(Member.class, member.getId());
//참조를 사용해서 연관관계 조회
Team findTeam = findMember.getTeam();
// 새로운 팀B
Team teamB = new Team();
teamB.setName("TeamB");
em.persist(teamB);
// 회원1에 새로운 팀B 설정
member.setTeam(teamB);
2. 양방향 연관관계
단방향 연관관계에서 멤버 엔티티에서 팀 엔티티로의 접근만 가능했던것과 달리 양방향 연관관계로 설정하면 팀 엔티티에서 멤버 엔티티로 접근도 가능하다.
// Member 엔티티는 동일
@Entity
public class Team {
@Id
@GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "team")
List<Member> members = new ArrayList<Member>();
…
}
mappedBy속성은 양방향 매핑일 때 사용하며 반대쪽 매핑의 필드 명을 값으로 주면 된다.
//조회
Team findTeam = em.find(Team.class, team.getId());
int memberSize = findTeam.getMembers().size(); //역방향 조회
3. 연관관계의 주인
3.1 객체와 테이블이 관계를 맺는 차이
객체가 양방향 연관관계를 맺는 방식은 2개의 단방향 연관관계를 맺는것이다
(팀 -> 멤버 / 멤버 -> 팀)
하지만 테이블의 연관관계는 외래키 하나로 두 테이블의 연관관계를 맺어 조인을 함으로써 두 테이블 간 참조가 가능하다.
ORM은 결국 객체를 관계형 데이터베이스에 매핑시키는것이기 때문에 객체의 2개의 연관관계 중 하나로 외래키를 관리해주어야 한다.
3.2 연관관계의 주인
양방향 매핑 규칙
- 객체의 두 관계중 하나를 연관관계의 주인으로 지정
- 연관관계의 주인만이 외래 키를 관리(등록, 수정)
- 주인이 아닌쪽은 읽기만 가능
- 주인은 mappedBy 속성 사용X
- 주인이 아니면 mappedBy 속성으로 주인 지정
그렇다면 두 연관관계 중 어떤 연관관계를 주인으로 정해야할까
외래키가 있는 곳을 주인으로 정해야한다.
양방향 매핑 정리
- 단방향 매핑만으로도 이미 연관관계 매핑은 완료
- 양방향 매핑은 반대 방향으로 조회(객체 그래프 탐색) 기능이 추 가된 것 뿐
- JPQL에서 역방향으로 탐색할 일이 많음
- 단방향 매핑을 잘 하고 양방향은 필요할 때 추가해도 됨 (테이블에 영향을 주지 않음)
'백엔드(Back End) > Spring' 카테고리의 다른 글
[TIL]20230828 - 톰캣 튜닝 (0) | 2023.09.05 |
---|---|
[TIL]20230824 - 다양한 연관관계 매핑 (1) | 2023.08.30 |
[TIL]20230819 - JPA와 ORM, 엔티티 매니저와 영속성 매니저 (0) | 2023.08.23 |
[TIL]20230818 - Redis 캐싱 전략 (0) | 2023.08.21 |
[TIL]20230809 - JPA save()와 saveAll()의 차이 (0) | 2023.08.11 |