[JPA] 연관관계 매핑 기초

김영한 님의 ‘자바 ORM 표준 JPA 프로그래밍 - 기본편’ 강의 中

객체와 관계형 데이터베이스 모델링의 차이

<외래 키로="" 조인을="" 사용해서="" 연관된="" 테이블을="" 찾는="" 테이블="">과
<참조를 사용해서="" 연관된="" 객체를="" 찾는="" 객체=""> 사이의 큰 간격을 인지하는 것이 중요..!
아래 두개의 코드 블럭을 통해 차이를 느낄 수 있다. ```java /** 객체를 테이블에 맞추어서 모델링 했을 경우 */ @Entity public class Member { @Id @GeneratedValue private Long id; @Column(name = "USERNAME") private String name; @Column(name = "TEAM_ID") private Long teamId; … } @Entity public class Team { @Id @GeneratedValue private Long id; private String name; … } /** 메인 메서드 */ //팀 저장 Team team = new Team(); team.setName("TeamA"); em.persist(team); //회원 저장 Member member = new Member(); member.setName("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); ``` ```java @Entity public class Member { @Id @GeneratedValue private Long id; @Column(name = "USERNAME") private String name; private int age; // @Column(name = "TEAM_ID") // private Long teamId; @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(); ``` ## 단방향 연관관계 - @ManyToOne - @JoinColumn("TEAM_ID") ## ** 양방향 연관관계와 연관관계의 주인 ** @OneToMany(mappedBy="name")는 name 필드에 따라 관리된다는 의미(가짜 매핑)
(mappedBy는 처음에 이해하기 힘듬..!) - 객체의 경우, 양방향 연관관계를 나타내려면 사실상 단방향 연관관계 두개로 관리를 해야함.
- 테이블의 경우, 양방향 연관관계를 하나의 외래키로 관리할 수 있음.
여기서 객체로 양방향 연관관계를 관리할 때, 어느 쪽을 업데이트 해줘야 하는지 고민하는 부분에서 딜레마가 발생.

그래서 양방향 매핑에 있어서 연관관계의 주인을 하나 정해서 관리한다!
=> 외래 키가 있는 곳을 주인으로 정해야 한다.

(다대일의 경우 무조건 多인 테이블의 외래키가 주인이 되는 것)



\*양방향 매핑 규칙

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

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

-

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

- 주인은 mappedBy 속성 사용X - 주인이 아니면 mappedBy 속성으로 주인 지정 ## 양방향 연관관계의 주인 2 - 주의점, 정리 \* 컨트롤러에는 엔티티를 절대 반환하지 마라. \- 컨트롤러에서 엔티티를 JSON으로 API 스펙에 반환해버리면 문제가 생긴다. 엔티티는 웬만하면 단순히 값만 있는 형태인 DTO로 변환해서 반환하는 것을 권한다 . 1. 무한루프 생길 수 있음. 2. 나중에 엔티티를 변경하면 API 스펙 자체가 바뀌어 버릴 수 있다.
\* 단방향 매핑만으로 이미 연관관계 매핑 설계는 완료된 것. \- 양방향 매핑은 반대 방향으로 조회(객체 그래프 탐색) 기능이 추가된 것 뿐이다.

(reference) 참고하면 좋을 책 - '객체지향 설계의 목표는 자율적인 객체들의 협력 공동체를 만드는 것이다' - 객체지향의 사실과 오해, 조영호 저 참조를>외래>