Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.practice.efubaccount.account.controller;

import com.practice.efubaccount.account.dto.response.AccountCommentResponse;
import com.practice.efubaccount.comment.service.CommentService;
import lombok.RequiredArgsConstructor;
//import org.springframework.http.ResponseEntity;
//import org.springframework.web.bind.annotation.GetMapping;
//import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
@RequestMapping("/accounts/{accountId}/comments")
public class AccountCommentController {
private final CommentService commentService;

//작성자별 댓글 목록 조회
@GetMapping
public ResponseEntity<AccountCommentResponse> getAccountComments(@PathVariable("accountId") Long accountId){
return ResponseEntity.ok(commentService.getAccountCommentList(accountId));
}

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package com.practice.efubaccount.account.domain;

import com.practice.efubaccount.comment.domain.Comment;

import jakarta.persistence.*;
import lombok.*;

import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@Table(name = "accounts")
Expand Down Expand Up @@ -33,6 +38,10 @@ public class Account {
@Enumerated(EnumType.STRING)
private AccountStatus status = AccountStatus.ACTIVE;

// // 연관관계의 Owner 설정
@OneToMany(mappedBy = "writer",cascade = CascadeType.ALL,orphanRemoval = true)
private List<Comment> commentList = new ArrayList<>();

@Builder
public Account(String email, String password, String nickname) {
this.email = email;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.practice.efubaccount.account.dto.response;

import com.practice.efubaccount.account.domain.Account;
import com.practice.efubaccount.comment.domain.Comment;
import com.practice.efubaccount.comment.dto.response.CommentResponse;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

import java.util.List;
import java.util.stream.Collectors;

@Getter
@Builder
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class AccountCommentResponse {
private final String accountNickname;
private final List<CommentResponse> accountCommentList;
private final Long count;

// 빌더
public static AccountCommentResponse of(Account account, List<Comment> commentList){
return AccountCommentResponse.builder()
.accountNickname(account.getNickname())
.accountCommentList(commentList.stream().map(CommentResponse::of).collect(Collectors.toList()))
.count((long) commentList.size())
.build();
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@

import java.util.Optional;

public interface AccountRepository extends JpaRepository<Account, Long> {
public interface AccountsRepository extends JpaRepository<Account, Long> {

// 이메일 중복검사를 위한 쿼리
boolean existsByEmail(String email);

// 회원 ID로 조회
Optional<Account> findByAccountId(Long accountId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import com.practice.efubaccount.account.dto.request.CreateAccountRequestDto;
import com.practice.efubaccount.account.domain.Account;
import com.practice.efubaccount.account.domain.AccountStatus;
import com.practice.efubaccount.account.repository.AccountRepository;
import com.practice.efubaccount.account.repository.AccountsRepository;
import com.practice.efubaccount.global.exception.CustomException;
import com.practice.efubaccount.global.exception.ErrorCode;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -18,11 +18,11 @@
@Transactional(readOnly = true)
public class AccountsService {

private final AccountRepository accountRepository;
private final AccountsRepository accountsRepository;

// 회원 단건 조회
public AccountResponseDto getAccount(Long accountId) {
Account account = accountRepository.findByAccountId(accountId)
Account account = accountsRepository.findByAccountId(accountId)
.orElseThrow(() -> new IllegalArgumentException("해당 회원을 찾을 수 없습니다."));
return AccountResponseDto.from(account);
}
Expand All @@ -31,18 +31,18 @@ public AccountResponseDto getAccount(Long accountId) {
@Transactional
public CreateAccountResponseDto createAccount(CreateAccountRequestDto requestDto) {
// 이메일 중복 검사
if (accountRepository.existsByEmail(requestDto.getEmail())) {
if (accountsRepository.existsByEmail(requestDto.getEmail())) {
throw new IllegalArgumentException("이미 존재하는 email입니다. " + requestDto.getEmail());
}
Account account = requestDto.toEntity();
Account savedAccount = accountRepository.save(account);
Account savedAccount = accountsRepository.save(account);
return CreateAccountResponseDto.from(savedAccount);
}

// 프로필(자기소개) 수정
@Transactional
public AccountResponseDto updateAccount(Long accountId, BioUpdateRequestDto requestDto) {
Account account = accountRepository.findByAccountId(accountId)
Account account = accountsRepository.findByAccountId(accountId)
.orElseThrow(() -> new IllegalArgumentException("해당 회원을 찾을 수 없습니다."));
account.updateBio(requestDto.getBio());
return AccountResponseDto.from(account);
Expand All @@ -51,21 +51,23 @@ public AccountResponseDto updateAccount(Long accountId, BioUpdateRequestDto requ
// 회원 논리적 삭제 (status 변경)
@Transactional
public void deleteAccount(Long accountId) {
Account account = accountRepository.findByAccountId(accountId)
Account account = accountsRepository.findByAccountId(accountId)
.orElseThrow(() -> new IllegalArgumentException("해당 회원을 찾을 수 없습니다."));
account.changeStatus(AccountStatus.DEACTIVATED);
}

// 회원 물리적 삭제
@Transactional
public void physicalDeleteAccount(Long accountId) {
Account account = accountRepository.findByAccountId(accountId)
Account account = accountsRepository.findByAccountId(accountId)
.orElseThrow(() -> new IllegalArgumentException("해당 회원을 찾을 수 없습니다."));
accountRepository.delete(account);
accountsRepository.delete(account);
}

@Transactional(readOnly=true)
public Account findByAccountId(Long accountId) {
return accountRepository.findByAccountId(accountId)
return accountsRepository.findByAccountId(accountId)
.orElseThrow(()-> new CustomException(ErrorCode.ACCOUNT_NOT_FOUND));
}

}
41 changes: 41 additions & 0 deletions src/main/java/com/practice/efubaccount/comment/domain/Comment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.practice.efubaccount.comment.domain;

import com.practice.efubaccount.account.domain.Account;
//import com.practice.efubaccount.global.domain.BaseEntity;
import com.practice.efubaccount.global.domain.BaseEntity;
import com.practice.efubaccount.post.domain.Post;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Comment extends BaseEntity {

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

@Column(length=1000)
private String content;

// 연관관계
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="account_id",updatable = false)
private Account writer;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="post_id",updatable = false)
private Post post;

@Builder
public Comment(String content, Account writer, Post post) {
this.content = content;
this.writer = writer;
this.post = post;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.practice.efubaccount.comment.dto.request;

import com.practice.efubaccount.account.domain.Account;
import com.practice.efubaccount.comment.domain.Comment;
import com.practice.efubaccount.post.domain.Post;
import lombok.*;

@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class CommentRequest {
// 댓글 작성자 ID, 댓글 내용 전달받기 위한 필드 정의
private Long accountId;
private String content;

public Comment toEntity(Account account, Post post){
return Comment.builder()
.content(content)
.writer(account)
.post(post)
.build();
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.practice.efubaccount.comment.dto.response;

import com.practice.efubaccount.comment.domain.Comment;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

import java.time.LocalDateTime;

@Getter
@Builder
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class CommentResponse {
// 필드 정의
private final Long commentId;
private final Long postId;
private final String writerNickname;
private final String content;
private final LocalDateTime createdAt;
private final LocalDateTime updatedAt;

public static CommentResponse of(Comment comment){
return CommentResponse.builder()
.commentId(comment.getId())
.postId(comment.getPost().getId())
.writerNickname(comment.getWriter().getNickname())
.content(comment.getContent())
.createdAt(comment.getCreatedAt())
.updatedAt(comment.getModifiedAt())
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.practice.efubaccount.comment.repository;

import com.practice.efubaccount.comment.domain.Comment;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface CommentRepository extends JpaRepository<Comment,Long> {

// 특정 게시글에 달린 모든 댓글을 작성된 시간 순서대로 가져오는 쿼리
List<Comment> findAllByPostIdOrderByCreatedAt(Long postId);

// 특정 사용자가 쓴 모든 댓글을 가장 최근에 쓴 순서대로 가져오는 쿼리
List<Comment> findAllByWriterAccountIdOrderByCreatedAtDesc(Long accountId);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.practice.efubaccount.comment.service;

import com.practice.efubaccount.account.dto.response.AccountCommentResponse;
import com.practice.efubaccount.comment.dto.request.CommentRequest;
import com.practice.efubaccount.post.dto.response.PostCommentResponse;
import com.practice.efubaccount.account.domain.Account;
import com.practice.efubaccount.account.service.AccountsService;
import com.practice.efubaccount.comment.domain.Comment;
import com.practice.efubaccount.comment.repository.CommentRepository;
import com.practice.efubaccount.post.domain.Post;
import com.practice.efubaccount.post.service.PostService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@RequiredArgsConstructor
public class CommentService {

private final AccountsService accountsService;
private final PostService postService;
private final CommentRepository commentRepository;

// 댓글 생성
@Transactional
public Long createComment(Long postId,CommentRequest commentRequest){
Long accountId = commentRequest.getAccountId();
Account writer = accountsService.findByAccountId(accountId);
Post post = postService.findByPostId(postId);
Comment newComment = commentRequest.toEntity(writer,post);
commentRepository.save(newComment);
return newComment.getId();
}

// postId 로 댓글 목록 조회
@Transactional(readOnly = true)
public PostCommentResponse getPostCommentList(Long postId){
List<Comment> commentList = commentRepository.findAllByPostIdOrderByCreatedAt(postId);
return PostCommentResponse.of(postId,commentList);
}

// accountId 로 댓글 목록 조회
@Transactional(readOnly = true)
public AccountCommentResponse getAccountCommentList(Long accountId){
Account account = accountsService.findByAccountId(accountId);
List<Comment> commentList = commentRepository.findAllByWriterAccountIdOrderByCreatedAtDesc(accountId);
return AccountCommentResponse.of(account,commentList);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.practice.efubaccount.post.controller;

import com.practice.efubaccount.comment.domain.Comment;
import com.practice.efubaccount.comment.dto.request.CommentRequest;
import com.practice.efubaccount.comment.service.CommentService;
import com.practice.efubaccount.post.dto.response.PostCommentResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.net.URI;

@RestController
@RequiredArgsConstructor
@RequestMapping("/posts/{postId}/comments")
public class PostCommentController {

private final CommentService commentService;

// 댓글 생성
@PostMapping
public ResponseEntity<Void> createComment(@PathVariable("postId") Long postId,
@RequestBody CommentRequest request){
Long id = commentService.createComment(postId,request);
return ResponseEntity.created(URI.create("/posts/"+postId+"/comments/"+id)).build();
}

// 게시글 별 댓글 목록 조회
@GetMapping
public ResponseEntity<PostCommentResponse> getComments(@PathVariable("postId") Long postId){
return ResponseEntity.ok(commentService.getPostCommentList(postId));
}

}
Loading