블로그 카테고리 달기 (백엔드)
방법 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());
}
}
<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도 지워질까?
(largeCategory에서 subCategory 리스트를 불러올 거라서 따로 subCategory는 get서비스를 안 만들었음 그럼 서브는 왜 만들었냐? -> 프론트에서 subCategory를 선택하면 해당 sub 카테고리 게시글들을 가져 올 것임)
이상으로 카테고리 crud 백엔드 마침. -> front에 적용하러 ㄱ