[온라인 화훼 경매](02) 카테고리를 구현해봅시다.

카테고리 등록 부분을 리펙토링 하기 위해서 가만히 코드를 들여다 보았습니다.

테스트도 통과하였고 Postman으로 확인하고 데이터베이스에 들어가는 것까지 확인을 하였는데 뭔가 찜찜했습니다.

조금 더 JPA에 대해서 이해를 하고 연관관계를 이용해보고자 JPA의 연관 관계를 이용하여 리팩토링을 진행하였습니다. 또한 프로젝트에 요구사항에 맞게 카테고리 등록 기능을 수정하였습니다.

이번 글에서는 리팩토링한 내용을 다뤄보려 합니다.


변경사항

Entity

    @Column(nullable = false)
    private int level;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_id")
    private Category parent;

    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
    private List<Category> children = new ArrayList<>();

                ```

    public Category createCategory(String name) {
        Category child = Category.builder()
                .name(name)
                .level(this.level + 1)
                .active(true)
                .parent(this)
                .build();
        this.children.add(child);
        return child;
    }

Entity의 일부분입니다. 저번 글에서 보았던 CRUD 메소드를 빼고 자식 카테고리를 생성해주는 메소드 createCategory를 생성하였습니다. 또한 @OneToMany 부분의 내용도 수정하였습니다.

KeyPoint

cascade = CascadeType.ALL

cascade는 JPA에서 영속성 전이를 설정하고 관리할 수 있는 옵션입니다. 쉽게 말해 부모 엔티티를 다룰 경우, 자식 엔티티까지 다룰 수 있다는 뜻입니다.

그중 CascadeType.ALL은 PERSIST와 REMOVE의 기능을 모두 수행해 줍니다. 즉, 부모를 영속화 하였을 때 자식도 함께 영속화 되고, 부모를 삭제할 때 자식도 삭제 됩니다.

level

지난 글과 다르게 level colum이 추가 된것을 볼 수 있습니다. 이는 카테고리가 등록 될 때 식물을 자동으로 등록해주기 위해서 넣었습니다. 카테고리를 등록 할 떄 부모의 level + 1을 해줘 계층을 이룰 수 있게 만들었습니다.

예를 들면 절화-장미-빨강이라는 카테고리를 순차적으로 등록했을 때 빨강이 최하위 카테고리라는 것을 알 수 있는 방법이 없었습니다.

그래서 level을 추가하였고 level 3이 추가 될때 식물 entity가 save되도록 코드를 작성하였습니다.

Service

    public Long addCategory(AddCategoryDto dto) {
        Category findCategory = getCategoryEntity(dto.getParentId());
        Category category = findCategory.createCategory(dto.getName());

        if (isSubdivision(category.getLevel()))
            addPlant(category);

        return category.getId();
    }

    private Category getCategoryEntity(Long categoryId) {
        return categoryRepository.findById(categoryId)
                .orElseThrow(() -> new EntityNotFoundException("존재하지 않는 카테고리 ID=" + categoryId));
    }

    private boolean isSubdivision(int level) {
        return level == 3;
    }

하지만 위 코드에는 문제점이있습니다. 이전에는 idname을 받아와 id가 null이면 최상위 카테고리로 등록되었지만, 바뀐 코드는 id로 null로 받을 수 없었습니다.

그렇다면 굳이 왜 코드를 바꿨을까요!

바로 저희 프로젝트의 최상위 카테고리의 수는 총 4개 밖에 안되었습니다. 그래서 이와 같은 코드를 작성하였고, 이번 프로젝트를 하면서 코딩에는 정답이 없다는 것을 느꼈습니다.

요약

이번 글에서는 부모-자식 관계를 직접 설정해주는 코드에서 JPA의 연관관계를 이용한 코드로 리팩토링을 하고 프로젝트에 맞게 더욱 간단하고 가독성 좋은 코드로 리팩토링 하는 과정을 다뤘습니다. 다음 글에서는 카테고리 조회에 대해서 다뤄보겠습니다!