새소식

TIL

[TIL] 230529 <Spring> 회원가입, 로그인 기능이 있는 투두앱 백엔드 서버 만들기 (1)

  • -
  • 각 일정에 댓글을 작성할 수 있도록 관련 클래스를 추가하고 연관 관계를 설정합니다.
  • 매핑 관계를 설정합니다. (1:1 or N:1 or N:M)

 

entity>Schedule

@Entity // JPA가 관리할 수 있는 Entity 클래스 지정
@Getter
@Setter
@Table(name = "schedule") // 매핑할 테이블의 이름을 지정
@NoArgsConstructor
public class Schedule extends Timestamped{
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	@Column(name = "title", nullable = false)
	private String title;
	@Column(name = "content", nullable = false, length = 500)
	private String content;
	@Column(name = "manager", nullable = false)
	private String manager;
	@Column(name = "password", nullable = false)
	private String password;

	@OneToMany(mappedBy = "schedule")
	private List<Comment> commentList = new ArrayList<>();

	public Schedule(ScheduleRequestDto requestDto) {
		this.title = requestDto.getTitle();
		this.content = requestDto.getContent();
		this.manager = requestDto.getManager();
		this.password = requestDto.getPassword();
	}

	public void update(ScheduleRequestDto requestDto) {
		this.title = requestDto.getTitle();
		this.content = requestDto.getContent();
		this.manager = requestDto.getManager();
		this.password = requestDto.getPassword();
	}
}

entity>Comment

@Entity
@Getter
@Setter
@Table(name = "comments")
@NoArgsConstructor
public class Comment extends Timestamped{
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	@Column(name = "content", nullable = false, length = 500)
	private String content;

	@ManyToOne
	@JoinColumn(name = "user_id", nullable = false)
	private User user;

	@ManyToOne
	@JoinColumn(name = "schedule_id", nullable = false)
	private Schedule schedule;
}

 

 


기능

  • 선택한 일정이 있다면 댓글을 등록합니다.

조건

  • 댓글이 등록되었다면 client에게 반환합니다.
  • 선택한 일정이 DB에 저장되어 있어야 합니다.
  • 댓글을 식별하는 고유번호, 댓글 내용, 댓글을 작성한 사용자 아이디, 댓글이 작성된 일정 아이디, 작성일자를 저장할 수 있습니다.

⚠️ 예외 처리

  • 선택한 일정의 ID를 입력 받지 않은 경우
  • 댓글 내용이 비어 있는 경우
  • 일정이 DB에 저장되지 않은 경우

 

controller>CommentController

@RestController
@RequiredArgsConstructor
@RequestMapping("/api")
public class CommentController {

	private final CommentService commentService;

	// 댓글 작성
	@PostMapping("/comment")
	public CommentResponseDto createComment(@RequestBody CommentRequestDto requestDto) {
		return commentService.createComment(requestDto);
	}
}

dto>CommentRequestDto

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class CommentRequestDto {

	private Long scheduleId;
	private String content;
	private String userId;
}

dto>CommentResponseDto

@Getter
public class CommentResponseDto {

	private Long id;
	private String content;
	private String userId;
	private Long scheduleId;
	private LocalDateTime createdAt;

	public CommentResponseDto(Comment comment) {
		this.id = comment.getId();
		this.content = comment.getContent();
		this.userId = comment.getUserId();
		this.scheduleId = comment.getSchedule().getId();
		this.createdAt = comment.getCreatedAt();
	}
}

service>CommentService

@Service
@RequiredArgsConstructor
public class CommentService {

	private final CommentRepository commentRepository;
	private final ScheduleRepository scheduleRepository;

	public CommentResponseDto createComment(CommentRequestDto requestDto) {

		Long scheduleId = requestDto.getScheduleId();
		if (scheduleId == null) {
			throw new IllegalArgumentException("댓글을 작성할 일정의 ID가 입력되지 않았습니다.");
		}

		String content = requestDto.getContent();
		if (content.isEmpty()) {
			throw new IllegalArgumentException("댓글의 내용이 비어있습니다.");
		}

		String userId = requestDto.getUserId();
		if (userId.isEmpty()) {
			throw new IllegalArgumentException("작성자 ID가 입력되지 않았습니다.");
		}


		// 선택한 일정이 DB에 저장되어 있는지 확인
		Optional<Schedule> checkSchedule = scheduleRepository.findById(scheduleId);
		if (checkSchedule.isEmpty()) {
			throw new NoSuchElementException("선택한 일정을 찾을 수 없습니다.");
		}

		Schedule schedule = checkSchedule.get();

		Comment comment = new Comment(content, userId, schedule);
		commentRepository.save(comment);
		return new CommentResponseDto(comment);
	}
}

entity>Comment

@Entity
@Getter
@Setter
@Table(name = "comments")
@NoArgsConstructor
public class Comment extends Timestamped{
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	@Column(name = "content", nullable = false, length = 500)
	private String content;

	@ManyToOne
	@JoinColumn(name = "user_id", nullable = false)
	private User user;

	@ManyToOne
	@JoinColumn(name = "schedule_id", nullable = false)
	private Schedule schedule;

	public Comment(String content, User user, Schedule schedule) {
		this.content = content;
		this.user = user;
		this.schedule = schedule;
	}
}

repository>CommentRepository

public interface CommentRepository extends JpaRepository<Comment,Long> {
}

 

 


기능

  • 선택한 일정의 댓글을 수정합니다.

조건

  • 댓글이 수정되었다면 수정된 댓글을 반환합니다.
  • 댓글 내용만 수정 가능합니다.
  • 선택한 일정과 댓글이 DB에 저장되어 있어야 합니다.

⚠️ 예외 처리

  • 선택한 일정이나 댓글의 ID를 입력 받지 않은 경우
  • 일정이나 댓글이 DB에 저장되지 않은 경우
  • 선택한 댓글의 사용자가 현재 사용자와 일치하지 않은 경우

 

controller>CommentController

@RestController
@RequiredArgsConstructor
@RequestMapping("/api")
public class CommentController {

	private final CommentService commentService;

	// 댓글 수정
	@PutMapping("/comment/{commentId}")
	public CommentResponseDto updateComment(@PathVariable Long commentId, @RequestBody CommentRequestDto requestDto) {
		return commentService.updateComment(commentId, requestDto);
	}

}

service>CommentService

@Service
@RequiredArgsConstructor
public class CommentService {

	private final CommentRepository commentRepository;
	private final ScheduleRepository scheduleRepository;

	@Transactional
	public CommentResponseDto updateComment(Long commentId, CommentRequestDto requestDto) {
		Long scheduleId = requestDto.getScheduleId();
		if (scheduleId == null) {
			throw new IllegalArgumentException("댓글을 작성할 일정의 ID가 입력되지 않았습니다.");
		}

		if (commentId == null) {
			throw new IllegalArgumentException("댓글의 ID가 입력되지 않았습니다.");
		}

		String newContent = requestDto.getContent();
		if (newContent.isEmpty()) {
			throw new IllegalArgumentException("댓글의 내용이 비어있습니다.");
		}

		String userId = requestDto.getUserId();
		if (userId.isEmpty()) {
			throw new IllegalArgumentException("작성자 ID가 입력되지 않았습니다.");
		}


		// 선택한 일정이 DB에 저장되어 있는지 확인
		Optional<Schedule> checkSchedule = scheduleRepository.findById(scheduleId);
		if (checkSchedule.isEmpty()) {
			throw new NoSuchElementException("선택한 일정을 찾을 수 없습니다.");
		}

		// 선택한 댓글이 DB에 저장되어 있는지 확인
		Optional<Comment> checkComment = commentRepository.findById(commentId);
		if (checkComment.isEmpty()) {
			throw new NoSuchElementException("선택한 댓글을 찾을 수 없습니다.");
		}

		Comment comment = checkComment.get();

		if (!comment.getUserId().equals(userId)) {
			throw new IllegalArgumentException("선택한 댓글의 사용자가 현재 사용자와 일치하지 않습니다.");
		}

		// 댓글 내용이 변경되었는지 확인하고 변경된 경우에만 업데이트
		if (!newContent.equals(comment.getContent())) {
			comment.setContent(newContent);
			commentRepository.save(comment);
		}

		return new CommentResponseDto(comment);
	}
}

 

 


기능

  • 선택한 일정의 댓글을 삭제합니다.

조건

  • 성공했다는 메시지와 상태 코드 반환하기
  • 선택한 일정과 댓글이 DB에 저장되어 있어야 합니다.

⚠️ 예외 처리

  • 선택한 일정이나 댓글의 ID를 입력받지 않은 경우
  • 일정이나 댓글이 DB에 저장되지 않은 경우
  • 선택한 댓글의 사용자가 현재 사용자와 일치하지 않은 경우

 

controller>CommentController

@RestController
@RequiredArgsConstructor
@RequestMapping("/api")
public class CommentController {

	private final CommentService commentService;

	// 댓글 삭제
	@DeleteMapping("/comment/{commentId}")
	public ResponseEntity<Response> deleteComment(@PathVariable Long commentId, @RequestBody CommentRequestDto requestDto) {
		return commentService.deleteComment(commentId, requestDto);
	}
}

service>CommentService

@Service
@RequiredArgsConstructor
public class CommentService {

	private final CommentRepository commentRepository;
	private final ScheduleRepository scheduleRepository;

	public ResponseEntity<Response> deleteComment(Long commentId, CommentRequestDto requestDto) {
		Long scheduleId = requestDto.getScheduleId();
		if (scheduleId == null) {
			throw new IllegalArgumentException("댓글을 작성할 일정의 ID가 입력되지 않았습니다.");
		}

		if (commentId == null) {
			throw new IllegalArgumentException("댓글의 ID가 입력되지 않았습니다.");
		}

		String userId = requestDto.getUserId();
		if (userId.isEmpty()) {
			throw new IllegalArgumentException("작성자 ID가 입력되지 않았습니다.");
		}

		// 선택한 일정이 DB에 저장되어 있는지 확인
		Optional<Schedule> checkSchedule = scheduleRepository.findById(scheduleId);
		if (checkSchedule.isEmpty()) {
			throw new NoSuchElementException("선택한 일정을 찾을 수 없습니다.");
		}

		// 선택한 댓글이 DB에 저장되어 있는지 확인
		Optional<Comment> commentOptional = commentRepository.findById(commentId);
		if (commentOptional.isEmpty()) {
			throw new NoSuchElementException("선택한 댓글을 찾을 수 없습니다.");
		}

		Comment comment = commentOptional.get();

		// 선택한 댓글의 사용자가 현재 사용자와 일치하지 않으면 예외 발생
		if (!comment.getUserId().equals(userId)) {
			throw new IllegalArgumentException("선택한 댓글의 사용자가 현재 사용자와 일치하지 않습니다.");
		}

		// 댓글 삭제
		commentRepository.delete(comment);

		Response response = new Response(HttpStatus.OK.value(), "댓글이 성공적으로 삭제되었습니다.");

		// 성공 메시지와 상태 코드 반환
		return ResponseEntity.ok(response);
	}
}
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.