티스토리 뷰
Member Team
--- ---
id id
team_id name
username
객체와 테이블 연관관계 정리
- 객체는 참조로 연관관계를 맺는다
- 테이블은 외래키로 연관관계를 맺는다
- 객체는 양방향으로 연관관계를 설정할 수 없다. 양쪽에 설정한다고 해도 서로 다른 단방향 관계 2개인 것이다.
어노테이션 사용
연관관계 매핑 시 다중성을 나타내는 어노테이션 사용 필수
@ManyToOne, OneToMany, OneToOne
attribute feature default value optional false 로 설정하면 연관된 엔티티가 항상 존재해야 한다. Inner Join true fetch 글로벌 페치 전략 설정 - @ManyToOne : EAGER @OneToMany : LAZY |
| cascade | 영속성 전이 기능 | |
| targetEntity | 연관된 엔티티의 타입 정보 설정.
거의 사용하지 않는다. deprecated?
컬렉션을 사용해도 제네릭으로 타입 정보를 알 수 있다. | |
@JoinColumn
외래 키를 매핑할 때 사용. 생략 가능
attribute feature default value name 매핑할 외래 키 컬럼명 {필드명}_{참조하는 테이블의 기본 키 컬럼명} referencedColumnName 외래 키가 참조하는 대상 테이블의 컬럼명 참조하는 테이블의 기본키 컬렴명 foreignKey(DDL) 외래 키 제약조건을 직접 지정할 수 있다. 이 속상은 테이블을 생성할 때만 사용 unique nullable insertable updatable columnDefinition table @Column 과 같다
단방향
다대일 N:1
일대일 관계와 유사. 어떤 걸 사용할지는 반대편 관계가 일대다인지 일대일인지를 보면 된다
코드
@Entity public class Member { @Id private String id; private String username; // 연관관계 매핑 @ManyToOne @JoinColumn(name = "team_id") private Team team; // 연관관계 설정 public void setTeam(Team team) {this.team = team;} } @Entity public class Team { @Id private String id; private String name; }
양방향
다대일
코드
@Entity public class Member { @Id private String id; private String username; // 연관관계 매핑 @ManyToOne @JoinColumn(name = "team_id") private Team team; // 연관관계 설정 public void setTeam(Team team) {this.team = team;} } @Entity public class Team { @Id private String id; private String name; // 연관관계 매핑. mappedBy : 반대쪽 매핑된 필드 이름 @OneToMany(mappedBy = "team") private List<Member> members = new ArrayList<Member>(); }
연관관계 주인
- 테이블과 달리 객체로 양방향 연관관계를 설정하면 관리 포인트가 두 곳이 된다.
- 따라서 테이블의 외래 키를 관리할 객체를 정해야 한다. 이를 연관관계의 주인이라 한다.
- 주인 객체가 외래키 등록, 수정, 삭제가 가능하고, 주인 객체가 아니면 읽기만 가능하다
- mappedBy 속성을 사용하지 않는 객체가 주인 객체이다.
- 주인은 테이블에 외래키가 있는 곳으로 정해야 한다.
주의점
연관관계의 주인인 곳에는 값을 입력하지 않고, 주인이 아닌 객체에만 값을 입력하는 것을 주의해야 한다.
그러나 순수 객체 관점에서 보면 둘다 값을 입력해주는 것이 좋다.
무한 루프에 빠지지 않게 조심해야 한다. toString() 같은 메서드나 JSON 으로 변환할 때 발생 가능하다.
결론
- 객체에서 양방향 연관관계를 사용하려면 로직을 견고하게 작성해야 한다.
- 양방향의 장점은 객체 그래프 탐색 기능이 추가된 것 뿐이다.
조인 테이블
조인 컬럼이 아닌 테이블로 두 테이블을 연결하는 방법이 있다
Parent parent_child Child
id parent_id(pk, fk) id
name child_id(unq, fk) name
username- 일대일 - 조인 테이블의 외래키 컬럼 각각에 유니크 인덱스를 설정해야 한다 - 코드 ```java @Entity public class Parent { @Id private String id; private String name; // 연관관계 매핑 @OneToOne @JoinTable(name = "parent_child", joinColumns = @JoinColumn(name = "parent_id), inverseJoinColumns = @JoinColumn(name = "child_id) ) private Child child; } @Entity public class Child { @Id private String id; private String name; // 양방향으로 하려면 설정 @OneToOne(mappedBy = "child") private Parent parent; } ```
- 일대다
- 다 에 해당하는 컬럼에 유니크 인덱스를 설정해야 한다 (여기서는 child_id)
- 코드
```java
@Entity
public class Parent {
@Id @GeneratedValue
private String id;
private String name;
// 연관관계 매핑
@OneToMany
@JoinTable(name = "parent_child",
joinColumns = @JoinColumn(name = "parent_id),
inverseJoinColumns = @JoinColumn(name = "child_id)
)
private List<Child> child = new ArrayList<Child>();
}
@Entity
public class Child {
@Id @GeneratedValue
private String id;
private String name;
// 양방향으로 하려면 설정
@ManyToOne(mappedBy = "child")
private Parent parent;
}
```
- 다대일
- 다 에 해당하는 컬럼에 유니크 인덱스를 설정해야 한다 (여기서는 child_id)
- 코드
```java
@Entity
public class Parent {
@Id @GeneratedValue
private String id;
private String name;
// 양방향으로 하려면 설정
@OneToMany(mappedBy = "parent")
private List<Child> child = new ArrayList<Child>();
}
@Entity
public class Child {
@Id @GeneratedValue
private String id;
private String name;
// 연관관계 매핑
@ManyToOne(optional = false)
@JoinTable(name = "parent_child",
joinColumns = @JoinColumn(name = "child_id),
inverseJoinColumns = @JoinColumn(name = "parent_id)
)
private Parent parent;
}
```
- 다대다
- 두 컬럼을 같이 복합 유니크 제약조건을 걸어야 한다.
- 조인 테이블에 외래키 이외의 새로운 컬럼을 추가하면 @JoinTable 을 사용할 수 없다.
대신 새로운 엔티티를 만들어서 매핑해야 한다
- 코드
```java
@Entity
public class Parent {
@Id @GeneratedValue
private String id;
private String name;
// 연관관계 매핑
@ManyToMany
@JoinTable(name = "parent_child",
joinColumns = @JoinColumn(name = "child_id),
inverseJoinColumns = @JoinColumn(name = "parent_id)
)
private List<Child> child = new ArrayList<Child>();
}
@Entity
public class Child {
@Id @GeneratedValue
private String id;
private String name;
}
```
'JPA' 카테고리의 다른 글
[QueryDSL] fetchResults()가 deprecated 된 이유 (0) | 2024.02.26 |
---|---|
JPA (1) - JPA 란? (0) | 2021.12.22 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- effective-java
- Spring-Boot
- TroubleShooting
- sort algorithm
- gitignore
- 메모리 릭
- ASCII
- SQL 전문가 가이드
- querydsl
- 코테 log
- annotation
- 사고..
- 이벤트스토밍
- ruby
- 실용주의
- aws
- IntelliJ
- WebClient
- 이펙티브자바
- SHA
- Encoding
- Java
- fetchResults
- DesignSystem
- Generic
- Git
- ActiveAdmin
- point
- 암호화
- Lombok
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
글 보관함