자바 ORM 표준 JPA 프로그래밍 [6-1]

김종하·2022년 7월 25일
0

JPA

목록 보기
9/10

자바 ORM 표준 JPA 프로그래밍 - 김영한
책 내용을 정리한 내용입니다.
6.1 다대일
6.2 일대다
6.3 일대일

들어가기 전

엔티티 연관관계 매핑시 고려해야할 것

  1. 다중성
  2. 단방향, 양방향
  3. 연관관계의 주인

연관관계가 있는 엔티티가 일대일 관계인지 일대다 관계인지 다중성을 고려하고,
엔티티 중 한쪽만 참조하는 단방향 관계인지 서로 참조하는 양방향 관계인지 고려하고,
양방향 관계라면 주인을 정해야한다.

다중성

  • 일대다 (@OneToMany)
  • 다대일 (@ManyToOne)
  • 일대일 (@OneToOne)
  • 다대다 (@ManyToMany)

단방향, 양방향

테이블은 외래키를 사용함으로 항상 양방향이다.
객체는 참조용 필드를 통해 연관된 객체를 조회한다. 한 쪽 객체만 참조하는 것을 단방향, 양 쪽 객체가 서로 참조하는 것을 양방향 관계라 한다.

연관관계의 주인

테이블에서 연관관계를 관리하는 포인트는 외래키 하나지만 엔티티는 양방향 연관관계에서 A.b / B.a 두 곳의 포인트에서 연관관계를 관리한다.
따라서 JPA 는 두 객체 연관관계 중 하나를 정해서 데이터베이스 외래키를 관리해야하며 이를 연관관계의 주인이라 한다.
외래키를 가진 테이블과 매핑한 엔티티가 외래키를 관리하는게 효율적임으로 해당 엔티티를 연관관계의 주인으로 선택하는 것을 권장한다.

6.1 다대일

다대일 단방향

@Entity
public class Member {

    @Id
    private Long id;

    private String memberName;

    @ManyToOne
    private Team team;
}


@Entity
public class Team {

    @Id
    private Long id;

    private String name;
}
  • N 인 Member 엔티티에서는 1 인 Team 을 참조할 수 있지만 Team 에서는 Member 를 참조하지 않는 관계
  • @JoinColumn 은 생략가능 생략시 : [참조 필드명(team)] + "_" + [참조엔티티 @Id 의 필드명 (id)] => team_id

다대일 양방향

@Entity
public class Member {

    @Id
    private Long id;

    private String memberName;

    @ManyToOne
    private Team team;
}


@Entity
public class Team {

    @Id
    private Long id;

    private String name;
    
    @OneToMany(mappedBy = "team")
    private List<Member> members;
}
  • Member 에서도 Team 을 참조할 수 있고 Team 에서도 Member 를 참조할 수 있다.
  • 일대다 혹은 다대일 연관관계에서 외래키는 항상 '다' 쪽에 있다 (테이블 구조상)
  • mappedBy 속성을 통해 연관관계의 주인을 설정할 수 있다. (Member.team 이 연관관계의 주인)
  • 주인이 아닌쪽은 조회만 가능하다.

6.2 일대다

일대다 단방향

@Entity
public class Member {

    @Id
    private Long id;

    private String memberName;
}


@Entity
public class Team {

    @Id
    private Long id;

    private String name;
    
    @OneToMany
    @JoinColumn(name = "team_id")
    private List<Member> members;
}
  • 일대다 단방향 관계는 실제 외래키 테이블(MEMBER 테이블) 과 외래키관리 엔티티(TEAM)의 위치가 반대편이다.
  • @JoinColumn 생략시 조인테이블 전략이 사용됨으로 @JoinColumn 을 명시하도록 한다.
  • 일대다 단방향의 경우 매핑한 객체가 관리하는 외래키가 다른테이블에 있음으로 저장과 연관관계 처리시 INSERT 할 떄 UPDATE 를 추가로 실행해야한다.
  • 일대다 단방향 매핑보다는 다대일 양방향 매핑을 사용하자

일대다 양방향

  • 일대다 양방향은 원칙적으로 존재하지 않는다 -> 다대일 양방향을 사용한다. (@ManyToOne 에는 mappedBy 속성이 없음)
  • @JoinColumn 을 Member 에 추가하고 insertable, updatable 을 false 로 설정하여 야매로 설정은 할 수 있다.
@Entity
public class Member {

    @Id
    private Long id;

    private String memberName;
    
    @ManyToOne
    @JoinColumn(name = "team_id", insertable = false, updatable = false) 
    private Team team;
}


@Entity
public class Team {

    @Id
    private Long id;

    private String name;
    
    @OneToMany
    @JoinColumn(name = "team_id")
    private List<Member> members;
}

6.3 일대일

  • 일대일 관계는 반대도 일대일 관계이다
  • 테이블 어느 쪽에나 외래키를 넣을 수 있다.
  • 외래키에 데이터베이스 유니크 제약조건을 추가해야한다.

주 테이블 외래키 단방향

// Member - 주 엔티티
// Locker - 대상 엔티티
@Entity
public class Member {

    @Id
    private Long id;

    private String userName;

    @OneToOne
    private Locker locker;
}

@Entity
public class Locker {

	@Id
    private Long id;
    
    private int number;
}

주 테이블 외래키 양방향

// Member - 주 엔티티
// Locker - 대상 엔티티
@Entity
public class Member {

    @Id
    private Long id;

    private String userName;

    @OneToOne
    private Locker locker;
}

@Entity
public class Locker {

	@Id
    private Long id;
    
    private int number;
    
    @OneToOne(mappedby = "locker")
    private Member member
}

대상 테이블 외래키 단방향

  • 불가능하다.

대상 테이블 외래키 양방향

// Member - 주 엔티티
// Locker - 대상 엔티티
@Entity
public class Member {

    @Id
    private Long id;

    private String userName;

    @OneToOne(mappedby = "member")
    private Locker locker;
}

@Entity
public class Locker {

	@Id
    private Long id;
    
    private int number;
    
    @OneToOne
    private Member member
}

0개의 댓글