๐๏ธ Repository
public int delete(int id) {
return jdbcTemplate.update(
"DELETE FROM teacher WHERE id = ?",
id
);
}
๐ก Controller
@PostMapping("/delete/{id}")
public String delete(@PathVariable int id, Model model) {
try {
int affected = teacherRepository.delete(id);
if (affected == 0) {
System.out.println("ํด๋น ๊ต์ฌ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.");
}
} catch (Exception e) {
model.addAttribute("error", e.getMessage());
System.out.println(e.getMessage());
}
return "redirect:/teachers";
}
@GetMapping ์ผ๋ก ์์ฑํ์๋๋ฐ, ๊ท์น์ delete๋ @PostMapping ์ด๋ผ๊ณ ํ๋ค. ์๊ฐํด ๋ณด๋ ์๋ฌ ๋ฉ์์ง๋ฅผ ํ๋ฉด์ผ๋ก ๋์ง๋๋ ์์ผ๋ post๊ฐ ๋ ์ ์ ํ๊ฒ ๊ฐ๋ค.๐ผ๏ธ teacher-list.html
<!-- <a th:href="@{'/teachers/delete/' + ${teacher.id}}">์ญ์ </a>-->
<form th:action="@{'/teachers/delete/' + ${teacher.id}}" method="post" style="display:inline;">
<button type="submit">์ญ์ </button>
</form>
๐ง Student model
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Student {
private Integer id;
private String name;
private Integer score;
private Integer teacherId;
private String teacherName;
}
๐๏ธ Student Repository
@Repository
@RequiredArgsConstructor
public class StudentRepository {
private final JdbcTemplate jdbcTemplate;
private final RowMapper<Student> mapper = (resultSet, rowNum) ->
Student.builder()
.id(resultSet.getInt("id"))
.name(resultSet.getString("name"))
.score(resultSet.getInt("score"))
.teacherId(resultSet.getInt("teacher_id"))
.build();
public List<Student> findAll() {
String sql = "SELECT s.id, s.name, s.score, s.teacher_id, t.name AS teacher_name " +
"FROM student s LEFT JOIN teacher t ON s.teacher_id = t.id " +
"ORDER BY s.id";
return jdbcTemplate.query(sql, mapper);
}
public Student findById(int id) {
String sql = "SELECT s.id, s.name, s.score, s.teacher_id, t.name AS teacher_name " +
"FROM student s LEFT JOIN teacher t ON s.teacher_id = t.id " +
"WHERE s.id = ?";
return jdbcTemplate.queryForObject(sql, mapper, id);
}
public int save(Student student) {
return jdbcTemplate.update(
"INSERT INTO student (name, score, teacher_id) VALUES (?, ?, ?)",
student.getName(),
student.getScore(),
student.getTeacherId()
);
}
public int update(Student student) {
return jdbcTemplate.update(
"UPDATE student SET name = ?, score = ?, teacher_id = ? WHERE id = ?",
student.getName(), student.getScore(), student.getTeacherId(), student.getId()
);
}
public int delete(int id) {
return jdbcTemplate.update(
"DELETE FROM student WHERE id = ?",
id
);
}
}
| ํจ์ | ์ค๋ช |
|---|---|
| mapper | RowMapper์ ๋๋ค, builder๋ฅผ ์ด์ฉํด data row๋ฅผ ์๋ฐ ์ธ์คํด์ค๋ก ๋งคํํ๋ ํจ์ |
| findAll | jdbcTemplate์ด sql๋ก rowData, rowNum์ ๊ฐ์ ธ์ mapper์ ๋๊ฒจ ์ธ์คํด์ค ๋ฆฌ์คํธ ์์ฑ. |
| findById | "WHERE s.id = ?" ๊ตฌ๋ฌธ์ผ๋ก Student ๊ฐ์ฒด 1๊ฐ๋ง ๊ฐ์ ธ์ค๊ธฐ ๋๋ฌธ์ queryForObject() ์ฌ์ฉ. |
| save | update("INSERT INTO student (name, score, teacher_id) VALUES (?, ?, ?)", student.ยทยทยท |
| update | update("UPDATE student SET name = ?, score = ?, teacher_id = ? WHERE id = ?", student.ยทยทยท |
| delete | update("DELETE FROM student WHERE id = ?", student.ยทยทยท |
๐ก Student Controller
@Controller
@RequestMapping("/students")
@RequiredArgsConstructor
public class StudentController {
private final StudentRepository studentRepository;
private final TeacherRepository teacherRepository;
@GetMapping
public String list(Model model) {
model.addAttribute("students", studentRepository.findAll());
return "student-list";
}
@GetMapping("/add")
public String addForm(Model model) {
List<Teacher> teachers = teacherRepository.findAll();
model.addAttribute("student", new Student()); // ๋น ๊ฐ์ฒด ๋์ง๊ธฐ
model.addAttribute("teachers", teachers);
return "student-form";
}
@PostMapping("/add")
public String add(@ModelAttribute Student student) {
studentRepository.save(student);
return "redirect:/students";
}
@GetMapping("/edit/{id}")
public String editForm(@PathVariable int id, Model model) {
model.addAttribute("student", studentRepository.findById(id));
model.addAttribute("teachers", teacherRepository.findAll());
return "student-form";
}
@PostMapping("/edit")
public String edit(@ModelAttribute Student student) {
studentRepository.update(student);
return "redirect:/students";
}
@PostMapping("/delete/{id}")
public String delete(@PathVariable int id) {
studentRepository.delete(id);
return "redirect:/students";
}
}
| ์ปจํธ๋กค๋ฌ | ์ค๋ช |
|---|---|
| @GetMapping | ๋ชจ๋ธ์ List<Student> ๋ด์ ํด๋ผ์ด์ธํธ์ ์ ๋ฌ |
| @GetMapping("/add") | ํ์ ์
๋ ฅ ํผ์ Student ๋น ๊ฐ์ฒด, List<Teachers> ์ ๋ฌ |
| @PostMapping("/add") | html <form>์์ @ModelAttribute๋ก Student๊ฐ์ฒด ๋๊ธฐ๋ฉด repository๋ก ์ ์ฅ |
| @GetMapping("/edit/{id}") | @PathVariable๋ก Student id ๋ฐ์์ repository๋ก ์ฐพ์์ teachers์ ํจ๊ป ๋ฐํ |
| @PostMapping("/edit") | html <form>์์ @ModelAttribute๋ก Student๊ฐ์ฒด ๋๊ธฐ๋ฉด repository๋ก ์
๋ฐ์ดํธ |
| @PostMapping("/delete/{id}") | @PathVariable๋ก Student id ๋ฐ์์ repository๋ก ์ฐพ์์ ๋ฆฌ๋ค์ด๋ ํธ |
๐ผ๏ธ student-list.html
<body>
<h1>๐ฉโ๐ ํ์ ๋ชฉ๋ก</h1>
<p>
<a href="/">๐ ํ์ผ๋ก</a>
<a href="/students/add">โ ํ์ ๋ฑ๋ก</a>
</p>
<table>
<p style="color:red;" th:if="${error}" th:text="${error}"></p>
<thead>
<tr>
<td>ID</td>
<td>์ด๋ฆ</td>
<td>์ฑ์ </td>
<td>๊ต์ฌ</td>
<td>์ก์
</td>
</tr>
</thead>
<tbody th:each="student: ${students}">
<tr>
<td th:text="${student.id}"></td>
<td th:text="${student.name}"></td>
<td th:text="${student.score}"></td>
<td th:text="${student.teacherName} ?: '-'"></td>
<td>
<a th:href="@{'/students/edit/' + ${student.id}}">์์ </a>
<form th:action="@{'/students/delete/' + ${student.id}}" method="post" style="display:inline;">
<button type="submit">์ญ์ </button>
</form>
</td>
</tr>
</tbody>
</table>
</body>
๐ผ๏ธ Student-form.html
<body>
<h1 th:text="${student.id} == null ? 'โ ํ์ ๋ฑ๋ก' : 'ํ์ ์์ '"></h1>
<p>
<a href="/">ํ์ผ๋ก</a>
<a href="/students">ํ์ ๋ชฉ๋ก</a>
</p>
<form th:action="${student.id} == null ? @{/students/add} : @{/students/edit}" th:object="${student}" method="post">
<input type="hidden" th:field="*{id}">
<p><label>์ด๋ฆ: <input type="text" th:field="*{name}" required/></label></p>
<p><label>์ฑ์ : <input type="text" th:field="*{score}" required/></label></p>
<p><label>๊ต์ฌ: <select th:field="*{teacherId}" required>
<option th:each="teacher: ${teachers}" th:value="${teacher.id}" th:text="${teacher.name}">
</option>
</select></label></p>
<p>
<button type="submit">์ ์ฅํ๊ธฐ</button>
<a href="/students">์ทจ์ํ๊ธฐ</a>
</p>
</form>
</body>
| ๊ตฌ๋ถ | ์ํฐํฐ (Entity) | DTO |
|---|---|---|
| ์ญํ | DB ํ ์ด๋ธ๊ณผ 1:1 ๋งคํ, ์์์ฑ ๊ด๋ฆฌ | ๋ฐ์ดํฐ ์ ๋ฌ๋ง, ์์์ฑ ๋ก์ง ์์ |
| ํฌํจ ๋ด์ฉ | PK, ์ฐ๊ด๊ด๊ณ, JPA ์ด๋ ธํ ์ด์ , ๋น์ฆ๋์ค ๋ฉ์๋ ๋ฑ ํฌํจ | ํ๋ฉด/API์ ํ์ํ ํ๋ ํ์ , ๋ณด์ ๋ฏผ๊ฐ ์ ๋ณด ์ ์ธ |
| ์ฑ ์ ๋ถ๋ฆฌ | ๋ฐ์ดํฐ ์ ์ฅยท์กฐํยท์ฐ๊ด ์ฒ๋ฆฌ | ํจํท์ฒ๋ผ ๊ณ์ธต ๊ฐ ๊ฐ ๋ฌถ์ ์ ๋ฌ |
์ํฐํฐ๋ โ์ ์ฅยท์กฐํโ ๋ด๋น, DTO๋ โ์ ๋ฌยท์๋ตโ ๋ด๋น
๐ง Entity
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
password VARCHAR(100) NOT NULL
);
CREATE TABLE todo (
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users(id) ON DELETE CASCADE,
title VARCHAR(200) NOT NULL,
completed BOOLEAN DEFAULT FALSE
);
๐ DTO
// ๋ก๊ทธ์ธ์ฉ
public class LoginDto {
private String username;
private String password;
}
// ํ์๊ฐ์
์ฉ
public class SignupDto {
private String username;
private String password;
}
// ํ ์ผ CRUD์ฉ
public class TodoDto {
private Integer id;
private String title;
private boolean completed;
}
๐๏ธ repository
public User findByUsername(String username) {
try {
return jdbc.queryForObject("SELECT * FROM users WHERE username=?", mapper, username);
} catch (EmptyResultDataAccessException e) {
return null;
}
}
public int save(User u) { /* ํ์๊ฐ์
INSERT */ }
public List<Todo> findAllByUserId(int uid) { /* ๋ชฉ๋ก SELECT */ }
public int save(Todo t) { /* INSERT */ }
public int update(Todo t) { /* UPDATE */ }
public int delete(int id, int uid) { /* DELETE */ }
๐ก ์ปจํธ๋กค๋ฌ ํ๋ฆ ์์ฝ
/signup โ ๋น SignupDto ์ ๋ฌ/signupfindByUsername), ์ ์ฅ(save)redirect:/login?registered/login โ ๋น LoginDto/login@ModelAttribute LoginDto โ ํผ ๋ฐ์ธ๋ฉsession.setAttribute("user", user)redirect:/todos/todos โ findAllByUserId โ ๋ชฉ๋ก/todos/add โ ์ ํญ๋ชฉ ์ถ๊ฐ/todos/edit/{id} โ ์์ /todos/delete/{id} โ ์ญ์ @PostMapping("/todos/add")
public String add(@ModelAttribute TodoDto dto, HttpSession session) {
int uid = getCurrentUser(session).getId();
todoRepo.save(new Todo(uid, dto.getTitle(), dto.isCompleted()));
return "redirect:/todos";
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread worker = new Thread(() -> {
System.out.println("Worker: ์์
์์");
try {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("Working...");
Thread.sleep(500);
}
} catch(InterruptedException e) {
System.out.println("Worker: ์ค๋จ ์ ํธ ์์ , ์ ๋ฆฌ ์์
ํ ์ข
๋ฃ");
}
});
worker.start();
Thread.sleep(2000);
System.out.println("๋ฉ์ธ์์ ์ธํฐ๋ฝํธ ์ ํธ ์ ์ก");
worker.interrupt();
worker.join();
System.out.println("Worker: ์์
์๋ฃ");
}
}
Worker: ์์
์์
Working...
Working...
Working...
Working...
๋ฉ์ธ์์ ์ธํฐ๋ฝํธ ์ ํธ ์ ์ก
Worker: ์ค๋จ ์ ํธ ์์ , ์ ๋ฆฌ ์์
ํ ์ข
๋ฃ
Worker: ์์
์๋ฃ
public class Main {
public static int divide(int a, int b) throws ArithmeticException {
if (b ==0) throw new ArithmeticException("0์ผ๋ก ๋๋ ์ ์์ต๋๋ค.");
return a /b;
}
public static void main(String[] args) {
try {
System.out.println(divide(10, 2));
System.out.println(divide(10, 0));
} catch (ArithmeticException e) {
System.out.println("์์ธ ๋ฐ์: " + e.getMessage());
} finally {
System.out.println("์ฒ๋ฆฌ ์๋ฃ.");
}
}
}
5
์์ธ ๋ฐ์: 0์ผ๋ก ๋๋ ์ ์์ต๋๋ค.
์ฒ๋ฆฌ ์๋ฃ.