์ค๋์ ์ฃผ์์ฌํญ (6/15, ๋ชฉ์์ผ)
- ๋๋์ง ์๋ Spring์ ๊ตด๋ ...
- ๊ฐ์ธ๊ณผ์ ์งํ (JPA ํ์ต ์ )
๋ฐค ๋ฆ๊ฒ๊น์ง ๋ณด์ถฉํ์ต โ ์๋ฉด๋ถ์กฑ์ผ๋ก ์์นจ์ด๋์ ๋ชปํจ
์ผ์ฐ ์ โ ์ง๋๊ฐ ์ด์ง ๋ฆ์ด์ง
๋๋ ๋ง์ธ ๋ฏ!!
๋งํฌ๋ค์ด์ผ๋ก๋ ํ๋ฅผ ๋ง๋ค ์ ์์ด์ ์คํ๋ ๋ ์ํธ๋ฅผ ์ผ๋ค๋ ์ฌํ ์ด์ผ๊ธฐ๊ฐ ์์ต๋๋ค...
mysql ์ฃผ์๊ฐ ์ ์ค์ ๋์ด์๋์ง ํ์ธํ ๊ฒ. ์ฃผ์๊ฐ ์๋ชป ์ ๋ ฅ๋์ด์์ผ๋ฉด DB์ ์ ์๋ ์ ๋ ๋ฟ๋๋ฌ ์๋ฌ๊ฐ ๋จ๊ธฐ ๋๋ฌธ์ sql ์ฃผ์๊ฐ ์ ๋๋ก ์ ๋ ฅ๋์ด์๋์ง ์ ์ํด์ ์ดํด์ผํ๋ค.
spring.datasource.url=jdbc:mysql://localhost:3306/{DB๋ช
}?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Seoul
์ฐธ๊ณ : [JDBC] PrepareStatement์์ TimeStamp, LocalDateTime ์ฌ์ฉํ๊ธฐ
์๊ฐ์ ์ง์ ์ ๋ ฅํด์ ๋ฃ์ ์๋ ์์ผ๋ฏ๋ก, id์ฒ๋ผ ์๊ฐ์ด ์๋์ผ๋ก ์์ฑ๋๋๋ก ํด์ค์ผํ๋ค.
๋ฐ๋ก ์์ฑํ๋ค๋ณด๋ฉด ์ค์ฐจ๊ฐ ์๊ธธ ์ ์๊ธฐ ๋๋ฌธ์ ์ค์ฐจ๊ฐ ์๊ธฐ์ง ์๋๋ก setCreatedAt
์ setModifiedAt
์ ํตํด ํ์ฌ ์๊ฐ์ ๋จผ์ ์ค์ ํด์ฃผ๊ณ , ๊ฐ์ updateํ ๋๋ getCreatedAt
์ getModifiedAt
์ ์ฌ์ฉํ์ฌ ์ค์ ๋ ๊ฐ์ ํธ์ถํ๋๋ก ํ๋ค.
Timestamp
๋ ๋งค๊ฐ๋ณ์๋ก LocalDateTime
๊ฐ์ ๋ฐ๊ธฐ ๋๋ฌธ์ .toLocalDateTime()
์ ์ฌ์ฉํด ๊ฐ์ ๋ณํ ํ ์ ๋ฌํด์ฃผ์๋ค.
public Blog save(Blog blog) {
// DB ์ ์ฅ
// ๊ธฐ๋ณธ ํค๋ฅผ ๋ฐํ๋ฐ๊ธฐ ์ํ ๊ฐ์ฒด
KeyHolder keyHolder = new GeneratedKeyHolder();
// ์๊ฐ ์ค์
blog.setCreatedAt(ZonedDateTime.now());
blog.setModifiedAt(ZonedDateTime.now());
String sql = "INSERT INTO post (createdAt, modifiedAt, title, content, author, password) VALUES (?,?,?,?,?,?)";
jdbcTemplate.update(con -> {
PreparedStatement preparedStatement = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
preparedStatement.setTimestamp(1, java.sql.Timestamp.valueOf(blog.getCreatedAt().toLocalDateTime()));
preparedStatement.setTimestamp(2, java.sql.Timestamp.valueOf(blog.getModifiedAt().toLocalDateTime()));
preparedStatement.setString(3, blog.getTitle());
preparedStatement.setString(4, blog.getContent());
preparedStatement.setString(5, blog.getAuthor());
preparedStatement.setString(6, blog.getPassword());
return preparedStatement;
}, keyHolder);
์ ์ฅ๋ ์ ๋ ๊ฒ์ ํ์ธํด ๋ณผ ์ ์๋ค!
์์ ํ๋ค!! (์๋์ ์ด์ด์)
์ฒ์ Table
์ ์์ฑํ ๋, ์๊ฐ์ ๋ํ ๋ฐ์ดํฐ๋ค(createdAt
๊ณผ modifiedAt
)์ ํ์
์ DATETIME
์ผ๋ก ์ง์ ํ์๋ค.
create table post (
...
createdAt DATETIME not null,
modifiedAt DATETIME not null,
...
);
post ์์ฑ ์งํ Response
๋ก๋ถํฐ๋ ๋ ์ง์ ์๊ฐ์ด ๋ฐ๋ฆฌ์ด๋จ์๊น์ง ์ถ๋ ฅ๋์ง๋ง, ๋ฐ๋ก ์์ ์ด๋ฏธ์ง์ฒ๋ผ yy-mm-dd HH-mm-ss
ํ์์ผ๋ก ์ ์ฅ๋๊ธฐ ๋๋ฌธ์, Table ์์ผ๋ก๋ ์์ธํ ํ์ธ์ด ๋ถ๊ฐ๋ฅํ๋ค. ๋, ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ ๋ถ๋ฌ์ฌ ๋ ๊ณ์ ํ๋ณํ์ ํด์ค์ผํ๋ ๋ฒ๊ฑฐ๋ก์์ด ์๋ค.
๊ทธ๋์ varchar
ํ์
์ผ๋ก ์ ์ฅํ๊ธฐ๋ก ๊ฒฐ์ ํ๋ค.
create table post (
...
createdAt varchar(100) not null,
modifiedAt varchar(100) not null,
...
);
varchar
ํ์
์ผ๋ก ๋ฐ๋์ ๋ฐ๋ผ ์์ฑํ๋ ์ฝ๋์๋ ๋ณํ๊ฐ ์กฐ๊ธ ์๊ธด๋ค. ๋จ์ํ๊ฒ LocalDateTime
์ ๋ฐ์์ String
ํ์
์ผ๋ก ๋ณํํด์ค๋ค. (๊ธฐ์กด์ ZonedDateTime
์ ์ฌ์ฉํ์์ง๋ง, ํ์์กด์ด ํ์๋ ํ์๊น์ง ์์ด์ LocalDateTime
์ ์ฌ์ฉํ๊ธฐ๋ก ํ๋ค.)
public Blog save(Blog blog) {
// ...
// ์๊ฐ ์ค์
// ํ์ฌ ์๊ฐ์ ๋ฐ์์ String ํ์
์ผ๋ก ๋ณํ
blog.setCreatedAt(LocalDateTime.now().toString());
blog.setModifiedAt(LocalDateTime.now().toString());
// ...
jdbcTemplate.update(con -> {
PreparedStatement preparedStatement = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
// ๋ค๋ฅธ ๋ฐ์ดํฐ๋ค์ฒ๋ผ getter๋ฅผ ์ฌ์ฉํ๋ค.
preparedStatement.setString(1, blog.getCreatedAt());
preparedStatement.setString(2, blog.getModifiedAt());
//...
return preparedStatement;
}, keyHolder);
๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ
์ ํด์ผํ๋ค๋ ์กฐ๊ฑด์ด ์์ด์ ์ ๋ ฌํด์ฃผ์๋ค. ์๋์ ๋ช
๋ น์ด๋ฅผ ์ด์ด์ ๋ถ์ฌ์ฃผ๊ธฐ๋ง ํ๋ฉด ๊ฐ๋จํ๊ฒ ํด๊ฒฐ๋์๋ค.
## ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌํ ๋ ์ฌ์ฉํ๋ ๋ช
๋ น์ด
ORDER BY {์ ๋ ฌ ๊ธฐ์ค ๋ฐ์ดํฐ ๋ช
} DESC
public List<BlogResponseDto> findAll() {
// DB ์กฐํ
String sql = "SELECT * FROM post ORDER BY createdAt DESC";
...
๋น๋ฐ๋ฒํธ๋ฅผ ๋ฐ์์์ผํ๋๋ฐ? ์ด๋ป๊ฒ ๋ฐ์์ค๋ผ๊ณ ์ ์๋์ด์์ง ์์์ผ๋... ์คํ ํ
์คํธ์๋ Postman์ ์ฌ์ฉํ๊ณ ์์ผ๋, ์๋ง @RequestBody
๋ฅผ ์ฌ์ฉํด์ผํ์ง ์์๊น! ๋ผ๋ ๊ฒฐ๋ก ์ด ๋์๋ค.
// ์ ํํ ๊ฒ์๊ธ ์์
@PutMapping("/post/{id}")
public BlogResponseDto updateBlogPost(@PathVariable Integer id, @RequestBody BlogRequestDto requestDto) {
return blogService.updateBlogPost(id, requestDto);
}
Controller
๋ ๋น๋ฐ๋ฒํธ ๊ฐ์ ๋ฐ๊ธฐ๋ง ํ๊ณ , ๋น๋ฐ๋ฒํธ๋ฅผ ํ๋ณํ๋ ์ผ์ Service
์๊ฒ ๋๊ฒผ๋ค. ์ฌ์ค ์ค์ ๋ก ํ๋ณํ๋ ์ผ์ Repository
๊ฐ ํ๊ฒ ๋ ๊ฒ์ด๋ค.
public BlogResponseDto updateBlogPost(Integer id, BlogRequestDto requestDto) {
// 1. ํด๋น ๊ฒ์๊ธ์ด DB์ ์กด์ฌํ๋์ง ํ์ธ
Blog blog = blogRepository.findById(id);
if(blog != null) {
// 2. ์กด์ฌํ๋ฉด ๋น๋ฐ๋ฒํธ๋ฅผ ์ฒดํฌ
boolean isRightPassword = blogRepository.checkByPassword(blog, requestDto.getPassword());
if(isRightPassword) {
// 3. ๋น๋ฐ๋ฒํธ๊ฐ ์ณ์ผ๋ฉด ๊ฒ์๊ธ ๋ด์ฉ ์์
blogRepository.update(id, requestDto); // DB ์ ์ฅ
BlogResponseDto blogResponseDto = new BlogResponseDto(blog);
return blogResponseDto;
} else {
throw new IllegalArgumentException("๋น๋ฐ๋ฒํธ๊ฐ ์ฌ๋ฐ๋ฅด์ง ์์ต๋๋ค.");
}
} else {
throw new IllegalArgumentException("์ ํํ ๊ฒ์๊ธ์ ์กด์ฌํ์ง ์์ต๋๋ค.");
}
}
Service
๋ Controller
๋ก๋ถํฐ ๋ฐ์ ์ ๋ณด๋ฅผ ์ฌ์ฉํด์ Repository
์๊ฒ ๋น๋ฐ๋ฒํธ๋ฅผ ํ๋ณํ๋๋ก ์ง์ํ๋ค.
// 2. ์กด์ฌํ๋ฉด ๋น๋ฐ๋ฒํธ๋ฅผ ์ฒดํฌ
boolean isRightPassword = blogRepository.checkByPassword(blog, requestDto.getPassword());
๋น๋ฐ๋ฒํธ๋ String.equals(String)
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ณํ์๋ค.
// ๋น๋ฐ๋ฒํธ ์ฒดํฌ
public boolean checkByPassword(Blog blog, String password) {
// ๋น๋ฐ๋ฒํธ(๋ฌธ์์ด) ๋น๊ต
if (blog.getPassword().equals(password)) {
return true;
} else {
return false;
}
}
๋ฌด์ฌํ ์คํ๋์๋ค!
{
"success":true
}
๋ช ์ธ๋ฅผ ๋ณด๋ฉด ์ด๋ฐ๊ฒ ์๋ค. ๋ญ์ง? (๋ณด์๋ง์ ์ง์ง ๋ญ์ง? ๋ผ๊ณ ์๊ฐํจ)
๋จ์ํ๊ฒ true
๋ผ๋ ๊ฐ๋ง ๋์์ค ๊ฒ ์๋๋ผ, Dto๋ฅผ ํตํด์ ๋ฐํํด์ค์ผํ๋ค๊ณ ์๊ฐํ๋ค. ๊ทธ๋ฐ๋ฐ ๊ธฐ์กด์ ์ฌ์ฉํ๋ BlogResonpseDto
ํด๋์ค๋ฅผ ๋ฐํํ๋ฉด ๋ค๋ฅธ ๊ฐ๋ค๋ ๊ฐ์ด ์ถ๋ ฅ์ด ๋๋ค. ๋ฐ๋๋ก "success"๋ผ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค ํ์๊ฐ ์์ ๋๋ ๋ณด์ฌ์ง๊ฒ ๋๋ค.
๊ทธ๋์ SuccessResponseDto
๋ผ๋ ๊ฐ์ฒด๋ฅผ ํ๋ ๋ ๋ง๋ค๊ธฐ๋ก ํ๋ค! ์ด๋ฆ์ ์ด๋ฏธ ์ค์ ํ ์ํ์์ ์๊ฐํ ๊ฑฐ์ง๋ง, ResultResponseDto
๋ผ๋ ์ด๋ฆ์ด ๋ ์ ์ ํ์์ง๋ ๋ชจ๋ฅด๊ฒ ๋ค...
@Getter
public class SuccessResponseDto {
private Boolean success; // ์ ์ฅ ์๋ฃ์ธ์ง ์๋์ง
public SuccessResponseDto(Boolean success) {
this.success = success;
}
}
์ด๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์ ์ฐ๊ด๋ ํด๋์ค์ ๋ฐํํ์ SuccessResponseDto
๋ก ์ค์ ํด์ฃผ์ด์ผํ๋ค. ๋ฐํํ์ด ๋ฐ๋ ๋ฉ์๋๋ BlogController.deleteBlogPost()
์ BlogService.deleteBlogPost()
์ด๋ค.
// ์ ํํ ๊ฒ์๊ธ ์ญ์
@DeleteMapping("/post/{id}")
public SuccessResponseDto deleteBlogPost(@PathVariable Integer id, @RequestBody BlogRequestDto requestDto) {
return blogService.deleteBlogPost(id, requestDto);
}
public SuccessResponseDto deleteBlogPost(Integer id, BlogRequestDto requestDto) {
// 1. ํด๋น ๊ฒ์๊ธ์ด DB์ ์กด์ฌํ๋์ง ํ์ธ
Blog blog = blogRepository.findById(id);
if (blog != null) {
// 2. ์กด์ฌํ๋ฉด ๋น๋ฐ๋ฒํธ๋ฅผ ์ฒดํฌ
boolean isRightPassword = blogRepository.checkByPassword(blog, requestDto.getPassword());
if(isRightPassword) {
// 3. ๋น๋ฐ๋ฒํธ๊ฐ ์ณ์ผ๋ฉด blog ์ญ์
blogRepository.delete(id);
// 4. Success ์ฌ๋ถ ๋ฐํ
return new SuccessResponseDto(true);
} else {
return new SuccessResponseDto(false);
}
} else {
throw new IllegalArgumentException("์ ํํ ๊ฒ์๊ธ์ ์กด์ฌํ์ง ์์ต๋๋ค.");
}
}
BlogService.deleteBlogPost()
์ ๊ฒฝ์ฐ๋ ๋น๋ฐ๋ฒํธ๊ฐ ํ๋ฆฌ๋ฉด false
๋ฅผ ๋์ฐ๋๊ฒ ์๋๋ผ, ์๋์ฒ๋ผ ์ค๋ฅ๋ฅผ ๋์ง๋ ค๊ณ ํ์๋ค. ํ์ฌ ์ํ์์๋ ๋ ์ค ๋ญ๊ฐ ๋ ์ข์์ง ๋ชจ๋ฅด๊ณ , api ๋ช
์ธ์์๋ "success"๋ฅผ ๋์ฐ๋ผ๊ณ ํ๊ธฐ ๋๋ฌธ์, ๋ช
์ธ์๋ฅผ ๋ ์ฐ์ ํด์ ์ ํํ๋ค.
throw new IllegalArgumentException("์๋ชป๋ ๋น๋ฐ๋ฒํธ ์
๋๋ค.");