개인 프로젝트/블로그

블로그 카테고리 달기 (백엔드)

공주맛밤 2022. 7. 4. 14:35

방법 1: 자기 자신을 참조하여 무한 depth로 카테고리 만들기

방법 2: 그냥 간단하게 parentCatgory, subCategory 테이블 2개 만들어서 구현하기


선택: 방법 2, 블로그 카테고리는 대분류에서 소분류로 2계층인데 무한 depth안해도 될 것 같음, 무한 depth는 대댓글 구현할 때 해볼것(이것도 댓글의 대댓글 정도까지만 할 거지만 테이블이 3개 이상보다 자기 참조가 을 것 같음)


<대분류와 소분류 연관관계 설정>

public class LargeCategory {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "largeCategory_id")
    private Long id;

    private String largeCategoryName;

    @OneToMany(mappedBy = "largeCategory", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) //largeCategory가 연관관계의 주인이며 largeCategory가 지워지면 subCateory도 지워짐
    @JsonIgnoreProperties("largeCategory")
    @OrderBy("id asc") //먼저 만든게 앞에 옴
    private List<SubCategory> subCategories = new ArrayList<>();
public class SubCategory {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String subCategoryName;

    @ManyToOne
    @JoinColumn(name = "largeCategory_id") //largeCategory_id를 참조해서 연관관계를 맺음
    private LargeCategory largeCategory;

}

<생성된 테이블>

<대분류 서비스 및 컨트롤러 작동 확인>

@RequiredArgsConstructor
@RestController
public class CategoryApiController {

    private CategoryService categoryService;

    @Autowired
    public CategoryApiController(CategoryService categoryService) {
        this.categoryService = categoryService;
    }

    @PostMapping("/api/largeCategory/save") //대분류카테고리 저장
    public ResponseDto<?> largeCategorySave (@RequestBody LargeCategory largeCategory) {
        return new ResponseDto<> (HttpStatus.CREATED.value(), categoryService.largeCategorySave(largeCategory));
    }

    @DeleteMapping("/api/largeCategory/{id}/delete") //카테고리 삭제
    public ResponseDto<?> largeCategoryDelete (@PathVariable Long id) {
        return new ResponseDto<> (HttpStatus.OK.value(), categoryService.largeCategoryDelete(id));
    }

    @PutMapping("/api/largeCategory/{id}/update") //카테고리 이름 변경
    public ResponseDto<?> largeCategoryUpdate (@PathVariable Long id, @RequestBody LargeCategory largeCategory) {
        return new ResponseDto<> (HttpStatus.OK.value(), categoryService.largeCategoryUpdate(id, largeCategory));
    }
}
@RequiredArgsConstructor
@RestController
public class CategoryController {

    private CategoryService categoryService;

    @Autowired
    public CategoryController(CategoryService categoryService) {
        this.categoryService = categoryService;
    }

    @GetMapping("/category") //-> 사이드 바
    public ResponseDto<?> categoryPage () {
        return new ResponseDto<> (HttpStatus.OK.value(), categoryService.largeCategoryList());
    }
}

save
get
update
delete

<subCategory 서비스 및 컨트롤러 작동 확인>

실력부족으로 로직이 간결하지 못하고 좀 어지럽다... 이해를 위해 먼저 서비스 부터 보자면

@Data
@NoArgsConstructor
@AllArgsConstructor
public class SubCategorySaveRequestDto {
    private Long largeCategory_id;
    private String subCategoryName;
}
@Transactional
    public SubCategory subCategorySave (SubCategorySaveRequestDto subCategorySaveRequestDto) {
        LargeCategory largeCategory = largeCategoryRepository.findById(subCategorySaveRequestDto.getLargeCategory_id())
                .orElseThrow(()-> new IllegalArgumentException("없는 대분류 카테고리 입니다."));

        SubCategory subCategory = SubCategory.builder()
                .largeCategory(largeCategory)
                .subCategoryName(subCategorySaveRequestDto.getSubCategoryName())
                .build();

        return subCategoryRepository.save(subCategory);
    }

프론트로부터 데이터를 dto로 받아와서 먼저 largeCategory를 찾고 찾은 대분류 카테고리를 subCategory에 넣어준다. 그리고 나머지는 builder 패턴을 통해서 넣고 저장해준다.

@PostMapping("/api/subCategory/{largeCategory_id}/save") //소분류카테고리 저장
    public ResponseDto<?> subCategorySave (@RequestBody SubCategorySaveRequestDto subCategorySaveRequestDto) {
        return new ResponseDto<> (HttpStatus.CREATED.value(), categoryService.subCategorySave(subCategorySaveRequestDto));
    }

 이제 컨트롤에서 largeCategory_id를 주소로 받고 dto를 통해 서비스 로직을 이행해주면

과 같은 형태의 값을 리턴해 준다. 여기서 아니 subCategories의 largeCategory는 어디감? 이라고 생각했다면 subCategory 모델에서   @JsonIgnoreProperties("largeCategory")가 잘 작동했다고 생각하면 된다. 

또한 왜 id가 2지? 는 테스트해본다고 지웠다가 새로 생성해서 그렇다.앞서서 largeCategory를 생성해주고 진행해야한다.

Transactional //subCategory delete
    public String subCategoryDelete (Long id) {
        subCategoryRepository.deleteById(id);
        return "success delete";
    }

    @Transactional //서브 카테고리 이름 바꾸기
    public SubCategory subCategoryUpdate(Long id, SubCategory subCategory) {
        SubCategory subCategoryEntity = subCategoryRepository.findById(id)
                .orElseThrow(()->new IllegalArgumentException("이미 삭제된 카테고리 입니다."));
        subCategoryEntity.setSubCategoryName(subCategory.getSubCategoryName()); 
        return subCategoryEntity;
    }

<종속관계 확인>:  largeCategory를 지우면 subCategory도 지워질까?

먼저 라지 카테고리 지우기
db에서 지워진 모습

(largeCategory에서 subCategory 리스트를 불러올 거라서 따로 subCategory는 get서비스를 안 만들었음 그럼 서브는 왜 만들었냐? -> 프론트에서 subCategory를 선택하면 해당 sub 카테고리 게시글들을 가져 올 것임)

이상으로 카테고리 crud 백엔드 마침. -> front에 적용하러 ㄱ

728x90
반응형