-
#Spring boot-9 상품 도메인 개발SPRING-BOOT 2021. 3. 4. 14:19
[출처] 인프런 김영한 강사님 -실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
상품 도메인 개발
구현 기능
· 상품 등록
· 상품 목록 조회
· 상품 수정
순서
· 상품 엔티티 개발(비즈니스 로직 추가)
· 상품 리포지토리 개발
· 상품 서비스 개발 상품
· 기능 테스트
상품 엔티티 개발(비즈니스 로직 추가)
상품 엔티티 코드
item class
package jpabook.jpashop.domain.item; import jpabook.jpashop.domain.Category; import jpabook.jpashop.exception.NotEnoughStockException; import lombok.Getter; import lombok.Setter; import javax.persistence.*; import java.util.ArrayList; import java.util.List; /* * * 1. 추상클래스는 뭐? 실체클래스의 공통적인 부분(변수,메서드)를 추출해서 선언한 클래스 2. 추상클래스는 객체를 생성할 수 없다! 아직은 실체성이 없고 구체적이지 않기 때문에! 3. 추상클래스와 실체클래스는 어떤관계? 상속관계! * */ @Entity @Getter @Setter @Inheritance(strategy = InheritanceType.SINGLE_TABLE) //한테이블에 다때려박는것 @DiscriminatorColumn(name ="dtype") public abstract class Item { @Id @GeneratedValue @Column(name ="item_id") private Long id; private String name; private int price; private int stockQuantity; //변경할 일이 있으면 setter로 변경하는 것이 아니라 아래와같이 핵심 비지니스 로직으로 변경해야 한다. // ->이게 가장 객체지향적인 것이다. @ManyToMany(mappedBy = "items") private List<Category> categories = new ArrayList<>(); //===비지니스 로즥===// //재고를 줄이고 늘리는 로직 // 엔티티 자체가 해결할 수 있는 것은 주로 엔티티 안에 비지니스 로직을 넣는게 좋다 -> 이게 객체지향적 //즉 데이터를 가지고 있는 쪽에 핵심 비지니스 로직이 있는 것이 좋다. /* * stock 증가 * */ public void addStock(int quantity){ this.stockQuantity += quantity; } /* * stock 감소 * */ public void remvoeStoc(int quantity){ int restStock = this.stockQuantity - quantity; if(restStock < 0){ throw new NotEnoughStockException("need more stock"); } this.stockQuantity = restStock; } }
stockQuantity를 변경할 일이 있으면 setter로 변경하는 것이 아니라 핵심 비지니스 로직을 따로 만들어서 변경해야 한다.
->이게 가장 객체지향적인 것이다.
참고 : 엔티티 자체가 해결할 수 있는 것은 주로 엔티티 안에 비지니스 로직을 넣는게 좋다 -> 이게 객체지향적
즉 데이터를 가지고 있는 쪽에 핵심 비지니스 로직이 있는 것이 좋다.예외추가
NotEnoughStockException class
package jpabook.jpashop.exception; public class NotEnoughStockException extends RuntimeException{ //여기서 overide를 했는데 왜해야 하냐면 메세지 같은것을 다넘겨 주고 // 메세지와 예외가 발생한 근원적 이셉션을 넣어 처리가 되게 하기 위해서 public NotEnoughStockException() { super(); } public NotEnoughStockException(String message) { super(message); } public NotEnoughStockException(String message, Throwable cause) { super(message, cause); } public NotEnoughStockException(Throwable cause) { super(cause); } }
여기서 overide를 했는데 왜해야 하냐면 메세지 같은것을 다넘겨 주고
메세지와 예외가 발생한 근원적 이셉션을 넣어 처리가 되게 하기 위해서 이다.비즈니스 로직 분석
· addStock() 메서드는 파라미터로 넘어온 수만큼 재고를 늘린다. 이 메서드는 재고가 증가하거나
상품 주문을 취소해서 재고를 다시 늘려야 할 때 사용한다.
· removeStock() 메서드는 파라미터로 넘어온 수만큼 재고를 줄인다. 만약 재고가 부족하면 예외가 발생한다.
주로 상품을 주문할 때 사용한다.
상품 리포지토리 개발
상품 리포지토리 코드
ItemRepository class
package jpabook.jpashop.Repository; import jpabook.jpashop.domain.item.Item; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; import javax.persistence.EntityManager; import java.util.List; @Repository @RequiredArgsConstructor public class ItemRepository { private final EntityManager em; public void save(Item item){ if(item.getId() == null){ //아이탬은 처음에 아이디가 없다(데이터 저장하는 시점까지는). em.persist(item); }else{ em.merge(item); //UPDATE 비슷한 것. } } public Item findOne(Long id){ return em.find(Item.class, id); } public List<Item> findAll(){ return em.createQuery("select i From Item i",Item.class) .getResultList(); } }
기능 설명
· save()
· id 가 없으면 신규로 보고 persist() 실행
· id 가 있으면 이미 데이터베이스에 저장된 엔티티를 수정한다고 보고, merge() 를 실행,
자세한 내용 은 뒤에 웹에서 설명(그냥 지금은 저장한다 정도로 생각하자)
상품 서비스 개발
상품 서비즈 코드
ItemService class
package jpabook.jpashop.service; import jpabook.jpashop.Repository.ItemRepository; import jpabook.jpashop.domain.item.Item; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Service @Transactional(readOnly = true) @RequiredArgsConstructor public class ItemService { private final ItemRepository itemRepository; @Transactional public void saveItem(Item item){ itemRepository.save(item); } public List<Item> findItems(){ return itemRepository.findAll(); } public Item findOne(Long itemId){ return itemRepository.findOne(itemId); } }
상품 서비스는 상품 리포지토리에 단순히 위임만 하는 클래스
상품 기능 테스트
상품 테스트는 회원 테스트와 비슷하므로 생략
ItemServiceTest class
package jpabook.jpashop.service; import jpabook.jpashop.Repository.ItemRepository; import jpabook.jpashop.domain.item.Book; import jpabook.jpashop.domain.item.Item; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.Transactional; import static org.junit.Assert.*; @RunWith(SpringRunner.class) @SpringBootTest @Transactional public class ItemServiceTest { @Autowired private ItemService itemService; @Autowired private ItemRepository itemRepository; @Test public void 상품등록() throws Exception{ //given Book book = new Book(); book.setName("박"); book.setAuthor("작가1"); //when itemService.saveItem(book); //then assertEquals(book,itemRepository.findOne(book.getId())); } }
'SPRING-BOOT' 카테고리의 다른 글
#Spring boot-11 웹 계층 개발 (0) 2021.03.04 #Spring boot-10 주문 도메인 개발 (0) 2021.03.04 #Spring boot-8_1 테스트 케이스 작성 중 에러 (0) 2021.03.04 #Spring boot-8 회원 기능 테스트 (0) 2021.03.04 #Spring boot-7_1 TEST CASE 작성 중 발생 에러 (0) 2021.03.04