김영한님의 '자바 ORM 표준 JPA 프로그래밍'을 읽고 정리한 글입니다.
먼저 일대다 단방향은 잘 사용하지 않는 것이 좋다.
왜 그런지 살펴보자.
public class Team {
@ID @GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
...
@OneToMany
@JoinColumn(name ="TEAM_ID")
private List<Member> members = new ArrayList<Member>();
일대다 단방향시 @JoinColumn 명시를 하지 않을 경우 JPA는 조인 테이블
전략을 사용해 매핑한다.
```java
public void testSave() {
Member member = new Member("member1");
Team team = new Team("team1");
team.getMembers().add(member);
em.persist(member);
em.persist(team);
transaction.commit();
}
```
이 경우 쿼리문을 보면 insert문 두번에 추가로 update문이 나간다!!-> 성능, 관리도 힘들다 때문에 다대일 양방향을 권장!
일대다 단방향 + 다대일 단방향을 추가한 것이다. 이렇게 되면 둘 다 같은 키를 관리한다. 따라서
반대편 다대일을 insertable=false, updatable=false로 설정해 읽기만 가능하게 해야한다.
이는 일대다 단방향의 단점이 그대로 있으므로 다대일 양항뱡 권장!
양쪽이 서로 하나의 관계만 가진다. 회원과 사물함의 관계와 같다.
일대일은 다가 없으므로 어디든 키를 관리할 수 있다. 선택이 필요하다.
JPA는 주 테이블에 외래 키가 있으면 좀 더 편리하게 매핑할 수 있다.
JPA는 일대일 관계에서 대상 테이블에 외래 키가 있는 단방향 관계는 지원하지 않는다.
프록시 사용시 외래 키를 직접 관리하지 않는 일대일 관계는 지연 로딩으로 설정해도 즉시 로딩된다.
예제에서 Locker.member는 지연로딩이 가능하지만 Member.locker는 즉시 로딩된다.
이것은 프록시의 한계때문이다.(8장)
회원과 상품의 관계는 다대다 관계이다. 중간 연결 테이블이 필요하다. Member_Product 연결 테이블이 그것이다. 그런데 객체는 테이블과 다르게 객체 2개로 다대다 관계를 만들 수 있다. 회원 객체는 컬렉션을 사용해서 상품들을 참조하면 되고 상품들도 컬렉션을 사용해서 회원들을 참조하면 된다.
@ManyToMany
를 사용하면 편리하게 매핑이 가능하다.
- 연결 테이블용 엔티티를 추가해야한다.
- @ManyToMany를 @OneToMany, @ManyToOne으로 풀어야한다.
✔ 정리