시험기간 때문에 너무 오랜만에 들어왔다.. 쫌 까먹은것 같은데... 잘 기억하고 있는지 모르겠지만 일단 다시 시작해보자!!
이번시간에서의 두가지 키워드는 기능
과 순서
다
등록
조회
수정
domain
repository
service
Test
구현 순서는 어떤 기능 구현에서도 적용되니 꼭 기억하기❗️❗️
구현해야할 각 기능마다 개발 순서를 따라가며 하나씩 코드 작성해보자
@Entity
//상속관계 매핑이기 때문에 상속관계 전략을 지정해야되는데 이 전략을 부모클래스에 잡아야해
//여기선 싱글 테이블 전략
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "dtype") //ex. book이면 어떻게 할거야.. 뭔소린지 더 알아보자..
@Getter @Setter
public abstract class Item {
@Id // PRIMARY KEY 표시 annotation
@GeneratedValue // 자동생성 설정 annotation
@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 quantity를 가져와서 거기서 지지고 볶고 삶고 마지막에 setQuantity 같은 방식으로 코딩을 했읉텐데
// BUT, 객체 지향적으로 생각해보면 데이터를 가지고 있는 쪽에 비즈니스 메서드가 있는게 가장 좋음. 응집력 있음
// quantity를 변경할일 있으면 setter를 쓰는게 아니라 이렇게 핵심 비즈니스 로직으로 변경하도록!!
/**
* stock(재고) 증가
*/
public void addStock(int quantity) {
this.stockQuantity += quantity;
}
/**
* stock(재고) 감소
*/
public void removeStock(int quantity) {
int restStock = this.stockQuantity - quantity;
if (restStock < 0) {
throw new NotEnoughStockException("need more stock");
}
this.stockQuantity = restStock;
}
}
자세한 설명은 코드에 주석을 달아놨다.
이해가 잘 안되는건 @DiscriminatorColumn(name = "dtype")
이 annotation인데
구글링해서 쫌 더 찾아보자.
비즈니스 로직 : addStock(), removeStock() 은 나중에 다시 돌아와서 하는데 그냥 한번에 하자.
@Repository
@RequiredArgsConstructor // final 변수만 생성자 만들어주는 친구
public class ItemRepository {
private final EntityManager em;
public void save(Item item) {
if (item.getId() == null) { // item 값이 없다 --> 새거다
em.persist(item);
} else { // item 값이 있다 --> 있던거다
em.merge(item); // merge : 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();
}
}
persist
, merge
, find
, createQeury
를 지원해준다em.persist(item)
/ em.merge(item)
를 기억하자@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class ItemService {
public final ItemRepository itemRepository;
// 위에 있는 @Transactional은 전체에 적용 : readOnly니까
// 가까이 있는 annotation이 우선권을 가짐 : write 해주기 위해 다시 annotation 붙임
@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);
}
}
ItemService는 ItemRepository에 있는 기능을 이름만 바꿔서 쓰고있다.
-saveItem(item)
-findItems()
-findOne(itemID)
이게 꼭 필요한가..?
엔티티, 리포지토리, 서비스를 모두 구현 했으면 이제 테스트 하고 마무리~~
하면 되는데 회원 테스트랑 비슷하다고 생략했다...
.
.
.
아싸 강의들을거 줄었다ㅎㅋ