JPA

실전 예제 3 - 다양한 연관관계 매핑

방구석 대학생 2020. 10. 6. 19:53

"인프런 - 자바 ORM 표준 JPA 프로그래밍 강의를 듣고 작성한 글 입니다."

www.inflearn.com/course/ORM-JPA-Basic#

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다. 초급 웹 개발 프로그

www.inflearn.com

 

이번엔 다양한 연관관계 매핑 에서 배운 일대일, 다대다 와 같은 연관관계를 이용하여, 배송, 카테고리 도메인 클래스를 생성한 후 연관관계를 매핑해보자.

 

이번 글에서 매핑할 연관관계는 아래와 같다.

1. Order - Delivery : 일대일 양방향 매핑 - 외래 키는 주 테이블인 Order 테이블에 넣는다.

2. Category - Item : 다대다 양방향 매핑 - 연결 테이블로 매핑한다.(CATEGORY_ITEM)

 

1. Order - Delivery : 일대일 양방향 매핑

- Order.java

@OneToOne
@JoinColumn(name = "DELIVERY_ID")
private Delivery delivery;

 

Delivery 클래스의 경우 따로 enum 타입의 DeliveryStatus 클래스를 생성해 주어야 한다.

- Delivery.java

@Entity
public class Delivery {

	@Id @GeneratedValue
	private Long id;

	// 배송지 주소
	private String city;
	private String street;
	private String zipcode;
	private DeliberyStatus status;

	@OneToOne(mappedBy = "delivery")
	private Order order;
}

- DeliveryStatus.java

public enum DeliberyStatus {
}

 

2. Category - Item : 다대다 양방향 매핑

Category 클래스의 경우,위의 Entity 매핑 테이블에 나와있듯이 클래스 내부에 자기자신과의 연관관계를 따로 만들어 주어야 한다.(parent : Category)

- Category.java

@Entity
public class Category {
	@Id @GeneratedValue
	private Long id;

	private String name;

	@ManyToOne
	@JoinColumn(name = "PARENT_ID")
	private Category parent;

	@OneToMany(mappedBy = "parent")
	private List<Category> child = new ArrayList<>();
	// Category 클래스 내부에서 다대일 연관관계 매핑을 따로 만들어줬다.

	@ManyToMany
	@JoinTable(name = "CATEGORY_ITEM", joinColumns = @JoinColumn(name = "CATEGORY_ID")
	, inverseJoinColumns = @JoinColumn(name = "ITEM_ID")) // 중간 테이블 매핑, 다대다 연관관계의 주인으로서 매핑된다.
	private List<Item> items = new ArrayList<>();
}

 

위의 소스 코드를 보면 joinColumns, inverseJoinColumns 속성을 통해  CATEGORY_ITEM 연결 테이블에 매핑할 양측 도메인 클래스의(Category.java, Item.java) 외래 키를 지정해주고 있다.

 

- Item.java

@ManyToMany(mappedBy = "items") // 연관관계의 주인 클래스가 아니므로 mappedBy 속성을 활용한다.
private List<Category> categories = new ArrayList<>();

 

 

위와 같이 코드를 작성한 후 실행시키면 아래와 같은 hibernate SQL 을 출력하는 것을 볼 수 있다.

Hibernate: 
    
    create table Delivery (
       id bigint not null,
        city varchar(255),
        status integer,
        street varchar(255),
        zipcode varchar(255),
        primary key (id)
    )
Hibernate: 
    
    create table Category (
       id bigint not null,
        name varchar(255),
        PARENT_ID bigint,
        primary key (id)
    )
Hibernate: 
    
    create table CATEGORY_ITEM (
       CATEGORY_ID bigint not null,
        ITEM_ID bigint not null
    ) // 연결(중간) 테이블 생성
Hibernate: 
    
    create table ORDERS (
       ORDER_ID bigint not null,
        orderDate timestamp,
        status varchar(255),
        DELIVERY_ID bigint, // delivery 외래 키 값 생성
        MEMBER_ID bigint,
        primary key (ORDER_ID)
    )

 

 

 

* 다대일 연관관계에 있어서 @ManyToOne, @OneToMany 어노테이션의 차이점?

- @OneToMany 어노테이션은 mappedBy 속성을 사용할 수 있는데 반해, @ManyToOne 어노테이션은 사용할 수 없다.

왜? : 다대일 연관관계를 사용할 경우 ManyToOne 어노테이션을 선언한 도메인 클래스가 반드시 연관관계의 주인이 되어야 하기 때문이다.