점프 투 스프링부트를 보고 게시판을 따라 만드는 프로젝트이다.
3-15의 추가기능을 모두 구현하는 것을 목표로 한다.
초보자라서 코드컨벤션이나 클린코드보다는 기능 구현을 목적으로 작성하였습니다.
💡 생성해야 할 부분 : Comment 도메인. 컨트롤러, 서비스, 엔티티, 리포지토리, 검증을 하기 위한 댓글 폼
@Entity
@Getter
@Setter
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(columnDefinition = "TEXT")
private String content;
private LocalDateTime createTime;
@ManyToOne
private SiteUser author;
@ManyToOne
private Answer answer;
}
id, 내용, 생성일자, 작성자를 가짐, answer와 매핑되어야 하므로 해당 answer도 가짐.
@Controller
@RequestMapping("/comment")
@RequiredArgsConstructor
public class CommentController {
private final QuestionService questionService;
private final UserService userService;
private final AnswerService answerService;
private final CommentService commentService;
@PreAuthorize("isAuthenticated()")
@PostMapping("/create/{id}")
public String createAnswer(Model model, @PathVariable("id") Integer id, @Valid CommentForm commentForm, BindingResult bindingResult, Principal principal, RedirectAttributes re) {
SiteUser user = this.userService.getUser(principal.getName());
Answer answer = this.answerService.getAnswer(id);
Question question =answer.getQuestion();
if (bindingResult.hasErrors()) {
model.addAttribute("answer", answer);
return "question_detail";
}
int page = question.getAnswerList().size() / 10;
re.addAttribute("answerPage", page);
Comment comment = this.commentService.create(answer,commentForm.getContent(),user);
model.addAttribute("comment",comment);
return String.format("redirect:/question/detail/%s#answer_%s", answer.getQuestion().getId(), answer.getId());
}
}
작성자, 답변, 질문까지 각각의 도메인 서비스에 요청해서 받아옴.
댓글 달려도 질문 상세 페이지에 다시 연결되야 해서 질문까지 가져왔음.
@Service
@RequiredArgsConstructor
public class CommentService {
private final CommentRepository commentRepository;
public Comment create(Answer answer, String content, SiteUser author) {
Comment comment = new Comment();
comment.setContent(content);
comment.setAuthor(author);
comment.setCreateTime(LocalDateTime.now());
comment.setAnswer(answer);
this.commentRepository.save(comment);
return comment;
}
}
객체 생성해서 필드에 값넣고 저장요청.
스프링-데이터-JPA에게 모든걸 맡기고 구현 안함.
<!-- 댓글작성, 댓글 표시-->
<div class="mt-5 ">
<form th:action="@{|/comment/create/${answer.id}|}" th:object="${commentForm}" method="post"
class="my-3">
<div th:replace="~{form_errors :: formErrorsFragment}"></div>
<textarea sec:authorize="isAnonymous()" disabled th:field="*{content}" placeholder="로그인을 먼저 해주세요"
class="form-control" rows="1"></textarea>
<textarea sec:authorize="isAuthenticated()" placeholder="댓글을 등록해주세요" th:field="*{content}"
class="form-control"
rows="1"></textarea>
<div class="text-end">
<input type="submit" value="댓글 등록" class="btn btn-primary my-2">
</div>
</form>
</div>
<div class="card border-info">
<div class="card-header bg-light" th:text="|${#lists.size(answer.commentList)}개의 댓글이 있습니다.|"></div>
<div class="card" th:each="comment : ${answer.commentList}">
<div class="card-body d-flex justify-content-between">
<div class="card-text" th:text="${comment.content}"></div>
<div class=" d-flex flex-column bg-light">
<div th:text="${comment.author.username}"></div>
<div th:text="${#temporals.format(comment.createTime, 'yyyy-MM-dd HH:mm')}"></div>
</div>
</div>
</div>
</div>
private Specification<Question> search(String kw) {
return new Specification<>() {
private static final long serialVersionUID = 1L;
@Override
public Predicate toPredicate(Root<Question> q, CriteriaQuery<?> query, CriteriaBuilder cb) {
query.distinct(true); // 중복을 제거
Join<Question, SiteUser> u1 = q.join("author", JoinType.LEFT);
Join<Question, Answer> a = q.join("answerList", JoinType.LEFT);
Join<Answer, SiteUser> u2 = a.join("author", JoinType.LEFT);
Join<Answer,Comment> c = a.join("commentList", JoinType.LEFT);
Join<Comment,SiteUser> u3 = c.join("author", JoinType.LEFT);
return cb.or(cb.like(q.get("subject"), "%" + kw + "%"), // 제목
cb.like(q.get("content"), "%" + kw + "%"), // 내용
cb.like(u1.get("username"), "%" + kw + "%"), // 질문 작성자
cb.like(a.get("content"), "%" + kw + "%"), // 답변 내용
cb.like(u2.get("username"), "%" + kw + "%"), //답변 작성자
cb.like(c.get("content"),"%"+kw+"%"), //댓글 내용
cb.like(u3.get("username"), "%" + kw + "%")); //댓글 작성자
}
};
}


댓글 내용이나 작성자를 기준으로 댓글을 검색 할 수 있게 되었음.