BE전문가 프로젝트

1.1 도메인 설계 - Products(Products.class) 본문

JPA

1.1 도메인 설계 - Products(Products.class)

원호보고서 2022. 5. 12. 13:18
package com.bnc.main.product.domain;

import com.bnc.main.support.BaseEntity;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.apache.logging.log4j.util.Strings;

import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;

import static com.google.common.base.Preconditions.checkArgument;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Product extends BaseEntity {

    private String name;

    private int price;

    private String brand;
    
    @Enumerated(EnumType.STRING)
    private ProductStatus productStatus = ProductStatus.CREATED;

    public Product(String name, int price, String brand) {
        checkArgument(Strings.isNotBlank(name));
        checkArgument(Strings.isNotBlank(brand));

        this.name = name;
        this.price = price;
        this.brand = brand;
    }

    public void change(String name, int price, String brand) {
        checkArgument(Strings.isNotBlank(name));
        checkArgument(Strings.isNotBlank(brand));

        this.name = name;
        this.price = price;
        this.brand = brand;
    }

    public void delete() {
        this.productStatus = ProductStatus.DELETED;
    }
}

도메인 설계

Setter를 사용하지 않는다.

- setter로 값을 집어 넣게 된다면 언제 값이 들어갔는지 추적하기 어렵기 때문에 setter가 아닌 생성자로 넣는다.

 

change()

- JPA Repository는 update를 지원하지 않는다. 하지만 JAVA에서 값을 바꿔준다면 자동으로 바꿔주기 때문에 chage라는 메소드를 만들어 update를 한다.

 

delete()

- JPA에서는 Delete라는 클래스가 기본적으로 제공되는데 이는 hard Delete에 해당하며 row자체를 지워버린다.

따라서 상태값을 Delete로 바꿔주는 method를 만들어 soft Delete를 해주도록 한다.

Annotation
@Entity JPA 생성시 기본적으로 붙여줘야하는 Annotaion
project 실행시 테이블이 자동으로 세팅된다
- Table명 = 클래스 이름(테이블 명을 다르게 하고 싶다면 @Table(name = "테이블명"))
- column = 변수 이름(컬럼 명을 다르게 하고 싶다면 @Column(name = "column명"))
@Enumerate(EnumType) Enum사용시 @Enumerate없이 사용하면 배열형식으로 들어가기 때문에 타입이 int 값으로 들어간다. 따라서 Enum사용시에 사용해야 될 Annotaion
package com.bnc.main.support;

import lombok.EqualsAndHashCode;
import lombok.Getter;

import javax.persistence.*;

@Getter
@EqualsAndHashCode
@MappedSuperclass
public class BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
}

 

Annotation
@Id PK값에 해당한다
@GeneratedValue
(strategy = GenerationType.IDENTITY)
AutoIncrement와 같은 의미이다

 

TEST

- 도메인 설계가 완료되었다면 test를 하여 도메인에 대한 신뢰도를 높이도록 한다.

 

package com.bnc.main.product.domain;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.NullAndEmptySource;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;

class ProductTest {

    final static Product product = new Product("옷", 123, "구찌");

    @Test
    void 상품_생성_성공() {
        assertThat(product.getName()).isEqualTo("옷");
        assertThat(product.getPrice()).isEqualTo(123);
        assertThat(product.getBrand()).isEqualTo("구찌");
        assertThat(product.getProductStatus()).isEqualTo(ProductStatus.CREATED);
    }

    @ParameterizedTest
    @NullAndEmptySource
    void 상품_이름이_null이면_실패(String name){
        assertThatIllegalArgumentException().isThrownBy(() -> new Product(name, 123, "구찌"));
    }

    @Test
    void 상품_이름이_공백이면_실패(){
        String name = "    ";

        assertThatIllegalArgumentException().isThrownBy(() -> new Product(name, 123, "구찌"));
    }

    @ParameterizedTest
    @NullAndEmptySource
    void 상품_브랜드가_null이면_실패(String brand){
        assertThatIllegalArgumentException().isThrownBy(() -> new Product("옷", 123, brand));
    }

    @Test
    void 상품_브랜드가_공백이면_실패(){
        String brand = "    ";

        assertThatIllegalArgumentException().isThrownBy(() -> new Product("옷", 123, brand));
    }

    @Test
    void 상품_변경_성공(){
        final Product product = new Product("옷", 123, "구찌");

        product.change("가방", 1233, "디올");

        assertThat(product.getName()).isEqualTo("가방");
        assertThat(product.getPrice()).isEqualTo(1233);
        assertThat(product.getBrand()).isEqualTo("디올");
    }

    @Test
    void 상품_삭제_성공() {
        final Product product = new Product("옷", 123, "구찌");

        product.delete();

        assertThat(product.getProductStatus()).isEqualTo(ProductStatus.DELETED);
    }
}
Comments