[JPA] 엔티티 클래스 개발 1,2

이준영·2022년 10월 7일
0

스프링 - JPA

목록 보기
5/11

설계한 도메인을 보고 엔티티 클래스 개발하기

우선, 코드 작성하다 보면 매핑 시킨 애들마다 빨간줄 뜨는데 매핑이 완전히 안되면 뜨는거니까 일단 무시하고 코드 작성하면 된다.

시작..!

  1. Member 클래스 만들고 속성추가. id에 @Id, @GenerateValue, @Column( )…

  2. (1)Address 과 (2)Order 클래스 생성

    1. Address에서는 @Embeddable —> Member의 Address에서는 @Embedded // 둘중 한나만 해도 됨

    2. Order에서 id에 @Id, @GenerateValue, @Column( )…

      1. Member속성- Member개체와 주인 관계 따짐 —> Order에 있는 member가 주인 :
        @JoinColumn( )… 이거 달린애가 주인이라는 뜻 같음 / column이랑 비교해보자
        @ManyToOne 달았는데 여기서 달았으니까 Member에서는 @OneToMany 달아주고 mappedBy = “member” // mappedBy는 나는 주인아님 표시. “member”랑 연결시킨거는 Order의 member 속성이랑 매핑했다는 뜻인듯
      1. OrderItem 클래스 생성후 속성추가

        1. OrderItem 에서 @Id, @GenerateValue, @Column( )…

        2. Item 클래스 생성 후 속성추가

          1. 얘는 추상 클래스로 만들거래 : class 앞에 abstract 쓰면됨

          2. 얘는 상속관계 매핑을 해야돼 (기본편 참고), domain 에서 얘를 상속할 애들을 만듦(book, album, movie)

          1. 상속관계 매핑이기 때문에 상속관계 전략을 지정해야되는데 이 전략을
            부모 클래스에 잡아야해. 여기선 싱글테이블 전략임
            @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
            @DiscriminatorColumn(name = “dtype”) —> “book”이면 뭘할꺼야..

          4.Album, Book, Movie가서 기본세팅해주고
          @DiscriminatorValue 설정

        3. Order속성 - Order개체와 주인 관계 —> OrderItem에 있는 order가 주인:
          @JoinColumn( )… 이거 달린애가 주인이라는 뜻 같음 / column이랑 비교
          @ManyToOne 달았는데 여기(OrderItem)서 달았으니까
          Order가서는 @OneToMany 달아주고 mappedBy=“order” 나는 주인이 아니에요.
          “order”랑 매핑돼서 얘가 주인이에요 라는 뜻 같음

        4. Item 속성이 있는데 Item 개체와 주인관계 따짐.
          여기있는(OrderItem) item 속성이 주인이야.
          @JoinColumn 이랑 @ManyToOne 달아줘

    3. Delivery 클래스 생성 후 속성추가

      1. Delivery 클래스에서 각 속성추가(DeliveryStatus)
      1. DeliveryStatus는 enum으로 생성 후 속성추가 해주는데 Enum 생성시 주의할점이 있음
        Enum 타입은 @Enumerated를 넣어야 되는데 enum타입에는 ordinary랑 string이 있는데 default가 ordinary.
        ordinary는 숫자인데 밀리면 대참사(?) 라 무튼 string 타입으로 넣어줘—>
        @Enumerated(EnumType.STRING)
      1. Order랑은 1대1 관계. JPA 1대1 관계는 fk를 어디에 둬도 상관없는데 여기선 order 개체에 둘거임
        그럼 이제 연관관계의 주인은 fk랑 가까이있는 order에 있는 delivery로 주면 된다!!
        여기선(Delivery) @OneToOne(mappedBy = ‘delivery’) 붙여주고
        Order에 있는 delivery에 @OneToOne , @JoinColumn(name = “delivery_id”) 붙여주면 된다!

    4.LocalDateTime 속성 추가

    5.OrderStatus Enum으로 생성

  3. Category 클래스 생성 후 속성추가

    1. items 속성이랑 뭔 짓 했음

    2. 카테고리 구조 -> 계층구조 인데 어떻게 표현해야되지? 자기자신을 클래스 타입으로.. 코드참고


코드로 다시 확인하기

  • Member 도메인
@Entity
@Getter @Setter
public class Member {

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

    private String name;

    @Embedded
    private Address address;

    @OneToMany(mappedBy = "member")
    private List<Order> orders = new ArrayList<>();

}
  • Order 도메인
@Entity
@Table(name = "orders")
@Getter @Setter
public class Order {

    @Id @GeneratedValue
    @Column(name = "order_id")  // column을 테이블명의 아이디. DB들이 이 방식을 선호
    private Long id;

    // ___ToOne 인 애들은 기본 fetch가 EAGER
    // 그래서 LAZY로 바꿔줘야함
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "member_id")  //추가로 joinColumn. 매핑을 뭘로 할거냐..?
    // Member orders와 양방향 연관관계
    // 양방향 연관관계는 관계의 주인을 정해줘야헤. Order의 회원을 바꿀떄 여기의 값을 바꿀 수 있고 반대로 Member에서 orderList의 값을 바꿀수도있어
    // 양방향 참조인데 fk를 가지고 있는건 orders!!
    // 그래서 누가 주인이라고? fk가 가까운애?
    // Order에 있는 member를 주인으로 잡아야한다는데
    // 주인이라는게  Member 개체 vs Order개체에 있는 Member 를 비교하는거였어?
    private Member member;

    //___ToMany 인 애들은 기본 fetch가 LAZY
    // cascade: 뭘 한번에 해준대..
    @OneToMany(mappedBy = "order", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List<OrderItem> orderItems = new ArrayList<>();

    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "delivery_id")
    private Delivery delivery;

    private LocalDateTime orderDate; // 주문시간

    @Enumerated(EnumType.STRING)
    private OrderStatus status; // 주문상태

    //==연관관계 메서드=//
    public void setMember(Member member) {
        this.member = member;
        member.getOrders().add(this);
    }

    public void addOrderItem(OrderItem orderItem) {
        orderItems.add(orderItem);
        orderItem.setOrder(this);
    }

    public void setDelivery(Delivery delivery) {
        this.delivery = delivery;
        delivery.setOrder(this);
    }


}
  • Address 도메인
@Embeddable // 내장타입..?
@Getter
// 값 타입은 변경 불가능하게 설계해야 함
// 그래서 @Setter를 제거하고 생성자에서 값을 초기화해서 변경 불가능하게 만들자!
// JPA에서 @Entity나 @Embeddable은 기본 생성자를 public 또는 protected 로 설정해야 한다.
// public 으로 두는 것 보다는 protected 로 설정하는 것이 더 안전 하다.
public class Address {

    private String city;
    private String street;
    private String zipcode;

    protected Address() {

    }

    public Address(String city, String street, String zipcode) {
        this.city = city;
        this.street = street;
        this.zipcode = zipcode;
    }
}
  • OrderItem 도메인
@Entity
@Getter @Setter
public class OrderItem {

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

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "item_id")
    private Item item;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "order_id")
    private Order order;

    private int orderPrice;
    private int count;
}
  • Item 도메인 (abstract)
@Entity
//상속관계 매핑이기 때문에 상속관계 전략을 지정해야되는데 이 전략을 부모클래스에 잡아야해
//여기선 싱글 테이블 전략
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "dtype")  //ex. book이면 어떻게 할거야.. 뭔소리야
@Getter @Setter
public abstract class Item {

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

    private String name;
    private int price;
    private int stockQuantity;

    @ManyToMany(mappedBy = "items")
    private List<Category> categories = new ArrayList<>();

}
  • Album, Book, Movie 도메인(Item을 상속)
@Entity
@DiscriminatorValue("A")
@Getter @Setter
public class Album extends Item {

    private String artist;
    private String etc;
  • OrderStatus 도메인(Enum)
public enum OrderStatus {
    ORDER, CANCEL
}
  • Delivery 도메인
@Entity
@Getter @Setter
public class Delivery {

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

    //JPA 1대1 관게에서는 fk를 어디에 둬도 됨
    //여기선 fk를 order에 둘거임
    //그럼이제 연관관계 주인은 fk랑 가까이있는 order에 있는 delivery로 주면 됨
    @OneToOne(mappedBy = "delivery", fetch = FetchType.LAZY)
    private Order order;

    @Embedded
    private Address address;

    //Enum으로 만들건데 enum타입은 조심해야되는게있음
    // @Enumerated를 넣어야되는데 이넘 타입 넣을때 ordinary랑 string이 있는데 ordinary 가 default. 꼭 string으로 쓰세요
    @Enumerated(EnumType.STRING)
    private DeliveryStatus status; //READY, COMP
}
  • Category 도메인
@Entity
@Getter @Setter
public class Category {

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

    private String name;

    @ManyToMany
    @JoinTable(name = "category_item",
            joinColumns = @JoinColumn(name = "category_id"),
            inverseJoinColumns =  @JoinColumn(name = "item_id")) // 중간 테이블 매핑을 해줘야함.  JPA에서 다대다  -->  1대다-다대1.. 근데 쓰지말
    private List<Item> items = new ArrayList<>();


    // 카테고리 구조, 계층구조 어떻게하지?
    // 부모가 타입이니까 Category 로 넣어주고
    // 부모니까 ManyToOne이겠지? --> JoinColumn()..
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_id")
    private Category parent;
    // 자식은 여러개 가질 수 있잖여
    // mappedBy에 부모 넣어주면 됨
    @OneToMany(mappedBy = "parent")
    private List<Category> child = new ArrayList<>();


    //==연관관계 메서드==//
    public void addChildCategory(Category child) {
        this.child.add(child);
        child.setParent(this);

    }
}

후우.. 힘들어따...

profile
화이팅!

0개의 댓글