> For the complete documentation index, see [llms.txt](https://heunnajo.gitbook.io/mvc/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://heunnajo.gitbook.io/mvc/7.-mvc/undefined-2.md).

# 상품 도메인 개발

상품 도메인과 상품 Repository를 구현해본다.

상품 도메인 모델과 요구사항 명세에 따라 구현한다!

![](https://4059345879-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdtAbfiAnzkPUNovpHX%2F-MeAqnBIAc7G3zsJvGT-%2F-MeAqtzGW8gtjN4rr44s%2Fimage.png?alt=media\&token=ec967079-af09-4dc2-b47c-6c967679034d)

1. 상품 도메인 모델 구현(domain패키지>item패키지>Item 클래스 생성)\
   int가 아닌 Integer로 설정한 이유 : 값이 안 들어가는 경우도 있기 때문에 null값도 받기 위해서다.\
   단순히 데이터를 주고받는 경우는 사용할 수도 있지만, 다음과 같은 이유로 @Data 애노테이션을 사용할  주의해야한다!  (@Getter, @Setter 정도만 사용하는 것을 추천)
   * @ToString의 경우 객체의 양방향 연관관계(a->b,b->a)가 있을 때 무한 루프로 호출될 수 있다.
   * Equals, hashCode도 모든 필드를 다 기준으로 잡는다.

```java
package hello.itemservice.domain.item;

import lombok.Data;
import lombok.Getter;
import lombok.Setter;

@Data
public class Item {
    private Long id;
    private String itemName;
    private Integer price;//price가 안들어갈 때도 있다고 가정하기 때문에 null도 받기 위해서
    private Integer quantity;

    public Item(){

    }

    public Item(String itemName, Integer price, Integer quantity) {
        this.itemName = itemName;
        this.price = price;
        this.quantity = quantity;
    }
}
```

2\. 아이템 Repository 구현(domain패키지>item패키지>ItemRepository 클래스 생성)

![](https://4059345879-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdtAbfiAnzkPUNovpHX%2F-MeAqnBIAc7G3zsJvGT-%2F-MeAqzixinxhk2NBEDis%2Fimage.png?alt=media\&token=683c421b-298d-48c8-a30f-bb94ec5baf90)

**멀티스레드** 사용하는 실무 환경에서 **여러 스레드가 동시에 접근 가능한 동시성 문제와** 스프링 컨테이너에서는 객체가 **싱글톤**으로 생성되기 때문에 HashMap사용하면 안되고 ConcurrentHashMap 사용해야한다. long 변수도 atomiclong 을 사용해야한다!

**상품 전체 조회 findAll()** : 아이템 객체들 날 것 그대로 반환해도 되지만 값을 변경해도 ArrayList에 값을 넣고 원래 객체 데이터는 보존하기 위해 ArrayList로 한번 감싼다!

**상품 수정 update()** : id가 사용되지 않기 때문에 updateParam라는 별도의 객체를 생성하는 것이 맞다! 개발자는 혼란스러워서 id필드가 있는데 왜 업데이트가 안되는지 의문을 가지며 setId로 값을 갱신해버릴 수도 있기 때문이다!

```java
package hello.itemservice.domain.item;

import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Repository
public class ItemRepository {
    private static final Map<Long,Item> store = new HashMap<>();//static
    private static long sequence = 0L;//static

    //상품 등
    public Item save(Item item){
        item.setId(++sequence);//@Data가 제공하는 자동 setter 기능으로 눈에 보이지는 않지만 Setter 존재!
        store.put(item.getId(),item);
        return item;
    }
    //상품 조회(id)
    public Item findById(Long id){
        return store.get(id);
    }
    //상품 조회(전체)
    public List<Item> findAll(){
        return new ArrayList<>(store.values());//아이템 객체들 반환
    }
    //상품 수정
    public void update(Long itemId,Item updateParam){
        Item findItem = findById(itemId);
        findItem.setItemName(updateParam.getItemName());
        findItem.setPrice(updateParam.getPrice());
        findItem.setQuantity(updateParam.getQuantity());
    }
    //전체 상품 삭제
    public void clearStore(){
        store.clear();
    }
}

```

3\. ItemRepository 테스트 코드 작성\
save() : 상품 생성, ItemRepository에 등록하고 ItemRepository에서 id로 찾은 객체와 같은지 비교.\
update() : 상품1 생성(**itemId**), ItemRepository에 등록. 상품2 생성, 상품2로 상품 수정(**itemId**,item2)\
**상품1의 id**인 **itemId**로 **ItemRepository 조회**했을 때 **상품2의 각 속성 값들과 같은지 비교.**\
**(쉽게 말해서 상품1을 상품2로 업데이트했기 때문에 상품1의 id로 상품2의 속성값들로 업데이트되있어야함)**\
findAll() : 상품1, 상품2 생성해서 ItemRepository에 등록, itemReository.findAll() 결과를 리스트에 저장.\
리스트의 크기가 상품 갯수와 같은지 비교, 객체 상품1과 상품2를 포함하는지 비교(assertThat(List).contains(item1,item2))
