๐ก
JPA๋ฅผ ํ์ฉํ์ฌ ๊ฒ์๊ธ ์์ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ํ์ตํฉ๋๋ค
boardController - ๊ฒ์๊ธ ์์ ํ๊ธฐ ํ๋ฉด ์์ฒญ
// ๊ฒ์๊ธ ์์ ํ๋ฉด ์์ฒญ
// board/id/update
@GetMapping("/board/{id}/update-form")
public String updateForm(@PathVariable(name = "id") Integer id, HttpServletRequest request) {
// 1. ๊ฒ์๊ธ ์กฐํ
Board board = boardNativeRepository.findById(id);
// 2. ์์ฒญ ์์ฑ์ ์กฐํํ ๊ฒ์๊ธ ์์ฑ ๋ฐ ๊ฐ ์ถ๊ฐ
request.setAttribute("board", board);
// ๋ทฐ ๋ฆฌ์กธ๋ธ - ํ
ํ๋ฆฟ ๋ฐํ
return "board/update-form"; // src/main/resources/templates/board/update-form.mustache
}
board/update-form.mustache
{{> layout/header}}
<main class="container p-5 content">
<article>
<div class="card">
<div class="card-header"><b>๊ธ์์ ํ๋ฉด ์
๋๋ค</b></div>
<div class="card-body">
<form action="/board/{{board.id}}/update" method="post">
<!--์์ฑ์ ์ด๋ฆ-->
<div class="mb-3">
<input type="text" class="form-control" placeholder="enter username" name="username" value="{{board.user.username}}" readonly >
</div>
<!--์ ๋ชฉ ์
๋ ฅ -->
<div class="mb-3">
<input type="text" class="form-control" placeholder="enter title" name="title" value="{{board.title}}" required>
</div>
<!--๋ด์ฉ ์
๋ ฅ -->
<div class="mb-3">
<textarea class="form-control" rows="5" name="content" required>{{{board.content}}}</textarea>
</div>
<button class="btn btn-primary form-controller">๊ธ ์์ ํ๊ธฐ</button>
</form>
</div>
</div>
</article>
</main>
{{> layout/footer}}
Board.UpdateDTO ๋ง๋ค๊ธฐ
package com.tenco.blog_v1.board;
import com.tenco.blog_v1.user.User;
import lombok.Data;
public class BoardDTO {
@Data
public static class SaveDTO {
private String title;
private String content;
public Board toEntity(User user) {
return Board.builder()
.title(title)
.content(content)
.user(user)
.build();
}
}
@Data
public static class UpdateDTO {
private String username;
private String title;
private String content;
}
}
BoardController
// ๊ฒ์๊ธ ์์ ์์ฒญ ๊ธฐ๋ฅ
// board/{id}/update
@PostMapping("/board/{id}/update")
public String update(@PathVariable(name = "id") Integer id, @ModelAttribute BoardDTO.UpdateDTO reqDto) {
// 1. ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ ๋ฐฉ์ ์์
// 2. ์ธ์ฆ ๊ฒ์ฌ - ๋ก๊ทธ์ ์ฌ๋ถ ํ๋จ
User sessionUser = (User) session.getAttribute("sessionUser");
if(sessionUser == null) {
return "redirect:/login-form";
}
// 3. ๊ถํ ์ฒดํฌ - ๋ด ๊ธ์ด ๋ง๋?
Board board = boardRepository.findById(id);
if(board == null) {
return "redirect:/"; // ๊ฒ์๊ธ์ด ์๋ค๋ฉด ์๋ฌ ํ์ด์ง ์ถํ ์์
}
if (!board.getUser().getId().equals(sessionUser.getId())) {
return "redirect:/error-403"; // ๊ถํ์ด ์์ต๋๋ค. ์ถํ ์์
}
// 4. ์ ํจ์ฑ ๊ฒ์ฌ - ์๋ต
// 5. ์๋น์ค ์ธก ์์ (์ง์ ๊ตฌํ) - ๋ ํ์งํ ๋ฆฌ ์ฌ์ฉ
boardRepository.updateByIdJPA(id, reqDto.getTitle(), reqDto.getContent());
// 6. ๋ฆฌ๋ค์ด๋ ํธ ์ฒ๋ฆฌ
return "redirect:/board/" + id;
}
BoardRepository ์ฝ๋ ์ถ๊ฐ
@RequiredArgsConstructor
@Repository // IoC
public class BoardRepository {
private final EntityManager em;
// ๋๊ฐ์ง ๋ฐฉ์์ผ๋ก ์ฐ์ต - JQPL ์ฌ์ฉ, JPA API
@Transactional
public void updateByIdJPQL(int id, String title, String content) {
// JPQL ์ฟผ๋ฆฌ ์์ฑ
String jpql = " UPDATE Board b SET b.title = :title, b.content = :content WHERE b.id = :id ";
Query query = em.createQuery(jpql);
query.setParameter("title", title);
query.setParameter("content", content);
query.setParameter("id", id);
query.executeUpdate();
}
@Transactional
public void updateByIdJPA(int id, String title, String content) {
Board board = em.find(Board.class, id);
if(board != null) {
board.setTitle(title);
board.setContent(content);
}
// flush ๋ช
๋ น, commit ๋ช
๋ น ํ ํ์ ์์ด
// ํธ๋์ญ์
์ ์ ์ธํ๋ฉด ---> ๋ํฐ ์ฒดํน
}
- JPQL Update Query์ JPA API๋ฅผ ํตํ ์ํฐํฐ ์์ ์ ๊ฐ๊ฐ์ ์ฅ๋จ์ ์ด ์์ผ๋ฏ๋ก, ์ฌ์ฉ ์ํฉ์ ๋ง๊ฒ ์ ํํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
- ๋จ์ผ ๊ฒ์๊ธ ์์ ๊ณผ ๊ฐ์ ๊ฒฝ์ฐ์๋ JPA API ๋ฐฉ๋ฒ์ด ๋ ์ ํฉํ๋ฉฐ, ๋๋ ๋ฐ์ดํฐ ์์ ์ด ํ์ํ ๊ฒฝ์ฐ์๋ JPQL Update Query๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ํจ์จ์ ์ ๋๋ค.
- ์์์ฑ ์ปจํ ์คํธ์ ํธ๋์ญ์ ๊ด๋ฆฌ๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ค์ ํ์ฌ ๋ฐ์ดํฐ ์ผ๊ด์ฑ์ ์ ์งํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.