Skip to content

[4기 박현지] Mission3: Order 도메인 구현, 연관 관계 매핑 및 테스트 #295

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 23 commits into
base: hyeon-z
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f50b119
feat: Member 엔티티 구현
hyeon-z Jul 28, 2023
e08b71f
feat: Order 엔티티 구현
hyeon-z Jul 28, 2023
f0c2ca2
feat: createdAt, updatedAt을 다루는 BaseEntity 구현
hyeon-z Jul 28, 2023
0461eec
feat: JpaRepository를 상속하는 Member, Order Repository 생성
hyeon-z Jul 28, 2023
a259ecb
test: 멤버, 주문 생성 테스트
hyeon-z Jul 28, 2023
131130e
test: @Transactional제거 및 Lazy Loading 오류 해결
hyeon-z Jul 28, 2023
bec71c7
feat: OrderItem 엔티티 구현
hyeon-z Jul 28, 2023
8355fc1
feat: OrderItem과의 연관관계 설정
hyeon-z Jul 28, 2023
78016cb
feat: JpaRepository를 상속하는 OrderItemRepository 생성
hyeon-z Jul 28, 2023
c855d4e
feat: 주문 상태를 저장한 OrderStatus enum 구현
hyeon-z Jul 28, 2023
9edcad3
test: 주문, 주문 아이템 생성 테스트
hyeon-z Jul 28, 2023
b015a6e
feat: Item 엔티티 구현
hyeon-z Jul 28, 2023
2b8d492
feat: Item과의 연관관계 설정
hyeon-z Jul 28, 2023
ababb8b
feat: feat: JpaRepository를 상속하는 ItemRepository 생성
hyeon-z Jul 28, 2023
5531a03
test: 아이템, 주문 아이템 생성 테스트
hyeon-z Jul 28, 2023
1d2bbd8
test: 파라미터 잘못 대입한 경우 수정
hyeon-z Jul 28, 2023
7059ca7
test: 사용하지 않는 테스트 파일 제거
hyeon-z Jul 29, 2023
93945c8
refactor: Entity 클래스 id의 strategy를 IDENTITY로 설정
hyeon-z Jul 29, 2023
54cb8bd
refactor: @Repository 어노테이션 제거
hyeon-z Jul 29, 2023
6556d76
feat: @OneToMany의 orphanRemoval을 true로 지정
hyeon-z Jul 29, 2023
4f4ba1b
refactor: add메서드에서 양방향 관계 설정 및 생성자 파라미터 수정
hyeon-z Jul 29, 2023
02e4c36
test: Order 도메인 테스트
hyeon-z Jul 29, 2023
4d5a4ab
refactor: member를 order 도메인으로 폴더 이동
hyeon-z Jul 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.prgms.springbootjpa.mission3.domain;

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

@MappedSuperclass
public class BaseEntity {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

abstract로 설정하여 entity로서 기능을 못하게 막는것은 어떨까요?


private LocalDateTime createdAt = LocalDateTime.now();

private LocalDateTime updatedAt = LocalDateTime.now();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now로 설정하신것은 entity가 생성될 때 초기화 해주기 위함인것인가요?
생성자에서는 그럼 updatedAt과 createdAt는 제외시켜주나요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵! Order가 생성될 때 현재 시각으로 초기화되어서 저장됩니다!

}
47 changes: 47 additions & 0 deletions src/main/java/org/prgms/springbootjpa/mission3/domain/Member.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.prgms.springbootjpa.mission3.domain;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.prgms.springbootjpa.mission3.domain.BaseEntity;
import org.prgms.springbootjpa.mission3.domain.order.Order;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Member extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(length = 12, nullable = false)
private String name;

@Column(length = 12, nullable = false, unique = true)
private String nickname;

private int age;

@Column(length = 50, nullable = false)
private String address;

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

public Member(String name, String nickname, int age, String address) {
this.name = name;
this.nickname = nickname;
this.age = age;
this.address = address;
}

public void addOrder(Order order) {
order.setMember(this);
orders.add(order);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.prgms.springbootjpa.mission3.domain;

import org.springframework.data.jpa.repository.JpaRepository;

public interface MemberRepository extends JpaRepository<Member, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.prgms.springbootjpa.mission3.domain.order;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Item {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private int price;

private int stockQuantity;

@OneToMany(mappedBy = "item", orphanRemoval = true)
private List<OrderItem> orderItems = new ArrayList<>();

public Item(int price, int stockQuantity) {
this.price = price;
this.stockQuantity = stockQuantity;
}

public void addOrderItem(OrderItem orderItem) {
orderItem.setItem(this);
orderItems.add(orderItem);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.prgms.springbootjpa.mission3.domain.order;

import org.springframework.data.jpa.repository.JpaRepository;

public interface ItemRepository extends JpaRepository<Item, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.prgms.springbootjpa.mission3.domain.order;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.prgms.springbootjpa.mission3.domain.BaseEntity;
import org.prgms.springbootjpa.mission3.domain.Member;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@Table(name = "orders")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Order extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private OrderStatus orderStatus;

private String memo;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;

@OneToMany(mappedBy = "order", cascade = CascadeType.PERSIST, orphanRemoval = true)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

persist만 특정지어 cascade를 하는 이유가 있을까요?

private List<OrderItem> orderItems = new ArrayList<>();

public Order(OrderStatus orderStatus, String memo) {
this.orderStatus = orderStatus;
this.memo = memo;
}

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

public void setMember(Member member) {
this.member = member;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.prgms.springbootjpa.mission3.domain.order;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class OrderItem {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private int price;

private int quantity;

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

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

public OrderItem(int price, int quantity) {
this.price = price;
this.quantity = quantity;
}

public void setOrder(Order order) {
this.order = order;
}

public void setItem(Item item) {
this.item = item;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.prgms.springbootjpa.mission3.domain.order;

import org.springframework.data.jpa.repository.JpaRepository;

public interface OrderItemRepository extends JpaRepository<OrderItem, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.prgms.springbootjpa.mission3.domain.order;

import org.springframework.data.jpa.repository.JpaRepository;

public interface OrderRepository extends JpaRepository<Order, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.prgms.springbootjpa.mission3.domain.order;

public enum OrderStatus {
CREATED, PROCESSING, SHIPPED, DELIVERED
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package org.prgms.springbootjpa.mission3.domain;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.prgms.springbootjpa.mission3.domain.order.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.prgms.springbootjpa.mission3.domain.order.OrderStatus.CREATED;

@SpringBootTest
class OrderDomainTest {

@Autowired
OrderRepository orderRepository;

@Autowired
OrderItemRepository orderItemRepository;

@Autowired
MemberRepository memberRepository;

@Autowired
ItemRepository itemRepository;

Member member = new Member("현지", "딩딩", 25, "서울시 마포구");
Order order = new Order(CREATED, "집 앞 배송");
Item item = new Item(1000, 100);
OrderItem orderItem = new OrderItem(10000, 2);

@BeforeEach
void setUp() {
itemRepository.deleteAll();
orderRepository.deleteAll();
orderItemRepository.deleteAll();
memberRepository.deleteAll();
}

@Test
void 멤버_생성() {
Member saveMember = memberRepository.save(member);

List<Member> members = memberRepository.findAll();

assertThat(members.size(), is(1));
assertThat(saveMember.getId(), notNullValue());
}

@Test
void 아이템_생성() {
Item saveItem = itemRepository.save(item);

List<Item> items = itemRepository.findAll();

assertThat(items.size(), is(1));
assertThat(saveItem.getId(), notNullValue());
}

@Test
void 아이템_주문아이템_생성() {
itemRepository.save(item);

item.addOrderItem(orderItem);

orderItemRepository.save(orderItem);

List<OrderItem> orderItems = item.getOrderItems();

assertThat(item.getId(), notNullValue());
assertThat(orderItems.size(), is(1));
assertThat(orderItems.get(0), samePropertyValuesAs(orderItem));

assertThat(orderItem.getId(), notNullValue());
assertThat(orderItem.getItem(), samePropertyValuesAs(item));
}

@Test
void 주문_주문아이템_생성() {
order.addOrderItem(orderItem);
orderRepository.save(order);

List<OrderItem> orderItems = order.getOrderItems();

assertThat(order.getId(), notNullValue());
assertThat(orderItems.size(), is(1));
assertThat(orderItems.get(0), samePropertyValuesAs(orderItem));

assertThat(orderItem.getId(), notNullValue());
assertThat(orderItem.getOrder(), samePropertyValuesAs(order));
}

@Test
void 멤버_주문_생성() {
memberRepository.save(member);

member.addOrder(order);

orderRepository.save(order);

List<Order> orders = member.getOrders();

assertThat(member.getId(), notNullValue());
assertThat(orders.size(), is(1));
assertThat(orders.get(0), samePropertyValuesAs(order));

assertThat(order.getId(), notNullValue());
assertThat(order.getMember(), samePropertyValuesAs(member));
}

@Test
void 주문_도메인_테스트() {
memberRepository.save(member);
itemRepository.save(item);

item.addOrderItem(orderItem);
order.addOrderItem(orderItem);
member.addOrder(order);

orderRepository.save(order);

assertThat(member.getId(), notNullValue());
assertThat(member.getOrders().size(), is(1));
assertThat(member.getOrders().get(0), samePropertyValuesAs(order));

assertThat(order.getId(), notNullValue());
assertThat(order.getMember(), samePropertyValuesAs(member));
assertThat(order.getOrderItems().size(), is(1));
assertThat(order.getOrderItems().get(0), samePropertyValuesAs(orderItem));

assertThat(item.getId(), notNullValue());
assertThat(item.getOrderItems().size(), is(1));
assertThat(item.getOrderItems().get(0), samePropertyValuesAs(orderItem));

assertThat(orderItem.getId(), notNullValue());
assertThat(orderItem.getItem(), samePropertyValuesAs(item));
assertThat(orderItem.getOrder(), samePropertyValuesAs(order));
}
}