
๊ฐ๋จํ ๊ฒ์ํ์ ๋ง๋ค๊ธฐ :
1. ๊ธ์ฐ๊ธฐ ๊ธฐ๋ฅ(C)
2. ์์ฑ๋ ๊ธ์ ๋ณด์ฌ์ฃผ๋ ๊ธฐ๋ฅ(R)
3. ๊ฒ์๋ฌผ ์์ ํ๋ ๊ธฐ๋ฅ(U)
4. ๊ฒ์๋ฌผ ์ญ์ ํ๋ ๊ธฐ๋ฅ(D)
Board ์๋ฐ ๋น์ ์์ฑํฉ๋๋ค.
@Data
public class Board {
private Integer id;
private String title;
private String content;
private String writer;
private LocalDateTime inserted;
}
BoardController
@GetMapping("/add")
public String add() {
return "board/add";
}
@PostMapping("/add")
public String addPost(Board board, RedirectAttributes redirectAttributes) {
service.add(board);
redirectAttributes.addAttribute("id", board.getId());
return "redirect:/";
}
@GetMapping("/add") : localhost:8080/add ๊ฒฝ๋ก๋ก ์์ฒญ์ด ๋ค์ด์ค๋ฉด add() ๋ฉ์๋๊ฐ ํธ์ถ๋๋ฉฐ ๊ฒ์๊ธ์ ์ถ๊ฐํ๋ ๋ทฐ ํ์ด์ง๋ก ์ด๋ํฉ๋๋ค.@PostMapping("/add") : addPost() ๋ฉ์๋๊ฐ ํธ์ถ๋๋ฉฐ ๊ฒ์๊ธ์ ์ถ๊ฐํ๊ณ ์ถ๊ฐ๋ ๊ฒ์๊ธ์ ID๋ฅผ ํฌํจํ ํ์ด์ง๋ก ๋ฆฌ๋ค์ด๋ ํธํฉ๋๋ค. ex) localhost:8080/board?id=10service.add(board); : ์ ๋ฌ๋ ๊ฒ์๊ธ ์ ๋ณด๋ฅผ ๊ฒ์ฆํ๊ณ ๋น์ฆ๋์ค ๋ก์ง์ ์คํํฉ๋๋ค.BoardService
public void add(Board board) {
mapper.insert(board);
}
BoardMapper
@Insert("""
INSERT INTO board (title, content, writer)
VALUES (#{title}, #{content}, #{writer})
""")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(Board board);
useGeneratedKeys = true๋ก ์ค์ ํ์ฌ ์๋ ์์ฑ๋ ํค(id)๋ฅผ ์ฌ์ฉํ๋๋ก ์ค์ ํฉ๋๋ค.์ฌ์ฉ์๊ฐ ๊ฒ์๊ธ ์ถ๊ฐ ์์ฒญ์ ํ๋ฉด ์ปจํธ๋กค๋ฌ์์ ํด๋น ์์ฒญ์ ์ฒ๋ฆฌํ๊ณ , ์๋น์ค ๊ณ์ธต์ ๊ฑฐ์ณ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์๋ก์ด ๊ฒ์๊ธ์ ์ถ๊ฐํ๋ ๊ณผ์ ์ด ์ํ๋ฉ๋๋ค. ์ถ๊ฐ๋ ๊ฒ์๊ธ์ ์ปจํธ๋กค๋ฌ๋ฅผ ํตํด ์ฌ์ฉ์์๊ฒ ์๋ ค์ง๊ณ , ์ฌ์ฉ์๋ ์ถ๊ฐ๋ ๊ฒ์๊ธ์ ID๋ฅผ ํฌํจํ ํ์ด์ง๋ก ๋ฆฌ๋ค์ด๋ ํธ๋ฉ๋๋ค.
โ๏ธ ๋ชจ๋ ๊ฒ์๊ธ์ ๋ณด์ฌ์ฃผ๋ ๊ธฐ๋ฅ
BoardController
@GetMapping("/")
public String home(Model model) {
// ๊ฒ์๋ฌผ ๋ชฉ๋ก ์กฐํ(Select)
// ๋ชจ๋ธ์ ๋ฃ๊ณ
model.addAttribute("boardList", service.list());
//jsp๋ก ํฌ์๋
return "board/home";
BoardService
public List<Board> list() {
return mapper.selectAll();
}
BoardMapper
@Select("SELECT * FROM board ORDER BY id DESC")
List<Board> selectAll();
์ ์ฒด ๊ฒ์๋ฌผ์ ์กฐํํ๋ ์์ฒญ์ ํ๋ฉด, ์๋น์ค์ list() ๋ฉ์๋๊ฐ ํธ์ถ๋๊ณ , ์ด ๋ฉ์๋๋ ๋งคํผ๋ฅผ ํตํด ํด๋น ๊ฒ์๋ฌผ์ ์กฐํํฉ๋๋ค. ์กฐํ๋ ๊ฒ์๋ฌผ์ ์๋น์ค๋ฅผ ํตํด ์ปจํธ๋กค๋ฌ๋ก ๋ฐํ๋์ด ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ง๊ฒ ๋ฉ๋๋ค.
โ๏ธ ํน์ id๋ฅผ ๋ฐ์ ๋ณด์ฌ์ฃผ๋ ๊ธฐ๋ฅ
BoardController
@GetMapping("/board")
public String view(Integer id, Model model) {
// ๊ฒ์๋ฌผ ์กฐํ(select) ์กฐํ ๊ฒฐ๊ณผ ๋ชจ๋ธ์ ๋ฃ๊ณ jsp๋ก ํฌ์๋ฉ
Board board = service.get(id);
model.addAttribute("board", board);
return "board/view";
}
BoardService
public Board get(Integer id) {
return mapper.selectById(id);
}
get(Integer id) : ๋งค๊ฐ๋ณ์๋ก ๋ฐ์ ID์ ํด๋นํ๋ ๊ฒ์๋ฌผ์ ๊ฐ์ ธ์ค๋ ๋ฉ์๋์
๋๋ค. ๋งคํผ๋ฅผ ํตํด ํด๋น ID๋ฅผ ๊ฐ์ง ๊ฒ์๋ฌผ์ ์กฐํํฉ๋๋ค.BoardMapper
@Select("SELECT * FROM board WHERE id = #{id}")
Board selectById(Integer id);
์ฌ์ฉ์๊ฐ ํน์ ID๋ฅผ ๊ฐ์ง ๊ฒ์๋ฌผ์ ์กฐํํ๋ ์์ฒญ์ ํ๋ฉด, ์๋น์ค์ get() ๋ฉ์๋๊ฐ ํธ์ถ๋๊ณ , ์ด ๋ฉ์๋๋ ๋งคํผ๋ฅผ ํตํด ํด๋น ๊ฒ์๋ฌผ์ ์กฐํํฉ๋๋ค. ์กฐํ๋ ๊ฒ์๋ฌผ์ ์๋น์ค๋ฅผ ํตํด ์ปจํธ๋กค๋ฌ๋ก ๋ฐํ๋์ด ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ง๊ฒ ๋ฉ๋๋ค.
BoardController
@PostMapping("/delete")
public String delete(Integer id) {
service.remove(id);
return "redirect:/";
}
remove(id) ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ์ ๋ฌ๋ฐ์ ID์ ํด๋นํ๋ ๊ฒ์๊ธ์ ์ญ์ ํฉ๋๋ค.BoardService
public void remove(Integer id) {
mapper.deleteById(id);
}
BoardMapper
@Delete("DELETE FROM board WHERE id = #{id}")
int deleteById(Integer id);
์ฌ์ฉ์๊ฐ ๊ฒ์๋ฌผ ์ญ์ ์์ฒญ์ ํ๋ฉด ์ปจํธ๋กค๋ฌ์์ ํด๋น ์์ฒญ์ ์ฒ๋ฆฌํ๊ณ , ์๋น์ค ๊ณ์ธต์ ๊ฑฐ์ณ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ํด๋น ๊ฒ์๋ฌผ์ด ์ญ์ ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ญ์ ๋ ํ์๋ ํ ํ์ด์ง๋ก ๋ฆฌ๋ค์ด๋ ํธ๋ฉ๋๋ค.
BoardController
@GetMapping("/modify")
public String modifyForm(Integer id, Model model) {
//์กฐํ ํด์ ๋ชจ๋ธ์ ๋ฃ๊ณ
model.addAttribute("board", service.get(id));
//view๋ก ํฌ์๋
return "board/modify";
}
@PostMapping("/modify")
public String modifyPost(Board board, RedirectAttributes redirectAttributes) {
service.modify(board);
redirectAttributes.addAttribute("id", board.getId());
return "redirect:/board"; // ์์ ๋ ๊ธ์ ๋ณด๋ ํ๋ฉด์ผ๋ก ๋ฆฌ๋ค์ด๋ ํธ
}
modifyForm() ๋ฉ์๋:
@GetMapping("/modify"): ์ฌ์ฉ์๊ฐ ๊ฒ์๋ฌผ์ ์์ ํ๊ณ ์ ํ ๋ ํธ์ถ๋ฉ๋๋ค.modifyPost() ๋ฉ์๋:
@PostMapping("/modify"): ์ฌ์ฉ์๊ฐ ๊ฒ์๋ฌผ์ ์์ ํ ๋ด์ฉ์ ์ ์ถํ๋ฉด ํธ์ถ๋ฉ๋๋ค.BoardService
public void modify(Board board) {
mapper.update(board);
}
BoardMapper
@Update("""
UPDATE board
SET title = #{title}, content = #{content}, writer = #{writer}
WHERE id = #{id}
""")
int update(Board board);
Board ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ ํด๋น ๊ฒ์๋ฌผ์ ์์ ํ๋ ๋ฉ์๋๋ฅผ ๋ํ๋
๋๋ค.์๋น์ค๋ ๊ฒ์๋ฌผ์ ์์ ํ๋ ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ๋น์ฆ๋์ค ๋ก์ง์ ์ฒ๋ฆฌํ๊ณ , ์ปจํธ๋กค๋ฌ๋ ์ฌ์ฉ์์ ์์ฒญ์ ๋ฐ์ ํด๋น ์์ฒญ์ ๋ง๋ ์๋น์ค ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉฐ, ๋งคํผ๋ ์ ๋ฌ๋ ๊ฒ์๋ฌผ ์ ๋ณด๋ฅผ ์ด์ฉํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ํด๋น ๊ฒ์๋ฌผ์ ์์ ํฉ๋๋ค.
BoardController
@Controller
@RequiredArgsConstructor
public class BoardController {
private final BoardService service;
@GetMapping("/add")
public String add() {
return "board/add";
}
@PostMapping("/add")
public String addPost(Board board, RedirectAttributes redirectAttributes) {
System.out.println("BoardController.addPost");
System.out.println("board = " + board);
service.add(board);
redirectAttributes.addAttribute("id", board.getId());
return "redirect:/";
}
// /board?id=3
@GetMapping("/board")
public String view(Integer id, Model model) {
// ๊ฒ์๋ฌผ ์กฐํ(select) ์กฐํ ๊ฒฐ๊ณผ ๋ชจ๋ธ์ ๋ฃ๊ณ jsp๋ก ํฌ์๋ฉ
Board board = service.get(id);
model.addAttribute("board", board);
return "board/view";
}
@GetMapping("/")
public String home(Model model) {
// ๊ฒ์๋ฌผ ๋ชฉ๋ก ์กฐํ(Select)
// ๋ชจ๋ธ์ ๋ฃ๊ณ
model.addAttribute("boardList", service.list());
//jsp๋ก ํฌ์๋
return "board/home";
}
@PostMapping("/delete")
public String delete(Integer id) {
service.remove(id);
return "redirect:/";
}
@GetMapping("/modify")
public String modifyForm(Integer id, Model model) {
//์กฐํ ํด์
// ๋ชจ๋ธ์ ๋ฃ๊ณ
model.addAttribute("board", service.get(id));
//view๋ก ํฌ์๋
return "board/modify";
}
@PostMapping("/modify")
public String modifyPost(Board board, RedirectAttributes redirectAttributes) {
System.out.println("board = " + board);
service.modify(board);
redirectAttributes.addAttribute("id", board.getId());
return "redirect:/board"; // ๊ธ์ ๋ณด๋ ํ๋ฉด์ผ๋ก ๋ฆฌ๋ค์ด๋ ํธ
}
}
BoardService
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class BoardService {
private final BoardMapper mapper;
public void add(Board board) {
mapper.insert(board);
}
public Board get(Integer id) {
return mapper.selectById(id);
}
public List<Board> list() {
return mapper.selectAll();
}
public void remove(Integer id) {
mapper.deleteById(id);
}
public void modify(Board board) {
mapper.update(board);
}
}
BoardMapper
@Mapper
public interface BoardMapper {
@Insert("""
INSERT INTO board (title, content, writer)
VALUES (#{title}, #{content}, #{writer})
""")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(Board board);
@Select("SELECT * FROM board WHERE id = #{id}")
Board selectById(Integer id);
@Select("SELECT * FROM board ORDER BY id DESC")
List<Board> selectAll();
@Delete("DELETE FROM board WHERE id = #{id}")
int deleteById(Integer id);
@Update("""
UPDATE board
SET title = #{title}, content = #{content}, writer = #{writer}
WHERE id = #{id}
""")
int update(Board board);
}
JSP
hoem(์ฒซ ํ๋ฉด)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>home</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
<c:import url="/WEB-INF/fragment/navbar.jsp"/>
<div class="container">
<div class="row justify-content-center">
<div class="col-6">
<h3>๊ฒ์๋ฌผ ๋ชฉ๋ก</h3>
<table class="table">
<thead>
<tr>
<th style="width: 50px">NO</th>
<th>์ ๋ชฉ</th>
<th style="width: 170px">์์ฑ์</th>
</tr>
</thead>
<tbody class="table-group-divider">
<c:forEach items="${boardList}" var="board">
<c:url value="/board" var="viewLink">
<c:param name="id" value="${board.id}"/>
</c:url>
<tr>
<td>${board.id}</td>
<td>
<a href="${viewLink}">${board.title}</a>
</td>
<td>${board.writer}</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
crossorigin="anonymous"></script>
</body>
</html>
navbar
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<nav class="navbar navbar-expand-lg bg-body-tertiary bg-primary mb-4" data-bs-theme="dark">
<div class="container">
<a class="navbar-brand" href="/">BOARD๐</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a href="/" class="nav-link">
๋ชฉ๋ก
</a>
</li>
<li class="nav-item">
<a href="/add" class="nav-link">
๊ธ์ฐ๊ธฐ
</a>
</li>
</ul>
</div>
</div>
</nav>
view(ํด๋น id ๊ฒ์๊ธ ํ๋ฉด)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
<c:import url="/WEB-INF/fragment/navbar.jsp"/>
<div class="container">
<div class="row justify-content-center">
<div class="col-6">
<h3>${board.id} ๋ฒ ๊ฒ์๋ฌผ</h3>
<div class="mb-3">
<label for="inputTitle" class="form-label">
์ ๋ชฉ
</label>
<input id="inputTitle" class="form-control" type="text" value="${board.title}" readonly>
</div>
<div class="mb-3">
<label for="textareaContent" class="form-label">
๋ณธ๋ฌธ
</label>
<textarea id="textareaContent" class="form-control" cols="30" rows="10"
readonly>${board.content}</textarea>
</div>
<div class="mb-3">
<label for="inputWriter" class="form-label">
์์ฑ์
</label>
<input id="inputWriter" class="form-control" type="text" readonly value="${board.writer}">
</div>
<div class="mb-3">
<label for="inputInserted" class="form-label">
์์ฑ์ผ์
</label>
<input id="inputInserted" class="form-control" type="datetime-local" readonly value="${board.inserted}">
</div>
<div class="mb-3">
<button form="formDelete" class="btn btn-danger">์ญ์ </button>
<a href="/modify?id=${board.id}" class="btn btn-primary">์์ </a>
</div>
</div>
</div>
</div>
<div style="display: none">
<form id="formDelete" action="/delete" method="post" onsubmit="return confirm('์ญ์ ํ์๊ฒ ์ต๋๊น?')">
<input type="hidden" name="id" value="${board.id}">
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
crossorigin="anonymous"></script>
</body>
</html>
add(๊ธ์ฐ๊ธฐ ํ๋ฉด)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>์ถ๊ฐ</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<body>
<c:import url="/WEB-INF/fragment/navbar.jsp"/>
<div class="container">
<div class="row justify-content-center">
<div class="col-7">
<h3 class="mb-4">์ ๊ฒ์๋ฌผ ์์ฑ</h3>
<form action="/add" method="post">
<div class="mb-3">
<label for="inputTitle" class="form-label">
์ ๋ชฉ
</label>
<input class="form-control" id="inputTitle" type="text" name="title" required>
</div>
<div class="mb-3">
<label for="textareaContent" class="form-control">
๋ณธ๋ฌธ
</label>
<textarea class="form-control" id="textareaContent" name="content" cols="30" rows="10"
required></textarea>
</div>
<div class="mb-3">
<label for="inputWriter" class="form-label">
์์ฑ์
</label>
<input class="form-control" id="inputWriter" type="text" name="writer" required>
</div>
<div class="mb-3">
<button class="btn btn-primary btn-lg">์ ์ฅ</button>
</div>
</form>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
crossorigin="anonymous"></script>
</body>
</html>
modiy(๊ฒ์๊ธ ์์ ํ๋ฉด)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>์์ </title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
<c:import url="/WEB-INF/fragment/navbar.jsp"/>
<div class="container">
<div class="row justify-content-center">
<div class="col-7">
<h3 class="mb-4">${board.id}๋ฒ ๊ฒ์๋ฌผ ์์ </h3>
<form action="/modify" method="post">
<input type="hidden" name="id" value="${board.id}">
<div class="mb-3">
<label for="inputTitle" class="form-label">
์ ๋ชฉ
</label>
<input id="inputTitle" class="form-control" type="text" value="${board.title}" name="title"
required>
</div>
<div class="mb-3">
<label for="textareaContent" class="form-label">
๋ณธ๋ฌธ
</label>
<textarea id="textareaContent" class="form-control" cols="30" rows="10" name="content"
required>${board.content}</textarea>
</div>
<div class="mb-3">
<label for="inputWriter" class="form-label">
์์ฑ์
</label>
<input id="inputWriter" class="form-control" type="text" value="${board.writer}" name="writer"
required>
</div>
<div class="mb-3">
<button class="btn btn-secondary">์์ </button>
</div>
</form>
</div>
</div>
</div>
<script src=" https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
crossorigin="anonymous"></script>
</body>
</html>
์ฒซ ํ๋ฉด

๊ฒ์๋ฌผ ์์ฑ ํ๋ฉด

์ ๋ชฉ ํด๋ฆญ ์ ํด๋น ๊ฒ์๋ฌผ๋ก ๋์ด๊ฐ๋ ํ๋ฉด
