JPA에 대해 알아보자 : 5장 연관관계 매핑 기초

ParkIsComing·2023년 1월 29일

Spring

목록 보기
3/21

책 [자바 ORM 표준 JPA 프로그래밍]을 참고하여 작성하였습니다.

5장 연관관계 매핑 기초

객체 연관관계 VS 테이블 연관관계

  • 객체는 참조(주소)로 연관관계를 맺는다.
    • 회원 객체가 있다면 member.getTeam() 이런 식으로 연관 데이터를 조회
    • 따라서 단방향
    • 양쪽에서 서로 참조하기 위해서는 단방향 관계 2개가 필요함
  • 테이블은 외래키로 연관관계를 맺는다.
    • JOIN을 사용하여 양방향 연관관계를 맺는다.
    • 즉, 외래키 하나로 양방향으로 조인하는 것이 가능하다.

JPA의 객체 관계 매핑

@Entity
pubic class Member{
	@Id
    @Column(name="MEMBER_ID")
    private String id;
    
    private String username;
    
    @ManyToOne
    @JoinColumn(name="TEAM_ID")
    private Team team;
    
    public void setTeam(Team team){
    	tihs.team = team;
    }
    
    //getter, setter 세팅 생략
}
@Entity
public class Team{
	@Id
    @Column(name="TEAM_ID")
    private String id;
    
    private String name;
    
    //getter, setter 세팅 생략

}

@ManyToOne

  • 다대일 관계 매핑
  • 속성
    • fetch : 글로벌 페치 전략 설정
      (기본값 :@ManyToOne=FetchType.EAGER, @OneToMany=FetchType.LAZY)
    • cascade : 영속성 전이 기능 사용

@JoinColumn

  • 외래키를 매핑할 때 사용
  • 속성
    • name : 매핑할 외래키 이름 지정
  • 생략 가능한 어노테이션

양방향 연관관계

  • 테이블은 외래 키 하나로 두 테이블의 연관관계를 관리
  • BUT, 객체의 연관관계를 관리하는 2곳
  • 따라서 어떤 관계를 사용해서 외래키를 관리할지 정해야
  • 이때 두 객체 연관관계 중 하나를 정해서 테이블의 외래키를 관리. 이것을 연관관계의 주인이라고 함.
  • 연관관계의 주인만이 데이터베이스 연관관계와 매핑되고 외래 키를 관리(등록, 수정, 삭제)할 수 있다.
  • 주인이 아닌 쪽은 읽기만 가능
  • 주인이 아닌 쪽에 mappedBy 속성을 사용하여 연관관계의 주인을 설정한다.
  • 연관관계의 주인은 테이블에 외래 키가 있는 곳으로 정한다.

    테이블의 다대일, 일대다 관계에서는 항상 '다' 쪽이 외래키를 가짐
    -> 항상 '다' 쪽이 연관관계의 주인이 됨
    -> 따라서 @ManyToOne에는 mappedBy 설정이 없다

양방향 연관관계 매핑

아래 예시에서는 회원 테이블이 외래키를 가지고 있으므로 Member.team이 주인이다.

@Entity
public class Member{
    @Id
    @Column(name="MEMBER_ID")
    private String id;
    
    private String username;
    
    @ManyToOne
    @JoinColumn(name="TEAM_ID")
    private Team team;
    
    public void setTeam(Team team){
        this.team = team;
    }
    
    //getter, setter 설정 생략
}
@Entity
public class Team {
    @Id
    @Column(name="TEAM_ID")
    private String id;
    
    private String name;
    
    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<Member>();
    
    //getter, setter 설정 생략
    
    
}

@OnetoMany

  • mappedBy 속성은 양방향 매핑일 때 사용. 반대쪽 매핑의 필드 이름을 값으로 주자.

연관관계의 주인을 정하는 기준

  • 단방향은 항상 외래키가 있는 곳을 기준으로 매핑
  • 양방향은 비즈니스 중요도를 기준으로 매핑하면 안 되고, 외래키 관리자로서 외래 키의 위치와 관련해서 연관관계의 주인을 정한다는 것을 기억하자.

일대다, 다대일 연관관계 매핑 예시

회원 엔티티

@Entity
@Data
public class Member{
    @Id
    @GeneratedValue
    @Column(name="MEBMER_ID")
    private Long id;
    
    private String name;
    
    private String city;
    private String street;
    private String zipcode;
    
    @OneToMany(mappedBy = "member")
    private List<Order> orders = new ArrayList<Order>();
    

}

주문 엔티티

@Entity
@Data
@Table(name="ORDERS")
public class Order {
    @Id
    @GeneratedValue
    @Column(name="ORDER_ID")
    private Long id;
    
    @ManyToOne
    @JoinColumn(name="MEMBER_ID") //외래키 : MEMBER_ID
    private Member member; //외래키가 있는 Order.member가 연관관계의 주인
    
    @OneToMany(mappedBy = "order")
    private List<OrderItem> orderItems = new ArrayList<OrderItem>();
    
    @Temporal(TemporalType.TIMESTAMP)
    private Date orderDate;
    
    @Enumerated(EnumType.STRING)
    private OrderStatus status;
    

    
}

주문상품

(주문 상품에서 상품을 참조할 일은 많으나, 반대의 경우는 거의 없으므로 주문상품과 상품은 다대일 단방향 관계로 설정)

@Entity
@Data
@Table(name="ORDER_ITEM")
public class OrderItem{
    @Id
    @GeneratedValue
    @Column(name="ORDER_ITEM_ID")
    private Long id;
    
    @ManyToOne
    @JoinColumn(name="ITEM_ID")
    private Item item;
    
    @ManyToOne
    @JoinColumn(name="ORDER_ID")
    private Order order;
    
    private int orderPrice;
    private int count;
    

}

상품 엔티티

@Entity
@Data
public class Item{
    @Id
    @GeneratedValue
    @Column(name="ITEM_ID")
    private Long id;
    
    private String name;
    private int price;
    private int stockQuantity;
    
    
}

~6장~

엔티티 연관관계 설정시 고려할 점

다중성

  • 다대일
  • 일대다
  • 일대일
  • 다대다

일대다의 반대방향은 항상 다대일
일대일의 반대는 항상 일대일
다대다 관계는 실무에서 거의 사용하지 않음.

단방향, 양방향

  • 테이블은 외래 키 하나로 조인 -> 양방향으로 쿼리 가능
  • 객체는 참조용 필드를 가지고 있는 객체만 연관된 객체를 조회할 수 있음
  • 객체 관계에서 한쪽만 참조 -> 단방향 관계
    양쪽이 서로 참조 -> 양방향 관계

연관관계의 주인

  • 외래키를 가진 테이블과 매핑한 엔티티가 외래키를 관리하는 게 효율적이므로 연관관계의 주인으로 선택
  • 주인이 아닌 방향은 외래키를 변경할 수 없고 읽기만 가능
  • 연관관계의 주인이 아니면 mappedBy 속성을 사용하고 값은 연관관계의 주인 필드 이름으로 한다.

0개의 댓글