본문 바로가기
Dev/JPA

[JPA] JPA 활용 I - 상품 도메인 개발

by dev_jsk 2021. 9. 17.
728x90
반응형

상품 기능인 상품 등록, 조회, 수정 기능을 개발해보자

상품 엔티티 내 비즈니스 로직 추가

파일 경로

main/java/jpabook/jpashop/domain/item/Item.java

소스 구현

package jpabook.jpashop.domain.item;

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)  // 싱글 테이블 전략 설정
@DiscriminatorColumn(name = "dtype")  // 구분컬럼명 지정
@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<>();

    // 비즈니스 로직 추가

    /**
     * stock 증가
     * @param quantity
     */
    public void addStock(int quantity) {
        this.stockQuantity += quantity;
    }

    /**
     * stock 감소
     * @param quantity
     */
    public void removeStock(int quantity) {
        int restStock = this.stockQuantity - quantity;
        // 잔여수량이 0보다 작으면 예외발생
        if(restStock < 0) {
            throw new NotEnoughStockException("need more stock");
        }
        this.stockQuantity = restStock;
    }
}
  • 엔티티 내 비즈니스 로직 추가
  • 도메인 주도 설계 시 도메인 내에서 해결 가능한 것은 Setter를 이용하여 값을 변경하여 처리하는 것 보다 도메인 안에 비즈니스 로직을 구성하여 사용하는 것이 객체지향적이고 응집력이 있고 관리하기 좋다.
  • addStock() : 파라미터로 넘어온 수량만큼 재고를 증가시킨다.
  • removeStock() : 파라미터로 넘어온 수량만큼 재고를 감소시킨다. 변경된 재고가 0보다 작을경우 예외를 발생시킨다.

예외 클래스 구현

main/java/jpabook/jpashop/exception/NotEnoughStockException.java

package jpabook.jpashop.exception;

public class NotEnoughStockException extends RuntimeException {
    
    public NotEnoughStockException() {
        super();
    }

    public NotEnoughStockException(String message) {
        super(message);
    }

    public NotEnoughStockException(String message, Throwable cause) {
        super(message, cause);
    }

    public NotEnoughStockException(Throwable cause) {
        super(cause);
    }
}
  • RuntimeException을 상속받아 메소드 오버라이딩을 통해 메시지와 오류를 출력할 수 있다.

상품 레포지토리 개발

파일 경로

main/java/jpabook/jpashop/repository/ItemRepository.java

소스 구현

package jpabook.jpashop.repository;

@Repository
@RequiredArgsConstructor
public class ItemRepository {
    
    private final EntityManager em;

    /**
     * save Item
     * @param item
     */
    public void save(Item item) {
        // id값이 null 이면 신규등록, 아니면 update
        // id값은 영속성 컨텍스트에 올라가 있지 않으면 null이다.
        if(item.getId() == null) {
            em.persist(item);
        } else {
            em.merge(item);
        }
    }

    /**
     * find one Item
     * @param id
     * @return Item
     */
    public Item findOne(Long id) {
        return em.find(Item.class, id);
    }

    /**
     * find all Item
     * @return List<Item>
     */
    public List<Item> findAll() {
        return em.createQuery("select i from Item i", Item.class)
                .getResultList();
    }
}
  • save()
    - id가 없으면 신규 등록으로 EntityManager.persist() 실행
    - id가 있으면 기존 엔티티 수정으로 EntityManager.merge() 실행

상품 서비스 개발

파일 경로

main/java/jpabook/jpashop/service/ItemService.java

소스 구현

package jpabook.jpashop.service;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class ItemService {
    
    private final ItemRepository itemRepository;

    /**
     * save Item
     * @param item
     */
    @Transactional
    public void saveItem(Item item) {
        itemRepository.save(item);
    }

    /**
     * find one Item
     * @param itemId
     * @return Item
     */
    public Item findOne(Long itemId) {
        return itemRepository.findOne(itemId);
    }

    /**
     * find all Item
     * @return List<Item>
     */
    public List<Item> findItems() {
        return itemRepository.findAll();
    }
}
  • Service 클래스는 Repository 에 위임하는 클래스
  • Service 단이 꼭 필요한지 판단 후 필요하지 않다고 생각되면 Controller 에서 바로 Repository 로 연결해도 무방하다.
728x90
반응형

댓글