[JPA] 5. 상품 도메인 개발

2025. 5. 14. 09:40·BE/스프링부트와 JPA 활용
728x90

1. 상품 엔티티 개발(비즈니스 로직 추가)

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

    @OneToMany(mappedBy = "item")
    private Collection<OrderItem> orderItem;

    // 비즈니스 로직

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

    public void removeStock(int quantity){
        int resultStock = this.stockQuantity - quantity;
        if(resultStock < 0){
            throw new NotEnoughStockException("need more stock");
        }
        this.stockQuantity = resultStock;
    }
}

왜 Entity 안에 비즈니스 로직을 넣어야 할까?

Item 엔티티 안에 addStock(), removeStock() 같은 메서드를 함께 넣어야한다.

보통은 엔티티에는 데이터만 정의하고 서비스에서 비즈니스 로직을 처리하는 경우가 많다 ex) setAddStock()
"왜 서비스가 아니라 엔티티 안에 이런 로직을 넣는 걸까?"

도메인 모델 패턴이란?

JPA에서는 보통 두 가지 설계 방식을 선택할 수 있습니다.

🧱 트랜잭션 스크립트 패턴 모든 비즈니스 로직을 서비스 계층에서 처리. 엔티티는 단순히 데이터만 들고 있음
🧠 도메인 모델 패턴 (권장) 비즈니스 로직을 엔티티 내부에 넣고, 객체가 스스로 상태를 관리함

→ JPA + 객체지향을 제대로 활용하려면 도메인 모델 패턴이 정석이다.

왜 엔티티 안에 로직을 넣을까?

1. 데이터와 행동은 함께 있어야 한다 (응집도 향상)

객체지향의 기본 원칙: “자신의 데이터를 스스로 처리하게 하라.”

item.removeStock(2); // 객체 스스로 상태를 변경

→ stockQuantity를 외부에서 막 바꾸는 게 아니라, Item이 "재고 감소"라는 행위를 책임지는 것

2. 불변성과 유효성 보장이 쉬움

public void removeStock(int quantity) {
    int resultStock = this.stockQuantity - quantity;
    if (resultStock < 0) {
        throw new NotEnoughStockException("need more stock");
    }
    this.stockQuantity = resultStock;
}

→ 잘못된 값(0 이하)일 때 예외를 던져 비즈니스 규칙을 강제할 수 있다.

3. 유지보수성이 좋아진다

엔티티는 단순한 데이터 덩어리가 아니라, "책임 있는 객체"로 행동하게 만들어야 한다.
비즈니스 규칙이 있는 기능은 서비스가 아니라, 도메인(Entity) 안에 넣는 것이 객체지향적이며 유지보수에도 유리하다.

2. 상품 리포지토리 개발

@Repository
@RequiredArgsConstructor
public class ItemRepository {

    private final EntityManager em;

    public void save(Item item){
        // item은 JPA에 저장하기 전까지 id가 없다.
        // id가 없다 == 새로 생성한 객체
        if(item.getId() == null){
            em.persist(item);
        } else{
            //이미 DB에 등록된 것을 가져온 것
            em.merge(item); // 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();
    }
}
  • save()
    • id 가 없으면 신규로 보고 persist() 실행
    • id 가 있으면 이미 데이터베이스에 저장된 엔티티를 수정한다고 보고, merge() 를 실행, 자세한 내용은 뒤에 웹에서 설명(그냥 지금은 저장한다 정도로 생각하자)

3. 상품 서비스 개발

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

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

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

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

ItemService는 비즈니스 로직을 처리하는 계층이고, 그 안에서 데이터베이스 관련 작업은 ItemRepository에 위임해서 처리

728x90

'BE > 스프링부트와 JPA 활용' 카테고리의 다른 글

[JPA] 6. 주문 도메인 개발 - 리포지토리/서비스/테스트  (0) 2025.05.17
[JPA] 6. 주문 도메인 개발 - 주문, 주문상품 엔티티 개발  (1) 2025.05.14
[JPA] 4. 회원 도메인 개발  (0) 2025.05.13
[JPA] 3. 애플리케이션 구현 준비  (0) 2025.05.12
[JPA] 2. 도메인 분석 설계 - 엔티티 설계시 주의점  (0) 2025.05.11
'BE/스프링부트와 JPA 활용' 카테고리의 다른 글
  • [JPA] 6. 주문 도메인 개발 - 리포지토리/서비스/테스트
  • [JPA] 6. 주문 도메인 개발 - 주문, 주문상품 엔티티 개발
  • [JPA] 4. 회원 도메인 개발
  • [JPA] 3. 애플리케이션 구현 준비
DROPDEW
DROPDEW
💻 Developer | 기록하지 않으면 존재하지 않는다
  • DROPDEW
    제 2장 1막
    DROPDEW
  • 전체
    오늘
    어제
    • Dev (417)
      • App·Android (1)
      • BE (44)
        • HTTP 웹 기본 지식 (8)
        • 스프링 입문 - 코드로 배우는 스프링 부트, 웹 .. (12)
        • 스프링부트와 JPA 활용 (11)
        • 스프링부트 시큐리티 & JWT (0)
        • PHP (6)
      • FE·Client (23)
        • HTML (1)
        • React (19)
        • Unity (1)
      • Data (17)
        • AI (7)
        • Bigdata (6)
        • Database (1)
        • 빅데이터분석기사 (2)
      • Infra (0)
      • Activity (0)
        • Education (0)
        • Intern (0)
        • 리모트 인턴십 6기 (0)
        • 구름톤 유니브 4기 (0)
        • SW교육기부단 15기 (0)
      • CS (8)
      • 취준 (13)
        • 자격증 (4)
        • 인적성·NCS (6)
        • 코테·필기·면접 후기 (3)
      • 코테 (270)
        • Algorithm (222)
        • SQL (35)
        • 정리 (13)
      • 인사이트 (27)
        • 회고 (0)
        • 금융경제뉴스 (7)
        • 금융용어·지식 (2)
        • 북마크 (7)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    문자열
    백준
    그래프이론
    그래프탐색
    최단경로
    누적합
    수학
    너비우선탐색
    시뮬레이션
    다이나믹프로그래밍
    이분탐색
    그리디알고리즘
    정렬
    구현
    자료구조
    티스토리챌린지
    투포인터
    오블완
    매개변수탐색
    브루트포스 알고리즘
  • 최근 댓글

  • 최근 글

  • 250x250
  • hELLO· Designed By정상우.v4.10.3
DROPDEW
[JPA] 5. 상품 도메인 개발
상단으로

티스토리툴바