아래 순서대로 카테고리 추가해볼 예정이다
카테고리 추가
- /entity/Category.java 클래스 추가
- /repository/CategoryRepository.java 인터페이스 추가
- /service/CategoryService.java 추가
- /entity/Board.java category 속성 추가
- /service/BoardService.java 조회 조건에 카테고리 추가 수정
- 카테고리를 자유게시판, 질문응답게시판 분리
- /templates/layout.html. 사이드바 태그 추가 기입
- /controller/BoardController.java GetMapping 메서드에 카테고리를 추가
/entity/Category.java 클래스 추가
package com.eunji.backboard.entity;
import java.time.LocalDateTime;
import org.springframework.data.annotation.CreatedDate;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Entity
public class Category {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Integer id;
@Column(length = 30)
private String title;
@CreatedDate
@Column(name = "createDate", updatable = false) // updatable = false : 작성날짜 바꾸지 않겠다는 의미
private LocalDateTime createDate;
}
- DBeaver에 Category 테이블 생성된 것 확인할 수 있음
/repository/CategoryRepository.java 인터페이스 추가
package com.eunji.backboard.repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.eunji.backboard.entity.Category;
@Repository
public interface CategoryRepository extends JpaRepository<Category, Integer> {
Optional<Category> findByTitle(String title); // select * from Category where title = title;
}
/service/CategoryService.java 추가
package com.eunji.backboard.service;
import java.time.LocalDateTime;
import java.util.Optional;
import org.springframework.stereotype.Service;
import com.eunji.backboard.common.NotFoundException;
import com.eunji.backboard.entity.Category;
import com.eunji.backboard.repository.CategoryRepository;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Service
public class CategoryService {
private final CategoryRepository categoryRepository;
// 카테고리를 생성하는 메서드
public Category setCategory(String title) {
Category cate = new Category();
cate.setTitle(title);
cate.setCreateDate(LocalDateTime.now());
Category category = this.categoryRepository.save(cate);
return category;
}
// free, qna..
// 생성한 카테고리를 가져오기 위한 메서드
public Category getCategory(String title) {
Optional<Category> cate = this.categoryRepository.findByTitle(title);
if(cate.isEmpty()) { // free나 qna라는 이름의 카테고리 데이터가 없으면
cate = Optional.ofNullable(setCategory(title)); // db Category 테이블에 해당 카테고리 값을 생성(insert)
}
if(cate.isPresent()) { // 카테고리가 있으면
return cate.get();
} else
throw new NotFoundException("Category NOT FOUND!!"); // 발생할 일이 없음
}
}
/entity/Board.java category 속성 추가
@ManyToOne
private Category category; // free, qna로 구분해서 글 작성 가능
- Board테이블과 Category id와 연결된 것을 확인할 수 있음
/service/BoardService.java 조회 조건에 카테고리 추가 수정
1. getList() 메서드 추가
public Page<Board> getList(int page, String keyword, Category category) {
List<Sort.Order> sorts = new ArrayList<>();
sorts.add(Sort.Order.desc("createDate"));
Pageable pageable = PageRequest.of(page, 10, Sort.by(sorts)); // pageSize를 동적으로도 변경할 수 있음. 나중에...
Specification<Board> spec = searchBoard(keyword, category.getId());
return this.boardRepository.findAll(spec, pageable); // Specification 인터페이스로 쿼리 생성로직 만들어서
// return this.boardRepository.findAllByKeyword(keyword, pageable);
}
2. searchBoard() 메서드 추가
public Specification<Board> searchBoard(String keyword, Integer cateId) {
return new Specification<Board>() {
private static final long serialVersionUID = 1L; // 필요한 값이라서 추가
@Override
@Nullable
public Predicate toPredicate(Root<Board> b, CriteriaQuery<?> query, CriteriaBuilder cb) {
// query를 JPA로 생성
query.distinct(true); // 중복 제거
Join<Board, Reply> r = b.join("replyList", JoinType.LEFT);
return cb.and(cb.equal(b.get("category").get("id"), cateId),
cb.or(cb.like(b.get("title"), "%" + keyword + "%"), // 게시글 제목에서 검색
cb.like(b.get("content"), "%" + keyword + "%"), // 게시글 내용에서 검색
cb.like(r.get("content"), "%" + keyword + "%") // 댓글 내용에서 검색
));
}
};
}
3. setBoard() 추가
public void setBoard(String title, String content, Member writer, Category category){
// 빌더로 생성한 객체
Board board = Board.builder().title(title).content(content)
.createDate(LocalDateTime.now()).build();
board.setCategory(category); // 카테고리 추가
board.setWriter(writer);
// 객체 저장
this.boardRepository.save(board); // PK가 없으면 INSERT
}
/templates/layout.html. 사이드바 태그 추가 기입
<!-- 레이아웃에 적용될 하위 페이지 위치 -->
<div class="container mt-3" style="height: auto !important;">
<div class="row">
<div class="col-sm-12 col-md-3 col-lg-2">
<!-- 게시판 카테고리 영역 -->
<nav class="border-top dorser-secondary">
<div class="list-group">
<a th:classappend="${category} == 'free' ? 'active'" th:href="@{/board/list/free}"
class="category-group rounded-0 list-group-item list-group-item-action list-group-item-light p-2">자유게시판</a>
<a th:classappend="${category} == 'free' ? 'active'" th:href="@{/board/list/qna}"
class="category-group rounded-0 list-group-item list-group-item-action list-group-item-light p-2">질의응답</a>
</div>
</nav>
</div>
<div class="col-sm-12 col-md-9 col-lg-10">
<!-- 기존 게시판 영역 -->
<th:block layout:fragment="main-content">
</th:block>
</div>
</div>
</div>
/controller/BoardController.java GetMapping 메서드에 카테고리 매개변수 추가
private final CategoryService categoryService; // 카테고리 사용
@GetMapping("/list")
public String list(Model model, @RequestParam(value="page", defaultValue = "0") int page,
@RequestParam(value = "kw", defaultValue = "") String keyword) {
Page<Board> paging = this.boardService.getList(page, keyword); // 검색 추가
model.addAttribute("paging", paging);
model.addAttribute("kw", keyword);
return "board/list";
}
// 24.06.25. 마지막 카테고리까지 추가
@GetMapping("/list/{category}")
public String list(Model model,
@PathVariable(value="category") String category,
@RequestParam(value="page", defaultValue = "0") int page,
@RequestParam(value = "kw", defaultValue = "") String keyword) {
Category cate = this.categoryService.getCategory(category);
Page<Board> paging = this.boardService.getList(page, keyword, cate); // 검색 및 카테고리 추가
model.addAttribute("paging", paging);
model.addAttribute("kw", keyword);
model.addAttribute("category", category);
return "board/list";
}
- CategoryService를 사용하기 위해 필드 추가
- list() 메서드에서 좀전에 boardService에 새롭게 추가한 getList()사용
/templates/board/list.html 카테고리 변수 추가
- 수정 전
<a th:href="@{/board/create}" class="btn btn-sm btn-primary my-2">게시글 등록</a>
<form th:action="@{/board/list}" method="get" id="searchForm">
- 수정 후
<a th:href="@{|/board/create/${category}|}" class="btn btn-sm btn-primary my-2">게시글 등록</a>
<form th:action="@{|/board/list/${category}|}" method="get" id="searchForm">
/controller/BoardController.java create() GET, POST 메서드에 category 추가!
1. create() GET 메서드
@PreAuthorize("isAuthenticated()") // 로그인 시만 작성 가능
@GetMapping("/create/{category}")
public String create(Model model,
@PathVariable("category") String category,
BoardForm boardForm){
model.addAttribute("category", category);
return "board/create";
}
2. create() POST 메서드
@PreAuthorize("isAuthenticated()") // 로그인 시만 작성 가능
@PostMapping("/create/{category}")
public String create(Model model,
@PathVariable("category") String category,
@Valid BoardForm boardForm,
BindingResult bindingResult,
Principal principal) {
if(bindingResult.hasErrors()) {
model.addAttribute("category", category);
return "board/create"; // 현재 html에 그대로 머무르기
}
Member writer = this.memberService.getMember(principal.getName()); // 현재 로그인 사용자 아이디
// this.boardService.setBoard(title, content);
Category cate = this.categoryService.getCategory(category);
this.boardService.setBoard(boardForm.getTitle(), boardForm.getContent(), writer, cate);
return String.format("redirect:/board/list/%s", category);
}
- 질의응답 게시판 카테고리에서 생성한 게시글이 뜨는 것을 확인!
'Spring Boot > STUDY' 카테고리의 다른 글
[Spring Boot] JPA 프로젝트 - AWS로 서버 연결 (1) | 2024.06.26 |
---|---|
[Spring Boot] JPA 프로젝트 - 조회수 기능 구현 (0) | 2024.06.26 |
[Spring Boot] JPA 프로젝트 - 마크다운 적용 (1) | 2024.06.25 |
[Spring Boot] JPA 프로젝트 - @Query를 사용한 검색 기능 구현(2) (0) | 2024.06.25 |
[Spring Boot] JPA 프로젝트 - Specification 인터페이스를 사용한 검색 기능 구현(1) (0) | 2024.06.24 |