엔티티 설계 & 개발

KMS·2022년 4월 13일
0

SpringBoot + JPA

목록 보기
1/14

SpringBoot와 JPA를 사용해서 간단하 웹 애플리케이션을 개발할 예정입니다. JPA 관련한 내용들은 JPA Basics 시리즈에 포스팅된 글들을 참고하시고, Spring 및 SpringBoot에 관한 내용들은 제가 해당 내용들을 학습하면서 깃허브에 커밋한 내용들을 확인하시면 됩니다.(https://github.com/k-ms1998/Spring-studies)

Member

@Entity
@Getter
@Setter
public class Member {

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

    private String username;

    @Embedded
    private Address address;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "member")
    private List<Order> orders = new ArrayList<>();

Order

@Entity
@Table(name = "orders")
@Getter
@Setter
public class Order {

    @Id
    @GeneratedValue
    @Column(name = "order_id")
    private Long id; //PK

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "member_id")
    private Member member; //FK => 그러므로, Member와 Order의 연관 관계에서 Order를 주인으로 설정

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "order", cascade = CascadeType.ALL)
    private List<OrderItem> orderItems = new ArrayList<>();

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "order", cascade = CascadeType.ALL)
    private Delivery delivery;

    private LocalDateTime orderDate;

    @Enumerated(EnumType.STRING)
    private OrderStatus status; //주문상태: [ORDER, CANCEL]

    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);
    }
}

Delivery

@Entity
@Getter
@Setter
public class Delivery {

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

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "order_id")
    private Order order; //FK => Order가 없으면 Delivery도 없기 때문에 Delivery에 FK를 두기로 결정

    @Embedded
    private Address address;

    @Enumerated(EnumType.STRING)
    private DeliveryStatus status; //READY, COMPLETE

}

Address(엔티티 X)

@Embeddable
@Getter
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

@Entity
@Getter
@Setter
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public abstract class Item {

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

    private String name; //제품 이름
    private int price; //제품 가격
    private int quantity; //제품 수량

    @ManyToMany(fetch = FetchType.LAZY, mappedBy = "items") //실무에서는 다대다 관계 사용 X, but, 현재는 공부하는 중이기 때문에 다대다 관계로 설정 후 학습
    private List<Category> categories;

}

Album

@Entity
@Getter
@Setter
public class Album extends Item {

    private String artist;
    private String etc;

}

Book

@Entity
@Getter
@Setter
public class Book extends Item{
    private String author;
    private String isbn;
}

Movie

@Entity
@Getter
@Setter
public class Movie extends Item{
    private String director;
    private String actor;
}

Category

@Entity
@Getter
@Setter
public class Category {
    @Id
    @GeneratedValue
    @Column(name = "category_id")
    private Long id;

    private String name;

    @ManyToMany(fetch = FetchType.LAZY) //실무에서는 다대다 관계 사용 X, but, 현재는 공부하는 중이기 때문에 다대다 관계로 설정 후 학습
    @JoinTable(name = "category_item",
        joinColumns = @JoinColumn(name = "category_id"),
            inverseJoinColumns = @JoinColumn(name = "item_id")
    ) //다대다 관계일때, 일반적으로 중간 테일(category_item)을 사용해서 일대다 & 다대일 관계를 성릅해서 다대다 관계 구현
    private List<Item> items = new ArrayList<>();

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_id")
    private Category parent;

    @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
    private List<Category> child = new ArrayList<>();

    public void addChildCategory(Category child) {
        this.child.add(child);
        child.setParent(this);
    }
}

엔티티 설계시 주의사항:
1. 엔티티에서 Setter는 가급적이면 사용하지 않습니다. 유지보수가 어려워지며, 엔티티의 속성 값들을 마음대로 바꿀수 있게 되기 때문에 피하는 것이 좋습니다. 하지만, 학습하는 과정에서는 그런 사항들을 고려하지 않아도 되기 때문에 일단은 Setter를 자유롭게 사용하도록 하겠습니다.
2. 다대다(@ManyToMany)를 실무에서는 사용하지 않는 것이 좋습니다. 중간 테이블을 사용해서 다대다 관계를 일대다, 다대일 관계로 변형 시켜서 적용하게 되는데, 중간 테이블에 연관된 테이블들의 외래키만 갖고 있는 것이 실무 상황에서는 어렵기 때문입니다. 하지만, 학습하는 과정에서는 다대다 관계도 공부 하기 위해 예제에서 억지로 Item과 Category를 다대다 관계로 설계했습니다.
3. 모든 연관관계는 지연 로딩(fetch = FetchType.LAZY)로 설정합니다. 이에 대한 내용은 JPA 지연 로딩 포스팅을 한것이 참고 하시면 됩니다.(https://velog.io/@k_ms1998/JPA-%EC%A7%80%EC%97%B0-%EB%A1%9C%EB%94%A9fetchFetchType.LAZY)
4. 컬렉션은 필드에서 초기화 합니다. (ex: private List orders = new ArrayList<>();)

profile
Student at Sejong University Department of Software

0개의 댓글