본문 바로가기

SpringBoot

SpringBoot(18) - Server, JPA, DB 예제(글 목록, 글 삭제, 글 수정)

728x90
반응형

1) SpringBoot

   1-1) Server, JPA, DB 예제

      1-1-1) 글 목록

      1-1-2) 글 삭제

      1-1-3) 글 수정

 

 

 

 

 

1) SpringBoot

1-1) Server, JPA, DB 예제

[src/main/resources] - [templates] 안에 home.html 파일 생성 후 아래와 같이 작성

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>web4</title>
</head>
<body>
	<h1>[ web4 ]</h1>
	
	<p>
		<a href="list">방명록</a>
	</p>
	
</body>
</html>

 

 

[src/main/java] - [net.datasa.web4.domain.dto] 안에 GuestBookDTO.java 파일 생성 후 아래와 같이 작성

package net.datasa.web4.domain.dto;

import java.time.LocalDateTime;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class GuestBookDTO {
	Integer num;               // 글 번호(기본키)
	String name;               // 작성자 이름
	String password;           // 비밀번호
	String message;            // 게시글 내용
	LocalDateTime inputdate;   //작성시간
}

 

 

 

1-1-1) 글 목록

(1) [src/main/java] - [net.datasa.web4.controller] 안에 GuestBookController.java 파일 생성 후 아래와 같이 작성

package net.datasa.web4.controller;

import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.datasa.web4.domain.dto.GuestBookDTO;
import net.datasa.web4.service.GuestBookService;

@Slf4j
@RequiredArgsConstructor
@Controller
public class GuestBookController {
	
	// @RequiredArgsConstructor : Lombok 라이브러리에서 제공하는 Annotation으로,
	// 해당 Annotation이 적용된 필드를 기반으로 생성자를 자동 생성해주는 역할을 한다.
	// (객체 변수에 final 키워드를 붙여 값이 변경되지 않도록 만듦)
	// 따라서 GuestBookController 클래스는 "@RequiredArgsConstructor" Annotation을 통해
	// 생성자를 만들어 주기 때문에 아래의 service 객체 정의 코드만으로 생성자를 실행시켜 서비스 객체를 자동으로 생성해줌!
	private final GuestBookService guestbookService;
	
	/*
	 * public class GuestBookController {
	 * 	GuestBookController(GuestBookService guestbookService) {
	 * 		this.guestbookService = guestbookService;
	 * 	}
	 * }
	*/
	
	// home.html에서 "test" 경로 클릭하면 처리할 메소드 정의
	// GuestBookService의 test() 메서드 호출하여 entity 생성하여 DB에 저장
	// 실행 후 메인화면으로 다시 redirect
	@GetMapping("test")
	public String test() {
		guestbookService.test();
		return "redirect:/";
	}
	
	// home 화면에서 "글쓰기"를 클릭하면 입력 form으로 이동
	@GetMapping("write")
	public String write() {
		return "writeForm";
	}
	
	// 입력 form에서 글쓰고 "저장" 버튼 누르면 받아서 글 저장
	@PostMapping("write")
	public String write(@ModelAttribute GuestBookDTO dto) {
		log.debug("전달된 값 : {}", dto);
		
		guestbookService.writeSave(dto);

		return "redirect:/";
	}
	
	// 글 목록
	@GetMapping("list")
	public String list(Model model) {
		List<GuestBookDTO> dtoList = guestbookService.list(); 
		
		log.debug("전달된 값 : {}", dtoList);
		model.addAttribute("list", dtoList);
		
		// forwarding(포워딩) : 정보를 유지하면서 이동하는 것을 말함
		// redirect : 지금까지의 정보를 다 버리고 새로 시작하겠다는 것을 의미함
		
		// list.html 페이지로 포워딩하는 코드이다!
		return "list";
	}
	
}

 

 

(2) [src/main/java] - [net.datasa.web4.service] 안에 GuestBookService.java 파일 생성 후 아래와 같이 작성

package net.datasa.web4.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import jakarta.persistence.EntityNotFoundException;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import net.datasa.web4.domain.dto.GuestBookDTO;
import net.datasa.web4.domain.entity.GuestBookEntity;
import net.datasa.web4.repository.GuestBookRepository;

@RequiredArgsConstructor
@Service
@Transactional
public class GuestBookService {
	
	private final GuestBookRepository guestbookRepository;

	// 저장 테스트
	public void test() {
		// GuestBookEntity entity = new GuestBookEntity(1, "aaa", "111", "글 내용1", null);
		
		GuestBookEntity entity = GuestBookEntity.builder()
				.name("aaa")
				.password("111")
				.message("글 내용1")
				.build();
		
		guestbookRepository.save(entity);
		
	}

	/**
	 * 글 저장
	 * @param dto 저장할 글 내용
	 * */
	public void writeSave(GuestBookDTO dto) {
		GuestBookEntity entity = GuestBookEntity.builder()
				.name(dto.getName())
				.password(dto.getPassword())
				.message(dto.getMessage())
				.build();
		
		guestbookRepository.save(entity);
		
	}
	
	// select * from guestbook order by num desc; SQL 문과 동일한 기능을 수행한다!
	public List<GuestBookDTO> list() {
		// 만약 정렬 조건이 여러 개인 경우
		// Sort sort = Sort.by(
		//     Sort.Order.desc("inputdate"),
		//     Sort.Order.desc("num"),
		//     Sort.Order.asc("name")
		//);
		
		// Sort : SQL의 order by 구문을 만들어주는 역할
		Sort sort = Sort.by(Sort.Direction.DESC, "num");
		
		List<GuestBookEntity> entityList = guestbookRepository.findAll(sort);
		List<GuestBookDTO> dtoList = new ArrayList<>();
		
		// 반복문으로 Entity 객체를 DTO로 변환해서 ArrayList에 저장
		for (GuestBookEntity entity : entityList) {
			GuestBookDTO dto = GuestBookDTO.builder()
					.num(entity.getNum())
					.name(entity.getName())
					.message(entity.getMessage())
					.inputdate(entity.getInputdate())
					.build();
			dtoList.add(dto);
		}
		
		return dtoList;
	}

}

 

 

(3) [src/main/resources] - [templates] 안에 list.html 파일 생성 후 아래와 같이 작성

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>방명록</title>
<style>
	#layout {
		width: 500px;
		margin: 0 auto;
	}
	
	h1 {
		text-align: center;
	}
	
	th {
		display: inline-block;
		width: 70px;
		text-align: left;
	}
	
	textarea {
		width: 350px;
		height: 70px;
	}
</style>
</head>
<body>
	<div id="layout">
		<h1>[ 방명록 ]</h1>
		<p>
			<a href="write">글쓰기</a>
		</p>
		
		<!-- 글목록 출력 영역 -->
		<table th:each="list, n : ${list}">
		<hr>
			<tr>
				<th>번호: </th>
				<td th:text="${list.num}"></td>
			</tr>
			<tr>
				<th>작성자: </th>
				<td th:text="${list.name}"></td>
			</tr>
			<tr>
				<th>작성일: </th>
				<td th:text="${#temporals.format(list.inputdate, 'yy년 MM월 dd일 HH시 mm분 ss초')}"></td>
			</tr>
			<tr>
				<td colspan="2"><textarea th:text="${list.message}"></textarea></td>
			</tr>
			<tr>
				<td colspan="2">
					<form th:action="@{/delete}" method="post">
						<input type="hidden" name="num" th:value="${list.num}">
						<label>비밀번호</label>
						<input type="text" name="password" required>
						<input type="submit" value="삭제">
					</form>
				</td>
			</tr>
		</table>
		
	</div>
	
</body>
</html>

 

 

(4) 결과 화면

글 목록(list.html) 화면

 

 

 

1-1-2) 글 삭제

(1) [src/main/java] - [net.datasa.web4.controller] 안에 GuestBookController.java 파일 생성 후 아래와 같이 작성

package net.datasa.web4.controller;

import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.datasa.web4.domain.dto.GuestBookDTO;
import net.datasa.web4.service.GuestBookService;

@Slf4j
@RequiredArgsConstructor
@Controller
public class GuestBookController {
	
	// @RequiredArgsConstructor : Lombok 라이브러리에서 제공하는 Annotation으로,
	// 해당 Annotation이 적용된 필드를 기반으로 생성자를 자동 생성해주는 역할을 한다.
	// (객체 변수에 final 키워드를 붙여 값이 변경되지 않도록 만듦)
	// 따라서 GuestBookController 클래스는 "@RequiredArgsConstructor" Annotation을 통해
	// 생성자를 만들어 주기 때문에 아래의 service 객체 정의 코드만으로 생성자를 실행시켜 서비스 객체를 자동으로 생성해줌!
	private final GuestBookService guestbookService;
	
	/*
	 * public class GuestBookController {
	 * 	GuestBookController(GuestBookService guestbookService) {
	 * 		this.guestbookService = guestbookService;
	 * 	}
	 * }
	*/
	
	// home.html에서 "test" 경로 클릭하면 처리할 메소드 정의
	// GuestBookService의 test() 메서드 호출하여 entity 생성하여 DB에 저장
	// 실행 후 메인화면으로 다시 redirect
	@GetMapping("test")
	public String test() {
		guestbookService.test();
		return "redirect:/";
	}
	
	// home 화면에서 "글쓰기"를 클릭하면 입력 form으로 이동
	@GetMapping("write")
	public String write() {
		return "writeForm";
	}
	
	// 입력 form에서 글쓰고 "저장" 버튼 누르면 받아서 글 저장
	@PostMapping("write")
	public String write(@ModelAttribute GuestBookDTO dto) {
		log.debug("전달된 값 : {}", dto);
		
		guestbookService.writeSave(dto);

		return "redirect:/";
	}
	
	// 글 목록
	@GetMapping("list")
	public String list(Model model) {
		List<GuestBookDTO> dtoList = guestbookService.list(); 
		
		log.debug("전달된 값 : {}", dtoList);
		model.addAttribute("list", dtoList);
		
		// forwarding(포워딩) : 정보를 유지하면서 이동하는 것을 말함
		// redirect : 지금까지의 정보를 다 버리고 새로 시작하겠다는 것을 의미함
		
		// list.html 페이지로 포워딩하는 코드이다!
		return "list";
	}
	
	// 글 삭제
	@PostMapping("delete")
	public String delete(
			@RequestParam("num") Integer num,
			@RequestParam("password") String password,
			RedirectAttributes redirectAttributes) {
		
		try {
			guestbookService.delete(num, password);
		}
		catch (Exception e) {
			e.printStackTrace();
			redirectAttributes.addFlashAttribute("msg", "게시글 삭제 실패");
		}
		
		return "redirect:list";
	}
	
}

 

 

(2) [src/main/java] - [net.datasa.web4.service] 안에 GuestBookService.java 파일 생성 후 아래와 같이 작성

package net.datasa.web4.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import jakarta.persistence.EntityNotFoundException;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import net.datasa.web4.domain.dto.GuestBookDTO;
import net.datasa.web4.domain.entity.GuestBookEntity;
import net.datasa.web4.repository.GuestBookRepository;

@RequiredArgsConstructor
@Service
@Transactional
public class GuestBookService {
	
	private final GuestBookRepository guestbookRepository;

	// 저장 테스트
	public void test() {
		// GuestBookEntity entity = new GuestBookEntity(1, "aaa", "111", "글 내용1", null);
		
		GuestBookEntity entity = GuestBookEntity.builder()
				.name("aaa")
				.password("111")
				.message("글 내용1")
				.build();
		
		guestbookRepository.save(entity);
		
	}

	/**
	 * 글 저장
	 * @param dto 저장할 글 내용
	 * */
	public void writeSave(GuestBookDTO dto) {
		GuestBookEntity entity = GuestBookEntity.builder()
				.name(dto.getName())
				.password(dto.getPassword())
				.message(dto.getMessage())
				.build();
		
		guestbookRepository.save(entity);
		
	}
	
	// select * from guestbook order by num desc; SQL 문과 동일한 기능을 수행한다!
	public List<GuestBookDTO> list() {
		// 만약 정렬 조건이 여러 개인 경우
		// Sort sort = Sort.by(
		//     Sort.Order.desc("inputdate"),
		//     Sort.Order.desc("num"),
		//     Sort.Order.asc("name")
		//);
		
		// Sort : SQL의 order by 구문을 만들어주는 역할
		Sort sort = Sort.by(Sort.Direction.DESC, "num");
		
		List<GuestBookEntity> entityList = guestbookRepository.findAll(sort);
		List<GuestBookDTO> dtoList = new ArrayList<>();
		
		// 반복문으로 Entity 객체를 DTO로 변환해서 ArrayList에 저장
		for (GuestBookEntity entity : entityList) {
			GuestBookDTO dto = GuestBookDTO.builder()
					.num(entity.getNum())
					.name(entity.getName())
					.message(entity.getMessage())
					.inputdate(entity.getInputdate())
					.build();
			dtoList.add(dto);
		}
		
		return dtoList;
	}

	public void delete(Integer num, String password) {
		// 해당 번호의 글 조회
		// 없으면 예외발생
		GuestBookEntity entity = guestbookRepository.findById(num)
				.orElseThrow(() -> new EntityNotFoundException("게시글이 없습니다."));
		
		// 비밀번호 비교
		// 틀리면 예외발생
		if (!password.equals(entity.getPassword())) {
			throw new RuntimeException("비밀번호가 틀립니다.");
		}
		
		// 맞으면 삭제
		guestbookRepository.delete(entity);
		
	}

}

 

 

(3) [src/main/resources] - [templates] 안에 list.html 파일 생성 후 아래와 같이 작성

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>방명록</title>
<style>
	#layout {
		width: 500px;
		margin: 0 auto;
	}
	
	h1 {
		text-align: center;
	}
	
	th {
		display: inline-block;
		width: 70px;
		text-align: left;
	}
	
	textarea {
		width: 350px;
		height: 70px;
	}
</style>
<script th:src="@{/js/jquery-3.7.1.min.js}"></script>
<script>
	$(document).ready(function() {
		if ("[[${msg}]]") {
			alert("[[${msg}]]");
		}
	});
</script>

</head>
<body>
	<div id="layout">
		<h1>[ 방명록 ]</h1>
		<p>
			<a href="write">글쓰기</a>
		</p>
		
		<!-- 글목록 출력 영역 -->
		<table th:each="list, n : ${list}">
		<hr>
			<tr>
				<th>번호: </th>
				<td th:text="${list.num}"></td>
			</tr>
			<tr>
				<th>작성자: </th>
				<td th:text="${list.name}"></td>
			</tr>
			<tr>
				<th>작성일: </th>
				<td th:text="${#temporals.format(list.inputdate, 'yy년 MM월 dd일 HH시 mm분 ss초')}"></td>
			</tr>
			<tr>
				<td colspan="2"><textarea th:text="${list.message}"></textarea></td>
			</tr>
			<tr>
				<td colspan="2">
					<form th:action="@{/delete}" method="post">
						<input type="hidden" name="num" th:value="${list.num}">
						<label>비밀번호</label>
						<input type="text" name="password" required>
						<input type="submit" value="삭제">
					</form>
				</td>
			</tr>
			
		</table>
		
	</div>
	
</body>
</html>

 

 

(4) 결과 화면

"삭제" 버튼 클릭 전후 화면 : "삭제" 버튼을 클릭하면 브라우저 화면과 DB에서 해당 글이 완전히 삭제됨!

클릭 전 화면

 

 

 

클릭 후 화면

 

 

 

 

1-1-3) 글 수정

(1) [src/main/java] - [net.datasa.web4.controller] 안에 GuestBookController.java 파일 생성 후 아래와 같이 작성

package net.datasa.web4.controller;

import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.datasa.web4.domain.dto.GuestBookDTO;
import net.datasa.web4.service.GuestBookService;

@Slf4j
@RequiredArgsConstructor
@Controller
public class GuestBookController {
	
	// @RequiredArgsConstructor : Lombok 라이브러리에서 제공하는 Annotation으로,
	// 해당 Annotation이 적용된 필드를 기반으로 생성자를 자동 생성해주는 역할을 한다.
	// (객체 변수에 final 키워드를 붙여 값이 변경되지 않도록 만듦)
	// 따라서 GuestBookController 클래스는 "@RequiredArgsConstructor" Annotation을 통해
	// 생성자를 만들어 주기 때문에 아래의 service 객체 정의 코드만으로 생성자를 실행시켜 서비스 객체를 자동으로 생성해줌!
	private final GuestBookService guestbookService;
	
	/*
	 * public class GuestBookController {
	 * 	GuestBookController(GuestBookService guestbookService) {
	 * 		this.guestbookService = guestbookService;
	 * 	}
	 * }
	*/
	
	// home.html에서 "test" 경로 클릭하면 처리할 메소드 정의
	// GuestBookService의 test() 메서드 호출하여 entity 생성하여 DB에 저장
	// 실행 후 메인화면으로 다시 redirect
	@GetMapping("test")
	public String test() {
		guestbookService.test();
		return "redirect:/";
	}
	
	// home 화면에서 "글쓰기"를 클릭하면 입력 form으로 이동
	@GetMapping("write")
	public String write() {
		return "writeForm";
	}
	
	// 입력 form에서 글쓰고 "저장" 버튼 누르면 받아서 글 저장
	@PostMapping("write")
	public String write(@ModelAttribute GuestBookDTO dto) {
		log.debug("전달된 값 : {}", dto);
		
		guestbookService.writeSave(dto);

		return "redirect:/";
	}
	
	// 글 목록
	@GetMapping("list")
	public String list(Model model) {
		List<GuestBookDTO> dtoList = guestbookService.list(); 
		
		log.debug("전달된 값 : {}", dtoList);
		model.addAttribute("list", dtoList);
		
		// forwarding(포워딩) : 정보를 유지하면서 이동하는 것을 말함
		// redirect : 지금까지의 정보를 다 버리고 새로 시작하겠다는 것을 의미함
		
		// list.html 페이지로 포워딩하는 코드이다!
		return "list";
	}
	
	// 글 삭제
	@PostMapping("delete")
	public String delete(
			@RequestParam("num") Integer num,
			@RequestParam("password") String password,
			RedirectAttributes redirectAttributes) {
		
		try {
			guestbookService.delete(num, password);
		}
		catch (Exception e) {
			e.printStackTrace();
			redirectAttributes.addFlashAttribute("msg", "게시글 삭제 실패");
		}
		
		return "redirect:list";
	}
	
	// 글 수정
	@PostMapping("update")
	public String update(
			@RequestParam("num") Integer num,
			Model model
			) {

		GuestBookDTO dto = guestbookService.select(num);
		
		model.addAttribute("writing", dto);
		
		return "updateWriting";
	}
	
	// update form에서 글 내용 수정하고 "수정" 버튼 누르면 받아서 수정된 글 저장
	@PostMapping("updateSave")
	public String update(
			@ModelAttribute GuestBookDTO dto,
			RedirectAttributes redirectAttributes) {
		
		log.debug("전달된 값 : {}", dto);
	
		try {
			guestbookService.updateSave(dto);
		}
		catch (Exception e) {
			e.printStackTrace();
			redirectAttributes.addFlashAttribute("msg", "게시글 수정 실패");
		}
		
		return "redirect:list";
	}
	
}

 

 

(2) [src/main/java] - [net.datasa.web4.service] 안에 GuestBookService.java 파일 생성 후 아래와 같이 작성

package net.datasa.web4.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import jakarta.persistence.EntityNotFoundException;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import net.datasa.web4.domain.dto.GuestBookDTO;
import net.datasa.web4.domain.entity.GuestBookEntity;
import net.datasa.web4.repository.GuestBookRepository;

@RequiredArgsConstructor
@Service
@Transactional
public class GuestBookService {
	
	private final GuestBookRepository guestbookRepository;

	// 저장 테스트
	public void test() {
		// GuestBookEntity entity = new GuestBookEntity(1, "aaa", "111", "글 내용1", null);
		
		GuestBookEntity entity = GuestBookEntity.builder()
				.name("aaa")
				.password("111")
				.message("글 내용1")
				.build();
		
		guestbookRepository.save(entity);
		
	}

	/**
	 * 글 저장
	 * @param dto 저장할 글 내용
	 * */
	public void writeSave(GuestBookDTO dto) {
		GuestBookEntity entity = GuestBookEntity.builder()
				.name(dto.getName())
				.password(dto.getPassword())
				.message(dto.getMessage())
				.build();
		
		guestbookRepository.save(entity);
		
	}
	
	// select * from guestbook order by num desc; SQL 문과 동일한 기능을 수행한다!
	public List<GuestBookDTO> list() {
		// 만약 정렬 조건이 여러 개인 경우
		// Sort sort = Sort.by(
		//     Sort.Order.desc("inputdate"),
		//     Sort.Order.desc("num"),
		//     Sort.Order.asc("name")
		//);
		
		// Sort : SQL의 order by 구문을 만들어주는 역할
		Sort sort = Sort.by(Sort.Direction.DESC, "num");
		
		List<GuestBookEntity> entityList = guestbookRepository.findAll(sort);
		List<GuestBookDTO> dtoList = new ArrayList<>();
		
		// 반복문으로 Entity 객체를 DTO로 변환해서 ArrayList에 저장
		for (GuestBookEntity entity : entityList) {
			GuestBookDTO dto = GuestBookDTO.builder()
					.num(entity.getNum())
					.name(entity.getName())
					.message(entity.getMessage())
					.inputdate(entity.getInputdate())
					.build();
			dtoList.add(dto);
		}
		
		return dtoList;
	}

	public void delete(Integer num, String password) throws Exception {
		// 해당 번호의 글 조회
		// 없으면 예외발생
		GuestBookEntity entity = guestbookRepository.findById(num)
				.orElseThrow(() -> new EntityNotFoundException("게시글이 없습니다."));
		
		// 비밀번호 비교
		// 틀리면 예외발생
		if (!password.equals(entity.getPassword())) {
			throw new RuntimeException("비밀번호가 틀립니다.");
		}
		
		// 맞으면 삭제
		guestbookRepository.delete(entity);
		
	}
	
	public GuestBookDTO select(Integer num) {
		// findById() : Primary Key 기준으로 검색을 하는 메서드
		// orElse(null) : 결과가 없으면 "null" 값을 대입하는 메서드
		GuestBookEntity entity = guestbookRepository.findById(num).orElse(null);
				
		if (entity == null) {
			return null;
		}
				
		
		GuestBookDTO dto = new GuestBookDTO();
		dto.setNum(entity.getNum());
		dto.setName(entity.getName());
		dto.setPassword(entity.getPassword());
		dto.setMessage(entity.getMessage());
		dto.setInputdate(entity.getInputdate());
		
		return dto;
	}

	public void updateSave(GuestBookDTO dto) throws Exception {
		// DB의 정보를 조회
		GuestBookEntity entity = guestbookRepository.findById(dto.getNum())
				.orElseThrow(() -> new EntityNotFoundException("게시글이 없습니다."));
		
		// 비밀번호 비교
		// 틀리면 예외발생
		if (!dto.getPassword().equals(entity.getPassword())) {
			throw new RuntimeException("비밀번호가 틀립니다.");
		}		
				
		// 값 수정
		entity.setMessage(dto.getMessage());
				
		// 저장
		guestbookRepository.save(entity);
		
	}

}

 

 

(3) [src/main/resources] - [templates] 안에 list.html 파일 생성 후 아래와 같이 작성

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>방명록</title>
<style>
	#layout {
		width: 500px;
		margin: 0 auto;
	}
	
	h1 {
		text-align: center;
	}
	
	th {
		display: inline-block;
		width: 70px;
		text-align: left;
	}
	
	textarea {
		width: 350px;
		height: 70px;
	}
</style>
<script th:src="@{/js/jquery-3.7.1.min.js}"></script>
<script>
	$(document).ready(function() {
		if ("[[${msg}]]") {
			alert("[[${msg}]]");
		}
	});
</script>

</head>
<body>
	<div id="layout">
		<h1>[ 방명록 ]</h1>
		<p>
			<a href="write">글쓰기</a>
		</p>
		
		<!-- 글목록 출력 영역 -->
		<table th:each="list, n : ${list}">
		<hr>
			<tr>
				<th>번호: </th>
				<td th:text="${list.num}"></td>
			</tr>
			<tr>
				<th>작성자: </th>
				<td th:text="${list.name}"></td>
			</tr>
			<tr>
				<th>작성일: </th>
				<td th:text="${#temporals.format(list.inputdate, 'yy년 MM월 dd일 HH시 mm분 ss초')}"></td>
			</tr>
			<tr>
				<td colspan="2"><textarea th:text="${list.message}"></textarea></td>
			</tr>
			<tr>
				<td colspan="2">
					<form th:action="@{/delete}" method="post">
						<input type="hidden" name="num" th:value="${list.num}">
						<label>비밀번호</label>
						<input type="text" name="password" required>
						<input type="submit" value="삭제">
					</form>
				</td>
			</tr>
			<tr>
				<td colspan="2">
					<form th:action="@{/update}" method="post">
						<input type="hidden" name="num" th:value="${list.num}">
						<input type="hidden" name="message" th:value="${list.message}">
						<input type="submit" value="수정">
					</form>
				</td>
			</tr>
			
		</table>
		
	</div>
	
</body>
</html>

 

 

(4) [src/main/resources] - [templates] 안에 updateWriting.html 파일 생성 후 아래와 같이 작성

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>방명록 글 수정</title>
</head>
<body>
	<h1>[ 방명록 글 수정 ]</h1>
	<br>
	
	<form th:action="@{/updateSave}" method="post">
		<table>
			<tr>
				<td>
					<input type="hidden" name="num" th:value="${writing.num}">
				</td>
			</tr>
			<tr>
				<th>내용</th>
				<td>
					<textarea name="message" id="message" th:text="${writing.message}"></textarea>
				</td>
			</tr>
			<tr>
				<td colspan="2">
					<input type="hidden" name="num" th:value="${writing.num}">
					<label>비밀번호</label>
					<input type="text" name="password" required>
					<input type="submit" value="수정" id="updateBtn">
				</td>
			</tr>
		</table>

	</form>
</body>
</html>

 

 

(5) 결과 화면

"수정" 버튼 클릭 전후 화면 : "수정" 버튼을 클릭하여 글 수정 페이지로 이동한 후 비밀번호를 올바르게 입력하고 글 내용을 수정하면 방명록 리스트 화면과 DB에서 해당 글 내용이 모두 수정됨!

 

클릭 전 화면

 

 

 

 

클릭 후 화면