[database] CRUD ์—ฐ์Šต

์ด๊ด‘ํ›ˆยท2023๋…„ 6์›” 16์ผ
0

โœ… CRUD

๐Ÿ‘‰ ๋Œ€๋ถ€๋ถ„์˜ ์ปดํ“จํ„ฐ ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ๊ฐ€์ง€๋Š” ๊ธฐ๋ณธ์ ์ธ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ์ธ Create(์ƒ์„ฑ), Read(์ฝ๊ธฐ), Update(๊ฐฑ์‹ ), Delete(์‚ญ์ œ)๋ฅผ ๋ฌถ์–ด์„œ ์ผ์ปซ๋Š” ๋ง, ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๊ฐ–์ถ”์–ด์•ผ ํ•  ๊ธฐ๋Šฅ(์ •๋ณด์˜ ์ฐธ์กฐ/๊ฒ€์ƒ‰/๊ฐฑ์‹ )์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ์šฉ์–ด๋กœ์„œ๋„ ์‚ฌ์šฉ๋จ

01. Create (์ƒ์„ฑ)

๐Ÿ“ข ์ˆœ์„œ

  • StudentDto ํด๋ž˜์Šค ์ƒ์„ฑ
  • create.html ์ƒ์„ฑ
  • StudentController ์ƒ์„ฑ
  • StudentService ์ƒ์„ฑ

1) StudentDto ์ƒ์„ฑ

DTO : Data Transfer Object

DAO : Data Access Object

  • crud ์•ˆ์— model ํŒจํ‚ค์ง€ ์ƒ์„ฑ
  • StudentDto ํด๋ž˜์Šค ์ƒ์„ฑ
public class StudentDto {
	private Long id;
    private String name;
    private Stirng email;
    
    public StudentDto() {
    }
    
    public StudentDto(Long id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "StudentDto{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}

๐Ÿ‘‰ Constructor, Getter, Setter, toString ์ถ”๊ฐ€

2) Create.html ์ƒ์„ฑ

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Create Student</title>
</head>
<body>

<h1>Create Student</h1>
<form action="/create" method="post">
  <!-- ์‚ฌ์šฉ์ž๊ฐ€ ์ œ๊ณตํ•  ๋ฐ์ดํ„ฐ์— ์•Œ๋งž์€ Input๊ณผ label์„ ๋งŒ๋“ ๋‹ค. -->
  <label for="name-input">Name: <input id="name-input" name="name"></label><br>
  <label for="email-input">Email: <input id="email-input" name="email"></label><br>
  <input type="submit">
</form>
</body>
</html>

3) StudentController ์ƒ์„ฑ

import com.example.crud.model.StudentDto;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class StudentController {
	private final StudentService studentService;
    
    public StudentController(StudentService studentService) {
    	this.studentService = studentService;
    }
    
    @GetMapping("/create-view") // URL ์ปจ๋ฒค์…˜, ํ•˜์ดํ”ˆ์„ ์—ฐ๊ฒฐํ•ด์„œ ์ด์šฉ
    public String createView() {
    	return "create";
    }
    
    @PostMapping("/create")
    public String create(
          @RequestParam("name")
          String name,
          @RequestParam("email")
          String email
    ) {
    	System.out.println(name);
        System.out.println(email);
        StudentDto studentDto = studentService.createStudent(name, email);
        System.out.println(studentDto.toString());
        return "redirect:/create-view"; // ์ฒ˜์Œ ํŽ˜์ด์ง€๋กœ ๋Œ์•„๊ฐ€๊ฒŒ๋”
     }
 }

4) StudentService ์ƒ์„ฑ

import com.example.crud.model.StudentDto;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;

@Service
public class StudentService {
	// ๋ณต์ˆ˜์˜ StudentDto๋ฅผ ๋‹ด๋Š” ๋ณ€์ˆ˜
   private final List<StudentDto> studentList = new ArrayList<>();
   private Long nextId = 1L;
   // ์ƒˆ๋กœ์šด StudentDto๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์†Œ๋“œ
   public StudentDto createStudent(String name, String email) {
   	StudentDto newStudent = new StudentDto(
       		nextId, name, email
       );
       nextId++;
       studentList.add(newStudent);
       return newStudent;
   }
}

5) ๊ฒฐ๊ณผ

๐ŸŒย http://localhost:8080/create-view ๋กœ ํ™•์ธ

02_1. Read All (์—ฌ๋Ÿฌ๊ฐœ ์ฝ๊ธฐ)

๐Ÿ“ข ์ˆœ์„œ

  • StudentService์— ๋ฉ”์†Œ๋“œ ์ถ”๊ฐ€
  • home.html ์ƒ์„ฑ
  • StudentController ์ˆ˜์ •

1) StudentService ๋ฉ”์†Œ๋“œ ์ถ”๊ฐ€

@Service
public class StudentService {
	private Long nextId = 1L;
    private final List<StudentDto> studentList = new ArrayList<>();
    
    public StudentDto createStudent(String name, Stirng email) {
    	StudentDto newStudent = new StudentDto(nextId, name, email);
        nextId++;
        studentList.add(newStudent);
        return newStudent;
    }
    
    public List<StudentDto> readStudentAll() {
    	return studentList;
    }
}

2) home.html ์ƒ์„ฑ

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Students Home</title>
</head>
<body>
  <h1>Student List</h1>
  <div th:if="${studentList.isEmpty()}">
    <p>No students here...</p>
  </div>
  <div th:unless="${studentList.isEmpty()}" th:each="student: ${studentList}">
    <p>๋ฒˆํ˜ธ: [[${student.id}]]</p>
    <p>์ด๋ฆ„: [[${student.name}]]</p>
    <p>์ด๋ฉ”์ผ: [[${student.email}]]</p>
  </div>
  <a th:href="@{/create-view}">Create</a>
</body>
</html>

๐Ÿ‘‰ Thymeleaf ๋ฌธ๋ฒ•์„ ์ด์šฉ

3) StudentController ์ˆ˜์ •

@Controller
public class StudentController {
	private final StudentService studentService;
    
    public StudentController(StudentService studentService) {
    	this.studentService = studentService;
    }
    
    @GetMapping("/create-view")
    public String createView() {
    	return "create";
    }
    
    @PostMapping("/create")
    public String create(
    		@RequestParam("name") Stirng name,
            @RequestParam("email") String email) {
        System.out.println(name);
        System.out.println(email);
        StudentDto newStudent = studentService.createStudent(name, email);
        System.out.println(newStudent);
        return "redirect:/create-view";
        // ์ œ์ถœํ•œ ๋’ค /home์œผ๋กœ ๋ณด๋‚ด๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑ
        // return "redirect:/home";
        
        // return "home"; ์œผ๋กœ ํ•  ๊ฒฝ์šฐ, redirectํ•˜๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ "home"์ด๋ผ๋Š” view๋ฅผ ๋ณด์—ฌ์คŒ
        // ๋‹จ, ์ด๋•Œ ํ˜„์žฌ ์ฝ”๋“œ๋Š” view์— ํ•„์š”ํ•œ ์†์„ฑ๊ฐ’์„ ๋„˜๊ฒจ์ฃผ์ง€ ์•Š๊ธฐ์—, ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฑฐ๋‚˜,
        // view๊ฐ€ ์ œ๋Œ€๋กœ ํ‘œ์‹œ๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Œ
        // ์‹ค์ œ๋กœ view์™€ studentList.isEmpty() ๋ถ€๋ถ„์—์„œ null ์—๋Ÿฌ ๋ฐœ์ƒ
    }
    
    @GetMapping("/home")
    public String home(Model model) {
    	model.addAttribute("studentList", studentService.readStudentAll());
        return "home";
    }
}

4) ๊ฒฐ๊ณผ

02_2. Read One (ํ•œ๊ฐœ ์ฝ๊ธฐ)

1) StudentService ๋ฉ”์†Œ๋“œ ์ถ”๊ฐ€

๐ŸŒ for each๋ฌธ์„ ํ™œ์šฉํ•œ ์ฝ”๋“œ

// ์œ„ ์ฝ”๋“œ ์ƒ๋žต
	public StudentDto readStudent(Long id) {
    	for(StudentDto studentDto: studentDtoList) {
        	if(studentDto.getId().equals(id)) {
            	return studentDto;
            }
        }
        return null;
    }

๐ŸŒ stream์„ ํ™œ์šฉํ•œ ์ฝ”๋“œ

// ์œ„ ์ฝ”๋“œ ์ƒ๋žต
	public StudentDto readStudent(Long id) {
    	return studentDtoList
        		.stream()
                .filter(studentDto -> studentDto.getId().equals(id))
                .findFirst()
                .orElse(null);
    }

2) read.html ์ƒ์„ฑ

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>[[${student.name}]]</title>
</head>
<body>
  <h1>[[${student.id}]]. [[${student.name}]]</h1>
  <p>์ด๋ฉ”์ผ : [[${student.email}]]</p>
  <a href="/home">Back</a>
</body>
</html>

3) StudentController์— ์ถ”๊ฐ€

//์œ„ ์ฝ”๋“œ ์ƒ๋žต
	@GetMapping("/read") // http://localhost:8080/read๋กœ ์‹คํ–‰๋˜๋Š” ๋ฉ”์†Œ๋“œ
	publci String read(Long id, Model model) {
    	System.out.println(id);
        model.addAttribute(
        	"student",
            studentService.readStudent(id)
        );
        
        return "read";
    }

๐ŸŒ URL ๊ฒฝ๋กœ์— ์žˆ๋Š” ๋ณ€์ˆ˜๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ํ• ๋‹น

๐Ÿ”ธ URL โ†’ ์ปดํ“จํ„ฐ์˜ ํŒŒ์ผ์‹œ์Šคํ…œ(๊ฒฝ๋กœ)์˜ ๋ชจ์Šต์„ ์ผ๋ถ€ ์œ ์‚ฌํ•˜๊ฒŒ ๋งŒ๋“ค์–ด, ํŠน์ • ์ž์›์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ์šฉ๋„

๐Ÿ‘‰ ์กฐํšŒํ•˜๊ณ  ์‹ถ์€ ์ž์›์ด URL์— ๋“œ๋Ÿฌ๋‚˜๊ฒŒ ํ•˜๊ธฐ

	@GetMapping("/{id}") // <----- ๋ณ€๊ฒฝ
    public String read(
            @PathVariable("id") Long id, // <---- @PathVariable๋กœ url๋กœ ๋„˜๊ฒจ ๋ฐ›์€ ๊ฐ’์„
            Model model                 // Long id๋กœ ๋ฐ›์•„์„œ ์“ธ์ˆ˜ ์žˆ๋‹ค.
    ) {
        System.out.println(id);
        model.addAttribute(
                "student",
                studentService.readStudent(id)
        );

        return "read";
    }

4) ๊ฒฐ๊ณผ

  1. ๋“ฑ๋ก
  1. id๊ฐ’(1) ํ™•์ธ

03. Update (๊ฐฑ์‹ )

๐Ÿ‘‰ ๋ฐ์ดํ„ฐ ๊ฐฑ์‹ ์„ ์œ„ํ•ด์„œ 1. ๋Œ€์ƒ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ 2. ๊ฐฑ์‹ ํ•  ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋กœ ์—…๋ฐ์ดํŠธ ํ•ด์•ผํ•จ

๐Ÿ”ธUpdate = Create + Read

1) update.html ์ƒ์„ฑ

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Update</title>
</head>
<body>
    <h1>Update Student</h1>
    <form method="post">
        <!-- ์‚ฌ์šฉ์ž๊ฐ€ ์ œ๊ณตํ•  ๋ฐ์ดํ„ฐ์— ์•Œ๋งž์€ input๊ณผ label์„ ๋งŒ๋“ ๋‹ค. -->
        <label for="name-input">Name: <input id = "name-input" name="name"></label>
        <br>
        <label for="email-input">Email : <input id = "email-input" name="email"></label>
        <br>
        <!--    ๋ฐ์ดํ„ฐ ์ œ์ถœ ๋ฒ„ํŠผ -->
        <input type="submit">
    </form>
<!--  ์—…๋ฐ์ดํŠธ์ฐฝ์—์„œ ๋‹ค์‹œ ๋Œ์•„๊ฐ€์•ผ ํ•  ๊ณณ์€ ํ•™์ƒ ์ƒ์„ธํŽ˜์ด์ง€ ์ž„์œผ๋กœ ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค์ •! -->
    <a th:href="@{/{id} (id=${student.id})}">Back</a>

</body>
</html>

๐Ÿ‘‰ back์€ ์ƒ์„ธ๋ณด๊ธฐ ํŽ˜์ด์ง€๋กœ ์„ค์ •

2) StudentController์— ๋ฉ”์†Œ๋“œ ์ถ”๊ฐ€ (update-view)

// ์œ„ ์ฝ”๋“œ ์ƒ๋žต
	@GetMapping("/{id}/update-view")
    public String updateView(
    		@PathVarible("id") Long id, Model model
    ) {
    	model.addAttribute("student", studentService.readStudent(id));
        return "update";
   	}

โ“ PathVariable๊ณผ RequestParam์˜ ์ฐจ์ด

  • PathVariable์€ url์—์„œ ํŠน์ • ๋ฐ์ดํ„ฐ๋ฅผ ์ง€์ •ํ•˜๋Š” ๋“ฑ ํ•œ ๊ฐ€์ง€ ๊ฐ’๋งŒ ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ
    • ex) ํ•™์ƒ๋“ค ์ค‘ id๊ฐ€ 12๋ฒˆ์ธ ํ•™์ƒ์˜ ๋งˆ์ดํŽ˜์ด์ง€๋กœ ๊ฐ€๊ธฐ
      โ†’ localhost:8080/mypage/{ ํ•™์ƒ์˜ ์•„์ด๋””(12) }
  • RequestParam์˜ ๊ฒฝ์šฐ ํ•ด๋‹น ์œ„์น˜์—์„œ ์‚ฌ์šฉํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์•„ ๋ณด๋‚ด๋Š” ์šฉ๋„
    • ex) ํ•™์ƒ id 12๋ฒˆ ๋งˆ์ดํŽ˜์ด์ง€์—์„œ ์˜ค๋Š˜ ๋‚ ์งœ์— ์ถœ์„์ฒดํฌ๋ฅผ ํ•˜๋ ค๊ณ  ํ•จ
      โ†’ localhost:8080/mypage/{ ํ•™์ƒ์˜ ์•„์ด๋””(12) }?date=20230609&isOk=true

3) update.html ์ˆ˜์ •

๐Ÿ‘‰ ์›๋ณธ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Update</title>
</head>
<body>
<h1>Update Student</h1>
<form th:action="@{/{id}/update (id=${student.id})}" method="post">
    <!--  ์‚ฌ์šฉ์ž๊ฐ€ ์ œ๊ณตํ•  ๋ฐ์ดํ„ฐ์— ์•Œ๋งž์€ input๊ณผ label์„ ๋งŒ๋“ ๋‹ค.  -->
    <label for="name-input">
    	<!--  value ์†์„ฑ ์ถ”๊ฐ€๋กœ ์ดˆ๊ธฐ์— ํ‘œ์‹œํ•  ๊ฐ’ ์„ค์ • -->
        Name: <input id="name-input" name="name" th:value="${student.name}">
    </label>
    <br>
    <label for="email-input">
    	<!--  value ์†์„ฑ ์ถ”๊ฐ€๋กœ ์ดˆ๊ธฐ์— ํ‘œ์‹œํ•  ๊ฐ’ ์„ค์ • -->
        Email: <input id="email-input" name="email" th:value="${student.email}">
    </label>
    <br>
    <!--  ๋ฐ์ดํ„ฐ ์ œ์ถœ ๋ฒ„ํŠผ  -->
    <input type="submit">
</form>
<!--  <a href="/home">Back</a>-->
<a th:href="@{/{id} (id=${student.id})}">Back</a>
</body>
</html>

4) StudentService ๋ฉ”์†Œ๋“œ ์ถ”๊ฐ€

	public StudentDto updateStudent(Long id, String name, String email) {
    	int target = 1;
        for(int i = 0; i < studentDtoList.size(); i++) {
        	// ํ•™์ƒ์˜ ์ธ๋ฑ์Šค๋ฅผ ์ฐพ์œผ๋ฉด ๊ธฐ๋ก ํ›„ ๋ฐ˜๋ณต ์ข…๋ฃŒ
            if(studentDtoList.get(i).getId().equals(id)) {
            	target = i;
                break;
            }
        }
        
        // ์ฐพ์€ ๋Œ€์ƒ์˜ name๊ณผ email ๋ณ€๊ฒฝ
        if (target != 1) {
       		studentDtoList.get(target).setName(name);
            studentDtoList.get(target).setEmail(email);
            return studentDtoList.get(target);
        }
        else return null;
    }

5) StudentController์— ๋ฉ”์†Œ๋“œ ์ถ”๊ฐ€ (update)

// ์œ„ ์ฝ”๋“œ ์ƒ๋žต
	@PostMapping("/{id}/update")
    public String update(
    		@PathVariable("id") Long id,
            @PathVariable("name") String name,
            @PathVariable("email") String email,
    ) {
    	// service ํ™œ์šฉ
        studentService.updateStudent(id, name, email);
        // ์ƒ์„ธ๋ณด๊ธฐ ํŽ˜์ด์ง€๋กœ redirect
        return String.format("redirect:/%s", id);
    }

6) ๊ฒฐ๊ณผ

04. Delete (์‚ญ์ œ)

๐Ÿ“ข ๊ตฌํ˜„ํ•  ๊ธฐ๋Šฅ ์ •๋ฆฌ

  • ์ƒ์„ธ๋ณด๊ธฐ ํŽ˜์ด์ง€ โ†’ ์‚ญ์ œ ํ™•์ธํ•˜๊ธฐ
  • ์‚ญ์ œ ํ™•์ธ + ์‚ญ์ œ ๋ฒ„ํŠผ + ๋’ค๋กœ ๊ฐ€๊ธฐ
  • ์‚ญ์ œ ์„ฑ๊ณต ํ›„ "/home"์œผ๋กœ ์ด๋™

1) StudentController์— ๋ฉ”์†Œ๋“œ ์ถ”๊ฐ€ (delete-view)

// ์œ„ ์ฝ”๋“œ ์ƒ๋žต
	@GetMapping("/{id}/delete-view")
   public String deleteView(
   		@PathVariable("id") Long id, Model model
   ) {
   	StudentDto studentDto = studentService.readStudent(id);
       model.addAttribute("student", studentDto);
       return "delete";
  	}

2) StudentService์— ๋ฉ”์†Œ๋“œ ์ถ”๊ฐ€

// ์œ„ ์ฝ”๋“œ ์ƒ๋žต
	public boolean deleteStudent(Long id) {
    	int target = -1;
        for(int i = 0; i < studentDtoList.size(); i++) {
        	// ๋Œ€์ƒ ์„ ์ •
            if(studentDtoList.get(i).getId().equals(id) {
            	target = i;
                break;
            }
        }
        
        // ๊ฒ€์ƒ‰ ์„ฑ๊ณต์‹œ
        if (target != -1) {
        	// ์‚ญ์ œ
            studentDtoList.remove(target);
            return true;
        }
        else return false;
    }

3) StudnetController์— ๋ฉ”์†Œ๋“œ ์ถ”๊ฐ€ (delete)

๐Ÿ‘‰ ์‚ญ์ œ ํ›„์—๋Š” ์ƒ์„ธํŽ˜์ด์ง€๊ฐ€ ์—†์œผ๋ฏ€๋กœ /home์œผ๋กœ ์ด๋™

	@PostMapping("/{id}/delete")
    public String delete(
    	@PathVariable("id") Long id
    ) {
    	studentService.deleteStudent(id);
        return "redirect:/home";
   	}

4) delete.html ์ƒ์„ฑ

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Delete</title>
</head>
<body>
<h1>Delete Student Name?</h1>
<form th:action="@{/{id}/delete (id=${student.id})}" method="post">
    <h3>[[${student.name}]] ๋‹˜์˜ ์ •๋ณด๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.</h3>
    <!-- create / update ์™€๋Š” ๋‹ค๋ฅด๊ฒŒ -->
    <!-- delete์˜ ๊ฒฝ์šฐ ์ถ”๊ฐ€์ ์ธ ๋ฐ์ดํ„ฐ ํ•„์š”ํ•˜์ง€ ์•Š์Œ -->
    <!-- ๊ทธ๋ž˜์„œ ์ถ”๊ฐ€์ ์ธ input ์š”์†Œ ์—†์ด submit ๋งŒ ๋งŒ๋“ค๋ฉด ๋จ-->
    <input type="submit" value="Delete" />
</form>
<a th:href="@{/{id}(id=${student.id})}">Back</a> <!--read ํŽ˜์ด์ง€๋กœ-->
</body>
</html>

5) ๊ฒฐ๊ณผ

profile
์›ƒ์œผ๋ฉฐ ์ผํ•  ๋•Œ, ์‹œ๋„ˆ์ง€๊ฐ€ ๋ฐฐ๊ฐ€ ๋œ๋‹ค๊ณ  ๋ฏฟ๋Š” ๊ฐœ๋ฐœ์ž

0๊ฐœ์˜ ๋Œ“๊ธ€