[JPA] 자바 ORM 표준 JPA 프로그래밍 ch.6

박지운·2023년 8월 1일
0
post-thumbnail

김영한님의 '자바 ORM 표준 JPA 프로그래밍'을 읽고 정리한 글입니다.


6장

✔ 다대일

  • 객체 양방향 관계에서 연관관계의 주인은 항상 다쪽이다.
  • 양방향은 외래 키가 있는 쪽이 주인이다.
    예시에서 Team.members느 조회를 위한 JPQL이나 객체 그래프를 탐색할 때만 사용한다.
  • 양방향은 항상 서로를 참조해야 한다.
    어느 한 쪽만 참조하면 연관관계가 성립하지 않는다.
    예시처럼 setTeam()이나 addMember()로 메소드를 작성하는 것이 좋다.

✔ 일대다

  • 다대일 관계의 반대 방향이다. 항상 하나 이상 참조할 수 있으므로 자바 컬렉션인 Collection, List, Set, Map 중에 하나를 사용해야 한다.

일대다 단방향

먼저 일대다 단방향은 잘 사용하지 않는 것이 좋다.
왜 그런지 살펴보자.

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문이 나간다!!
    연관관계에 대한 정보는 Team의 members가 관리하기 때문이다. Member엔티티를 저장시 MEMBER테이블의 TEAM_ID 외래키에는 아무 값도 저장되지 않는다. 대신 Team엔티티를 저장할 때 Team.members의 참조 값을 확인해 업데이트하는 것이다.

-> 성능, 관리도 힘들다 때문에 다대일 양방향을 권장!

일대다 양방향

일대다 단방향 + 다대일 단방향을 추가한 것이다. 이렇게 되면 둘 다 같은 키를 관리한다. 따라서
반대편 다대일을 insertable=false, updatable=false로 설정해 읽기만 가능하게 해야한다.
이는 일대다 단방향의 단점이 그대로 있으므로 다대일 양항뱡 권장!


✔ 일대일

양쪽이 서로 하나의 관계만 가진다. 회원과 사물함의 관계와 같다.
일대일은 다가 없으므로 어디든 키를 관리할 수 있다. 선택이 필요하다.

주 테이블에 외래 키

JPA는 주 테이블에 외래 키가 있으면 좀 더 편리하게 매핑할 수 있다.

대상 테이블에 외래 키

JPA는 일대일 관계에서 대상 테이블에 외래 키가 있는 단방향 관계는 지원하지 않는다.

프록시 사용시 외래 키를 직접 관리하지 않는 일대일 관계는 지연 로딩으로 설정해도 즉시 로딩된다. 
예제에서 Locker.member는 지연로딩이 가능하지만 Member.locker는 즉시 로딩된다.
이것은 프록시의 한계때문이다.(8장)

✔ 다대다

회원과 상품의 관계는 다대다 관계이다. 중간 연결 테이블이 필요하다. Member_Product 연결 테이블이 그것이다. 그런데 객체는 테이블과 다르게 객체 2개로 다대다 관계를 만들 수 있다. 회원 객체는 컬렉션을 사용해서 상품들을 참조하면 되고 상품들도 컬렉션을 사용해서 회원들을 참조하면 된다.

@ManyToMany를 사용하면 편리하게 매핑이 가능하다.

  • 한계
    - 편리해보이지만 실무에서 사용하지 않는다.
    - 연결 테이블이 단순히 연결만 하는 것이 아니기 때문
    -> 회원 - 상품에서 주문시간, 수량 같은 데이터가 들어올 수도 있다.

한계 극복

- 연결 테이블용 엔티티를 추가해야한다. 
- @ManyToMany를 @OneToMany, @ManyToOne으로 풀어야한다.

업로드중..


✔ 정리

  • 테이블의 N:M 관계는 중간 테이블을 이용해서 1:N, N:1로 만들어야한다.
  • 실무에서 중간테이블이 단순하지 않고 @ManyToMany는 제약이 있다.
profile
앞길막막 전과생

0개의 댓글