자바 ORM 표준 JPA 프로그래밍(5)

YulHee Kim·2021년 10월 23일
0
post-thumbnail

[참고 강의] 김영한님의 자바 ORM 표준 JPA 프로그래밍

[ 엔티티 매핑 ]

💡 실전 예제

✔️ 요구사항, 도메인 모델 분석

  • 회원은 상품을 주문할 수 있다.
  • 주문 시 여러 종류의 상품을 선택할 수 있다.

도메인 모델 분석

  • 회원과 주문의 관계: 회원은 여러 번 주문할 수 있다.(일대다)
  • 주문과 상품의 관계: 주문할 때 여러 상품을 선택할 수 있다. 반대로 같은 상품도 여러 번 주문될 수 있다. 주문상품이라는 모델을 만들어서 다대다 관계를 일대다, 다대일 관계로 풀어냄

✔️ 엔티티 설계와 매핑

Member.java

package jpashop.domain;

import javax.persistence.*;

@Entity
public class Member {

    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;
    private String name;
    private String city;
    private String street;
    private String zipcode;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public String getZipcode() {
        return zipcode;
    }

    public void setZipcode(String zipcode) {
        this.zipcode = zipcode;
    }
}

Order.java

package jpashop.domain;

import javax.persistence.*;
import java.time.LocalDateTime;

@Entity
@Table(name = "ORDERS")
public class Order {

    @Id @GeneratedValue
    @Column(name = "ORDER_ID")
    private Long id;

    @Column(name = "MEMBER_ID")
    private Long memberId;
    private LocalDateTime orderDate;

    @Enumerated(EnumType.STRING)
   private OrderStatus status;


}

OrderItem.java

Order와 Item의 다대다 관계를 일대다, 다대일 관계로 풀어내는 주문상품 모델

package jpashop.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class OrderItem {

    @Id @GeneratedValue
    @Column(name = "ORDER_ITEM_ID")
    private Long id;

    @Column(name = "ORDER_ID")
    private Long orderId;

    @Column(name = "ITEM_ID")
    private Long itemId;

    private int orderPrice;
    private int count;
    
    ...
}

✔️ 데이터 중심 설계의 문제점

  • 현재 방식은 객체 설계를 테이블 설계에 맞춘 방식
  • 테이블의 외래키를 객체에 그대로 가져옴
  • 객체 그래프 탐색이 불가능
  • 참조가 없으므로 UML도 잘못됨

[ 연관관계 매핑 기초 ]

💡 단방향 연관관계

예제 시나리오

  • 회원과 팀이 있다.
  • 회원은 하나의 팀에만 소속될 수 있다.
  • 회원과 팀은 다대일 관계다.

✔️ 객체를 테이블에 맞추어 모델링

(연관관계가 없는 객체)

  • 참조 대신 외래 키를 그대로 사용
@Entity
public class Member {

	@Id @GeneratedValue
	private Long id;
    
	@Column(name = "USERNAME")
    	private String name;
    
    	@Column(name = "TEAM_ID")
	private Long teamId;
    ...

}

@}Entity
public class Team {

	@Id @GeneratedValue
	private Long id;
	private String name;
   
    ...
}
  • 외래 키 식별자를 직접 다룸
//팀 저장
Team team = new Team();

team.setName("TeamA");

em.persist(team);//회원 저장
Member member = new Member();

member.setName("member1");

member.setTeamId(team.getId());

em.persist(member);
  • 식별자로 다시 조회, 객체 지향적인 방법은 아님
//조회Member findMember = em.find(Member.class, member.getId());

//연관관계가 없음Team findTeam = em.find(Team.class, team.getId());

객체를 테이블에 맞추어 데이터 중심으로 모델링하면, 협력 관계를 만들 수 없다.

  • 테이블은 외래 키로 조인을 사용해서 연관된 테이블을 찾는다.
  • 객체는 참조를 사용해서 연관된 객체를 찾는다.
  • 테이블과 객체 사이에는 이런 큰 간격이 있다.

✔️ 객체 지향 모델링

(객체 연관관계 사용)

  • 객체의 참조와 테이블의 외래 키를 매핑
@Entity
public class Member {

	@Id @GeneratedValue
	private Long id;
    
	@Column(name = "USERNAME")
    	private String name;
    
    	// @Column(name = "TEAM_ID")
	// private Long teamId;
    
    	@ManyToOne
    	@JoinColumn(name = "TEAM_ID")
    	private Team team;
 
    ...

}
  • ORM 매핑

  • 연관관계 저장

//팀 저장
Team team = new Team();
team.setName("TeamA");
em.persist(team);

//회원 저장
Member member = new Member()
member.setName("member1");
member.setTeam(team); //단방향 연관관계 설정, 참조 저장
em.persist(member);
  • 참조로 연관관계 조회 - 객체 그래프 탐색
//조회Member findMember = em.find(Member.class, member.getId());

//참조를 사용해서 연관관계 조회Team findTeam = findMember.getTeam();
  • 연관관계 수정
// 새로운 팀B
Team teamB = new Team();
teamB.setName("TeamB");
em.persist(teamB);

// 회원1에 새로운 팀B 설정
member.setTeam(teamB);
profile
백엔드 개발자

0개의 댓글