-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8e21b97
commit b5ebb8c
Showing
1 changed file
with
137 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
# 5장 연관관계 매핑 기초 | ||
|
||
> 객체의 참조와 테이블의 외래키를 매핑 | ||
방향 : 한쪽만 참조하면 단방향 관계, 서로 참조하면 양방향 관계 | ||
다중성 : 다대일(N:1), 일대다(1:N), 일대일(1:1), 다대다(M:N) | ||
연관관계의 주인 : 객체를 연관관계로 만들면 연관관계의 주인을 정해야 한다. 연관관계의 주인은 테이블의 외래키가 있는 곳이다. | ||
|
||
## 5.1 단방향 연관관계 | ||
|
||
객체 연관관계 : 회원 객체는 `Member.team` 필드로 팀 객체와 연관관계를 맺는다. (단방향) | ||
테이블 연관관계 : 회원 테이블은 `TEAM_ID` 외래키로 팀 테이블과 연관관계를 맺는다.(양방향, 정확히는 서로 다른 단방향 2개) | ||
|
||
```sql | ||
SELECT * | ||
FROM MEMBER M | ||
JOIN TEAM T ON M.TEAM_ID = T.ID | ||
|
||
SELECT * | ||
FROM TEAM T | ||
JOIN MEMBER M ON T.ID = M.TEAM_ID | ||
``` | ||
|
||
연관된 데이터를 조회할 때 객체는 참조를 사용하지만 테이블은 조인을 사용한다. | ||
|
||
### 객체 그래프 탐색 | ||
객체는 참조를 사용해서 연관관계를 탐색할 수 있는데, 이것을 객체 그래프 탐색이라고 한다. | ||
|
||
### 조인 | ||
데이터베이스는 외래 키를 사용해서 연관관계를 탐색할 수 있는데 이것을 조인이라 한다. | ||
|
||
## 객체 관계 매핑 | ||
```java | ||
@Entity | ||
public class Member { | ||
@Id | ||
@GeneratedValue | ||
private String id; | ||
|
||
// 연관관계 매핑 | ||
@ManyToOne // 다대일 관계라는 매핑 정보 | ||
@JoinColumn(name = "TEAM_ID") // 외래키 매핑시 사용. 생략가능 | ||
private Team team; | ||
|
||
// ... | ||
} | ||
``` | ||
```java | ||
@Entity | ||
public class Team { | ||
@Id | ||
@Column(name = "TEAM_ID") | ||
private String id; | ||
|
||
private String name; | ||
|
||
// ... | ||
} | ||
``` | ||
|
||
### @JoinColumn | ||
|
||
| Modifier and Type | Optional Element | Description | | ||
|-|-|-| | ||
| java.lang.String | columnDefinition | (Optional) The SQL fragment that is used when generating the DDL for the column. | | ||
| ForeignKey | foreignKey | (Optional) Used to specify or control the generation of a foreign key constraint when table generation is in effect. | | ||
| boolean | insertable | (Optional) Whether the column is included in SQL INSERT statements generated by the persistence provider. | | ||
| java.lang.String | name | (Optional) The name of the foreign key column. | | ||
| boolean | nullable | (Optional) Whether the foreign key column is nullable. | | ||
| java.lang.String | referencedColumnName | (Optional) The name of the column referenced by this foreign key column. | | ||
| java.lang.String | table | (Optional) The name of the table that contains the column. | | ||
| boolean | unique | (Optional) Whether the property is a unique key. | | ||
| boolean | updatable | (Optional) Whether the column is included in SQL UPDATE statements generated by the persistence provider. | | ||
|
||
https://docs.jboss.org/hibernate/jpa/2.2/api/javax/persistence/JoinColumn.html | ||
|
||
### @ManyToOne | ||
|
||
| Modifier and Type | Optional Element | Description | | ||
|-|-|-| | ||
| CascadeType[] | cascade (Optional) The operations that must be cascaded to the target of the association. | | ||
| FetchType | fetch | (Optional) Whether the association should be lazily loaded or must be eagerly fetched. | | ||
| boolean | optional | (Optional) Whether the association is optional. | | ||
| java.lang.Class | targetEntity | (Optional) The entity class that is the target of the association. | | ||
|
||
https://docs.jboss.org/hibernate/jpa/2.2/api/javax/persistence/ManyToOne.html | ||
|
||
## 연관관계 사용 | ||
### 저장 | ||
### 수정 | ||
### 삭제 | ||
|
||
## 양방향 연관관계 | ||
### 매핑 | ||
### 조회 | ||
|
||
## 연관관계의 주인 | ||
두 객체 연관관계 중 하나를 정해서 테이블의 외래키를 관리해야하는데 이것을 연관관계의 주인(Owner)이라 한다. | ||
연관관계의 주인만이 데이터베이스의 연관관계와 매핑되고 외래 키를 관리(등록, 수정, 삭제)할 수 있따. 반면에 주인이 아닌 쪽은 읽기만 할 수 있다. | ||
연관관계의 주인을 정한다는 것은 사실 외래 키 관리자를 선택하는 것이다. (객체 입장) | ||
|
||
## 양방향 연관관계 유의점 | ||
가장 흔히 하는 실수는 연관관계의 주인에는 값을 입력하지 않고, 주인이 아닌 곳에만 값을 입력하는 것이다. | ||
|
||
### 순수한 객체까지 고려한 양방향 연관관계 | ||
객체 관점에서 양쪽 방향에 모두 값을 입력해주는 것이 가장 안전하다. | ||
|
||
### 연관관계 편의 메서드 | ||
```java | ||
public class Member { | ||
private Team team; | ||
|
||
/** | ||
* 양방향 관계를 모두 설정 | ||
* 실수로 하나만 호출해서 양방향 연관관계가 깨지는 것을 방지 | ||
*/ | ||
public void setTeam(Team team) { | ||
// 기존 팀이 있으면 삭제 | ||
if (this.team != null) { | ||
this.team.getMembers().remove(this); | ||
} | ||
this.team = team; | ||
team.getMembers().add(this); // 디미터의 법칙 | ||
} | ||
} | ||
``` | ||
|
||
https://johngrib.github.io/wiki/law-of-demeter/ | ||
|
||
## 정리 | ||
- 단방향 매핑만으로 테이블과 객체의 연관관계 매핑은 이미 완료되었다. | ||
- 단방향을 양방향으로 만들면 반대방향으로 객체 그래프 탐색 기능이 추가된다. | ||
- 양방향 연관관계를 매핑하려면 객체에서 양쪽 방향을 모두 관리해야 한다. | ||
- 연관관계의 주인은 외래키의 위치와 관련해서 정해야지 비즈니스 중요도로 접근하면 안된다. | ||
- 양방향 매핑시에는 무한루프에 빠지지 않게 조심해야한다. | ||
|
||
|