์ผ์ ์ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์๋ ์ผ์ ๊ด๋ฆฌ ์ฑ API๋ฅผ ๊ฐ๋ฐํ๋ค. ๊ณผ์ ํธ๋ฌ๋ธ์ํ ๊ณผ ๊ณ ๋ฏผํ๋ ์ , ๋ฐฐ์ด ์ ๋ฑ์ ๊ธฐ๋กํ๊ณ ์ ํ๋ค.
๋๊ธ ์์ฑ ์, ์๋์ ๊ฐ์ด INSERT๋ฌธ์ ์ ๋๋ก ์คํ๋ ๊ฒ ๊ฐ์๋ฐ DB์์๋ comment ํ
์ด๋ธ์ด ๋ณด์ด์ง ์๋ ๋ฌธ์ ๊ฐ ์์๋ค.
@Transactional
์ ์ถ๊ฐํ์ง ์์ ๊ฒ์ด ์์ธ์ด๋ค. ํธ๋์ญ์
์ด ์๋์ผ๋ก ์ปค๋ฐ๋์ง ์์์ ๋ฐ์ดํฐ๊ฐ DB์ ๋ฐ์๋์ง ์์๋ ๊ฒ์ด๋ค. Service ๊ณ์ธต์์ DB ์์
์ ์ํํ ๋๋ ๋ฐ๋์ @Transactional
์ ์ฌ์ฉํด ํธ๋์ญ์
์ ๊ด๋ฆฌํด์ผํ๋ค.
๋ค์๊ณผ ๊ฐ์ด @Transactional
์ ๋ถ์ธ๋ค.
@Transactional
public CommentResponseDto save(Long scheduleId, String email, CommentRequestDto dto) {
Schedule schedule = scheduleRepository.findByIdOrElseThrow(scheduleId);
Member member = memberRepository.findByEmailOrElseThrow(email);
Comment comment = new Comment(dto.getContents(), member, schedule);
Comment savedComment = commentRepository.save(comment);
return new CommentResponseDto(
savedComment.getId(),
savedComment.getContents(),
member.getUsername(),
savedComment.getCreatedAt(),
savedComment.getModifiedAt()
);
}
์ด๋ ๊ฒ ํด๋ ๋์ง๋ง, ์ด์ <์ฐ๊ด ๊ด๊ณ ๋งคํ ์ธ์
>์์ ํํฐ๋๊ป์ ํด๋์ค ๋ ๋ฒจ์ ์ฐ์ @Transactional(readOnly = true)
๋ฅผ ์ฌ์ฉํ๋ค๋ ๊ฒ์ด ๊ธฐ์ต๋ ๋ค์๊ณผ ๊ฐ์ด ์์ ํ๋ค. ๊ทธ๋ฆฌ๊ณ ์ง๋๋ฒ ํผ๋๋ฐฑ์ ๋ค์ ๋ณด๋ ๋ค๋ฅธ ํํฐ๋๊ป์๋ "ํธ๋์ญ์
๋ฒ์๋ฅผ ํ์คํ ํ๊ธฐ ์ํด DB ์
๋ฐ์ดํธ์ ๊ด๋ จ๋ ๋ชจ๋ ์์
์ ํธ๋์ญ์
๋ด์์ ์ฒ๋ฆฌํ๋ ๊ฒ์ด ์ข๋ค."๋ผ๊ณ ํผ๋๋ฐฑ์ ๋จ๊ฒจ์ฃผ์
จ๋ค.
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class CommentService {
private final CommentRepository commentRepository;
private final ScheduleRepository scheduleRepository;
private final MemberRepository memberRepository;
@Transactional
public CommentResponseDto save(Long scheduleId, String email, CommentRequestDto dto) {
Schedule schedule = scheduleRepository.findByIdOrElseThrow(scheduleId);
Member member = memberRepository.findByEmailOrElseThrow(email);
Comment comment = new Comment(dto.getContents(), member, schedule);
Comment savedComment = commentRepository.save(comment);
return new CommentResponseDto(
savedComment.getId(),
savedComment.getContents(),
member.getUsername(),
savedComment.getCreatedAt(),
savedComment.getModifiedAt()
);
}
}
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ฉด์ ์ ์ ๊ฒฝ์ฐ์ง ์์๋ ๋ถ๋ถ์ ๊ฐ๋ ์ ํ์คํ ์ตํ๊ฒ ๋์๋ค.
@Transactional(readOnly = true)
์ ์ฉ@Transactional
์ด ์์ด๋ ๋์ํ์ง๋ง, @Transactional(readOnly = true)
๋ฅผ ์ฌ์ฉํ๋ฉด ์ฑ๋ฅ์ด ์ต์ ํ ๋๋ฉฐ Lazy Loading(์ง์ฐ ๋ก๋ฉ) ์ฌ์ฉ ์ ํธ๋์ญ์
์ ์ง๊ฐ ํ์ํ ์ ์์@Transactional
์ ๊ฐ๋ณ์ ์ผ๋ก ์ถ๊ฐํด์ผ ํจ.@Transactional
์ ๋ช
์ํ๋ฉด, ํด๋์ค ๋ ๋ฒจ์ readOnly = true
๋ฅผ ๋ฌด์ํ๊ณ ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ด ๊ฐ๋ฅํ ํธ๋์ญ์
์ผ๋ก ๋์๋๊ธ ์์ฑ ์, ํ์ฌ ๋ก๊ทธ์ธํ member์ ์ธ์
ํค๋ฅผ ๊ฐ์ ธ์ค๋ ๊ณผ์ ์์ ClassCastException
์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
HttpSession session = request.getSession(false);
Long memberId = (Long) session.getAttribute("sessionKey"); // ์ค๋ฅ ๋ฐ์
CommentResponseDto commentResponseDto = commnetService.save(id, memberId, dto);
์ธ์
ํค๋ก Email์ ์ ์ฅํ๋๋ฐ, String
์ Long
์ผ๋ก ๋ณํํ๋ ค๊ณ ํ๋ ์ค๋ฅ๊ฐ ๋ ๊ฒ์ด๋ค. ๋ฐ๋ผ์ ๋ค์๊ณผ ๊ฐ์ด ์์ ํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ค.
HttpSession session = request.getSession(false);
String email = (String) session.getAttribute("sessionKey");
CommentResponseDto commentResponseDto = commnetService.save(id, email, dto);
Service์์๋ id๋ก ์ฐพ๋ member๋ฅผ email๋ก ์ฐพ์ ๋ฐํํ๋ค.
// Member member = memberRepository.findByIdOrElseThrow(id); // ๊ธฐ์กด ์ฝ๋
Member member = memberRepository.findByEmailOrElseThrow(email);
๋ค์๊ณผ ๊ฐ์ด Validation ์ด๋ ธํ ์ด์ ์ ์ ์ฉํ๊ณ ํ ์คํธ ํ๋ ๊ณผ์ ์์ ๋ฌธ์ ๊ฐ ์์๋ค.
@NotBlank(message = "๋น๋ฐ๋ฒํธ๋ ํ์๊ฐ์
๋๋ค.")
@Size(min = 8, max = 12, message = "๋น๋ฐ๋ฒํธ๋ 8์ ์ด์, 12์ ์ดํ์ฌ์ผ ํฉ๋๋ค.")
@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d@$!%*?&]+$", message = "๋น๋ฐ๋ฒํธ๋ ์๋ฌธ, ์ซ์, ํน์๋ฌธ์๋ฅผ ์ ์ด๋ 1๊ฐ ์ด์ ํฌํจํด์ผ ํฉ๋๋ค.")
@Setter
@Column(nullable = false)
private String password;
๋ฌธ์ ๊ธธ์ด ์กฐ๊ฑด์ ์ถฉ์กฑํ๊ณ , ํจํด ์กฐ๊ฑด์ ์ถฉ์กฑํ์ง ์๊ณ ํ
์คํธ ํ์ ๋ 1๊ฐ์ ์ค๋ฅ๋ฅผ ์์ํ์ง๋ง 2๊ฐ์ ์ค๋ฅ ๋ชจ๋ ๋์๋ค. ์์๋ ๋ฐ๊ฟ๋ณด๊ณ ๋ช ๋ฒ์ด๋ ์กฐ๊ฑด์ ๋ค์ ํ์ธํ๋๋ฐ ๊ณ์ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์๋ค.
ํํฐ๋๊ป ์ฌ์ญค๋ณด๋ ์์ฑ์์์ ๋ฉ์ธ์ง๋ฅผ ์ฐ์ด๋ณด๋ผ๊ณ ํ์
์ ์ฐ์ด๋ณด๋ ๋ด๊ฐ ์
๋ ฅํ ๊ฐ์ด ์๋ ์ํธํ ๋ ๊ฐ์ด ๋์๋ค. ์๊ณ ๋ณด๋ ํด๋น ์ด๋
ธํ
์ด์
์ DTO ํด๋์ค์ ์ ์ฉํด์ผํ๋๋ฐ Member ์ํฐํฐ ํด๋์ค์ ์ ์ฉํด์ ์๊ธด ๋ฌธ์ ์๋ค.
๋ฌด์์ ์ ์ฉํ๋ ค๋ค ๋ณด๋ ์ด๋ฐ ๋ฌธ์ ๊ฐ ์๊ธด ๊ฒ ๊ฐ๋ค. DTO์ ์ ์ฉํ๋ ์ ์์ ์ผ๋ก ์๋ํ์๋ค.
๊ฐ์๋ฅผ ์ฐธ๊ณ ํด ๋น๋ฐ๋ฒํธ ์์ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ฉด์ ์ Setter๋ฅผ ์ฌ์ฉํ์ง์๊ณ ๋ค์๊ณผ ๊ฐ์ด ๊ตณ์ด updatePassword()
๋ฉ์๋๋ฅผ ๋ง๋ค์ด ์์ ํ๋์ง ๊ถ๊ธํ๋ค.
public void updatePassword(String password) {
this.password = password;
}
Member ์ํฐํฐ์์ ์๋์ ๊ฐ์ด @Setter
๋ฅผ password ํ๋ ์์ ์ถ๊ฐํ๋ฉด ์๋๋ ๊ฒ์ผ๊น?
@Setter
@Column(nullable = false)
private String password;
์ฐพ์๋ณด๋ Setter์ ์ฌ์ฉ์ ์ง์ํ๋ ์ด์ ๋ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์์๋ค.
setPassword()
๋ง์ผ๋ก๋ ์ด ๋ฉ์๋๊ฐ ๋น๋ฐ๋ฒํธ๋ฅผ ์ฒ์ ์ ์ฅํ๋ ์ฉ๋์ธ์ง, ๋ณ๊ฒฝํ๋ ์ฉ๋์ธ์ง ์ ์ ์๋ค. ๋ํ, ๋น๋ฐ๋ฒํธ ๋ณ๊ฒฝ ์ ๊ธฐ์กด ๋น๋ฐ๋ฒํธ ๊ฒ์ฆ ๊ฐ์ ์ถ๊ฐ ๋ก์ง์ด ํ์ํ ์๋ ์๋ค. ๋ฐ๋ผ์, updatePassword()
์ฒ๋ผ ์ญํ ์ด ๋ช
ํํ ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ด ๋ ๋ฐ๋์งํ๋ค.
โ๏ธ ์ํ์
request
์ response
์์ ์ฌ์ฉํ๋ dto๋ค์ด ์ ๋๋ ์ ธ ์๋ค.@Transactional(readOnly = true)
๊ณผ @Transactional
์ด ์ ์ ํ๊ฒ ์ฌ์ฉ๋๊ณ ์๋ค.โ๏ธ ์๊ฐํด๋ณผ ์
HttpStatus.OK
๋ฅผ ๋ฐํํ๊ณ ์์ง๋ง, ์ผ๋ฐ์ ์ผ๋ก ๋ก๊ทธ์ธ ์ฑ๊ณต ์ ๋ก๊ทธ์ธํ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ResponseEntity
์ ๋ด์์ ๋ฐํํ๋ฉด ํด๋ผ์ด์ธํธ๊ฐ ๋ก๊ทธ์ธ ํ ์ ๋ณด๋ฅผ ๋ฐ๋ก ์ฌ์ฉํ ์ ์์ด ๋ ์ ์ฉํ ์ ์๋ค.โ๏ธ ๊ถ๊ธํ ์ & ์ด๋ ค์ ๋ ์
default
๋ฉ์๋๋ฅผ ์ด์ฉํด ์์ธ ์ฒ๋ฆฌํ๋ ๋ฐฉ์๊ณผ service์์ ์์ธ ์ฒ๋ฆฌํ๋ ๋ฐฉ์ ์ค ์ผ๋ฐ์ ์ธ ๋ฐฉ์์ ๋ฌด์์ด๊ณ , default
๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ repository์์ ์์ธ์ฒ๋ฆฌ๋ฅผ ํ๋ ํน๋ณํ ๊ฒฝ์ฐ๊ฐ ์๋์ง ๊ถ๊ธํ๋ค.findByScheduleIdOrElseThrow()
์ ๊ฐ์ ๋ฉ์๋๋ฅผ repository์์ ๊ตฌํํ๋ ๋ฐฉ์๊ณผ service์์ ์์ธ ์ฒ๋ฆฌ๋ฅผ ํ๋ ๋ฐฉ์์ ๋ ๋ค ์ ํจํ๋ฉฐ, ์ ํ์ ์ํฉ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง ์ ์๋ค.findById()
์ ๊ฐ์ ๋ฉ์๋๋ฅผ ํ์ฉํ ๋, Optional
์ ๋ฐํํ๊ฑฐ๋ ๊ธฐ๋ณธ์ ์ธ throw
์ฒ๋ฆฌ๋ง ํ๊ณ ์ถ์ ๊ฒฝ์ฐ์๋ respository์์ ์ฒ๋ฆฌํ๋ ๊ฒ์ด ์ ์ฉํ ์ ์๋ค. ๋ํ, ํน์ ์์ธ๋ฅผ ์์ฃผ ๋์ง๋ ๊ฒฝ์ฐ์๋ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉํ ์ ์๋ค.