- 객체 지향적인 설계를 위해 entity 안에서 해결할 수 있는 로직은 entity 안에 넣어주는 게 좋음
- 데이터를 가지고 있는 쪽에 비즈니스 메서드가 있는게 좋음
- (기존에 하던 식으로, setter 이용하지 않기)
-> 아이템 엔티티의 재고 수량 늘리고 줄이는 로직을 아이템 엔티티 안에 작성
package jpabook.jpashop.domain.item;
import jakarta.persistence.*;
import jpabook.jpashop.domain.Category;
import jpabook.jpashop.domain.OrderItem;
import jpabook.jpashop.domain.exception.NotEnoughStockException;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
@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<>();
// == 비즈니스 로직 추가 ==
// * 객체 지향적인 설계를 위해 entity 안에서 해결할 수 있는 로직은 entity 안에 넣어주는 게 좋음
// * 데이터를 가지고 있는 쪽에 비즈니스 메서드가 있는게 좋음
// 재고 수량 증가 로직
public void addStock(int quantity) {
this.stockQuantity += quantity;
}
public void removeStock(int quantity) {
int restStock = this.stockQuantity - quantity;
if (restStock < 0) {
throw new NotEnoughStockException("need more stock");
}
this.stockQuantity = restStock;
}
}
package jpabook.jpashop.repository;
import jakarta.persistence.EntityManager;
import jpabook.jpashop.domain.item.Item;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
@RequiredArgsConstructor
public class ItemRepository {
private final EntityManager em;
public void save(Item item) {
// item 은 저장할 때, 처음에 id 가 없음
// 따라서 id 가 없다는 건, 완전히 새로 저장함을 의미
if(item.getId() == null) {
// 이 아이템을 신규로 등록
em.persist(item);
} else {
// item 이 있다는 건, 이미 db 에 등록된 걸 db 에서 가져온 거
// 따라서 여기에서의 save 는 update 와 유사
// (merge 는 update 와 유사함)
em.merge(item);
}
}
// 단 건 조회를 할 땐 find 이용 가능
public Item findOne(Long id) {
return em.find(Item.class, id);
}
// 여러 개 찾을 땐, jpql 이용
public List<Item> findAll() {
return em.createQuery("select i from Item i", Item.class)
.getResultList();
}
}
package jpabook.jpashop.service;
import jpabook.jpashop.domain.item.Item;
import jpabook.jpashop.repository.ItemRepository;
import lombok.RequiredArgsConstructor;
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 디폴트가 현재는 (readOnly = true) 로 설정해뒀으므로,
// save 에서는 (readonly = false) 가 되도록, 이렇게 따로 적어줘야함 (여기서 적어준 게 우선권을 가짐)
@Transactional
public void saveItem(Item item) {
itemRepository.save(item);
}
public List<Item> findItems() {
return itemRepository.findAll();
}
public Item findItem(Long itemId) {
return itemRepository.findOne(itemId);
}
// 현재 이 ItemRepository 는 위임만 하는 역할 수행
// 경우에 따라서는, 이렇게 위임만 하는 경우 굳이 꼭 만들어야하나 고민해보자
// 이런 경우엔, controller 에서 repository 에 바로 접근해서 써도 된다고 생각
}
| 7. 웹 계층 개발 (0) | 2024.03.10 |
|---|---|
| 4. 회원 도메인 개발 (0) | 2024.03.04 |
| 2. 도메인 분석 설계 (0) | 2024.03.03 |
| 1. 환경 설정 (0) | 2024.03.03 |