ItemRepository, ItemService (+엔티티에서 비즈니스 로직 구현, myExcpetion)

KMS·2022년 4월 14일
0

SpringBoot + JPA

목록 보기
3/14

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;

    /**
     * == 비즈니스 로직 ==
     * 도메인 주도 설계 => 엔티티에서 구현 가능한 비즈니스 로직들은 엔티티에서 바로 구현(ex: 수량 증가/감소) => 객체 지향적
     * ex: quantity는 엔티티에 있으므로, quantity의 값만 변하는 비즈니스 로직은 엔티티에서 바로 구현하는 것이 객체 지향적 & 응집력 있음
     */
    public void increaseStock(int quantity) {
        this.quantity += quantity;
    }

    public void decreaseStock(int quantity) {
        int restStock = this.quantity - quantity;
        if (restStock < 0) {
            throw new NotEnoughStockException("Need More Stock"); //남은 갯수가 0보다 작을때, 직접 개발한 exception을 던지도록 설계
        }

        this.quantity = restStock;
    }
}

increaseStock(), decreaseStock() 같은 비즈니스 로직들을 ItemService대신 엔티티에서 바로 구현 했습니다. 이러한 이유는, 해당 비즈니스 로직들에서는 quantity의 값만 변경하기 때문에 엔티티에서 바로 구현하는 것이 객체 지향적이며 응집력이 있기 때문입니다.

NotEnoughStockException(자체 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);
    }

    protected NotEnoughStockException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

RunTimeException을 상속 받고 메서드들을 구현함으로써 자체적인 exception을 개발할 수 있습니다.

ItemRepository

@Repository
@RequiredArgsConstructor
public class ItemRepository {

    private final EntityManager em; //@RequiredArgsConstructor 덕분에 자동으로 관계 주입 해줌

    public void save(Item item) {
        if (item.getId() == null) {
            em.persist(item);
        } else {
            em.merge(item);
        }
    }

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

    public List<Item> findByName(String name) {
        return em.createQuery("select i from Item i where i.name = :itemName", Item.class)
                .setParameter("itemName", name)
                .getResultList();
    }

}

@RequiredArgsConstructor 로 생성자를 별도로 생성하지 않아도 자동으로 생성 & final 키워드가 붙어 있는 변수들(private final EntityManager em)에 대해서 생성자 관계 주입을 해줍니다.

ItemService

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ItemService {

    private final ItemRepository itemRepository;

    @Transactional  //DEFAULT = false
    public void saveItem(Item item) {
        itemRepository.save(item);
    }

    public Item findOne(Long itemId) {
        return itemRepository.findOne(itemId);
    }

    public List<Item> findItems() {
        return itemRepository.findAll();
    }

    public List<Item> findItemsByName(String name) {
        return itemRepository.findByName(name);
    }
}
profile
Student at Sejong University Department of Software

0개의 댓글