본문 바로가기

SpringBoot

SpringBoot(15) - Server, JPA, DB 예제(전체 회원 아이디 조회 후 아이디별 회원 상세 정보 조회 / 각 아이디별 회원 정보 삭제), 추가 정리 사항

728x90
반응형

1) SpringBoot

   1-1) Server, JPA, DB 예제

      1-1-1) 전체 회원 아이디 조회 후 아이디별 회원 상세 정보 조회

      1-1-2) 각 아이디별 회원 정보 삭제

   1-2) 추가 정리사항

 

 

 

 

 

1) SpringBoot

1-1) Server, JPA, DB 예제

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

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>web3</title>
</head>
<body>
	<h1>[ web3 ]</h1>
	
	<p>
		<a href="test">저장 테스트</a>
	</p>
	
	<p>
		<a href="save">사용자 입력값을 저장</a>
	</p>
	
	<p>
		<a href="select">사용자 정보 조회</a>
	</p>
	
	<p>
		<a href="delete">사용자 정보 삭제</a>
	</p>
	
	<p>
		<a href="selectAll">모든 회원 보기</a>
	</p>
</body>
</html>

 

 

 

1-1-1) 전체 회원 아이디 조회 후 아이디별 회원 상세 정보 조회

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

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 전체조회 결과</title>
<style>
	div {
		width: 100%
	}

	h1, table {
		width: 600px;
		margin: 0 auto;
		text-align: center;
	}
	
	h1 {
		padding-bottom: 50px;
	}

	table, th, td {
		border: 1px solid black;
		border-collapse: collapse;
		font-weight: bold;
	}
	
	th, td {
		width: 150px;
		text-align: center;
	}
	
	th {
		background-color: orange;
		color: white;
	}
	
	th:nth-child(1) {
		width: 50px
	}
	
	td:nth-child(1) {
		width: 50px
	}
</style>
</head>
<body>
	<div>
		<h1>[ 회원 전체조회 결과 ]</h1>
		
		<table>
	      <tr>
	      	<th>NO.</th>
	        <th>ID</th>
	        <th>ID2</th>
	      </tr>
	      <tr th:if="${personList == null or personList.isEmpty()}">
	      	<td colspan="4">조회 결과가 없습니다.</td>
	      </tr>
	      <tr th:if="${personList}" th:each="person, num : ${personList}">
			<td th:text="${num.count}"></td>
			<td>
				<a th:href="|view?id=${person.id}|" th:text="${person.id}"></a>
			</td>
			<td>
				<a th:href="@{/info/{userid}(userid=${person.id})}" th:text="${person.id}"></a>
			</td>
			<!-- 경로 : /info/abc -->
		  </tr>
	    </table>
	</div>
	
</body>
</html>

 

 

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

package net.datasa.web3;

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.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RequiredArgsConstructor
@Controller
public class PersonController {
	
	private final PersonService personService;
	
	@GetMapping("test")
	public String test() {
		personService.test();
		return "redirect:/";
	}
	
	/**
	 * 입력 폼으로 이동
	 * @return Form이 있는 HTML 파일 경로
	 * */
	@GetMapping("save")
	public String save() {
		return "inputForm";
	}
	
	/**
	 * form의 입력값을 받아서 저장
	 * */
	@PostMapping("save")
	public String save(@ModelAttribute PersonDTO dto) {
		log.debug("전달된 값 : {}", dto);
		
		personService.save(dto);
		
		return "redirect:/";
	}
	
	/**
	 * 검색 form으로 이동
	 * @return HTML 파일 경로
	 * */
	@GetMapping("select")
	public String select() {
		return "selectForm";
	}
	
	@PostMapping("select")
	public String select(@RequestParam("id") String id, Model model) {
		PersonDTO dto = personService.select(id);
		
		model.addAttribute("id", id);
		model.addAttribute("person", dto);
		
		return "select";
	}
	
	// 삭제 form으로 이동
	@GetMapping("delete")
	public String delete() {
		return "deleteForm";
	}
	
	// 삭제
	@PostMapping("delete")
	public String delete(@RequestParam("id") String id, Model model) {
		boolean result = personService.delete(id);
		
		// 삭제 여부와 삭제한 아이디를 모델에 저장하고 HTML로 포워딩
		// 1. XXX : 없는 아이디입니다.
		// 2. XXX 회원정보를 삭제했습니다.
		
		model.addAttribute("id", id);
		model.addAttribute("result", result);
		
		return "delete";
	}
	
	// 모든 회원 보기
	@GetMapping("selectAll")
	public String selectAll(Model model) {
		List<PersonDTO> dtoList = personService.selectAll();
		
		// 리스트를 모델에 저장하고 selectAll.html로 포워딩
		// 결과를 화면에 표 형태로 출력한다.
		model.addAttribute("personList", dtoList);
		
		return "selectAll";
	}
	
	// 1명의 회원 상세보기
	@GetMapping("view")
	public String view(@RequestParam("id") String id, Model model) {
		PersonDTO dto = personService.select(id);
		
		model.addAttribute("id", id);
		model.addAttribute("person", dto);
		
		return "select";
	}
	
	// 1명의 회원 상세보기(새로운 버전)
	// 바로 위의 코드와 결과는 동일하지만 주소 보안성이 더 좋다(주소 상 노출되는 정보가 적어 사용자가 임의로 주소부분 값을 수정하여 페이지를 접속할 수 없다)
	// 그래서 위의 방식보다 아래 방식을 더 추천함!
	@GetMapping("/info" + "/{id}")
	public String info(@PathVariable("id") String id, Model model) {
		PersonDTO dto = personService.select(id);
		
		model.addAttribute("id", id);
		model.addAttribute("person", dto);
		
		return "select";
	}

}

 

 

(3) 결과 화면

첫 접속 화면

 

 

"모든 회원 보기" 문구 클릭 시 화면

 

 

"abc" 클릭 시 화면 (ID Column의 "abc" 클릭, ID2 Column의 "abc" 클릭  >>  주소값 비교해서 확인할 것)

 

 

 

 

1-1-2) 각 아이디별 회원 정보 삭제

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

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 전체조회 결과</title>
<style>
	div {
		width: 100%
	}

	h1, table {
		width: 600px;
		margin: 0 auto;
		text-align: center;
	}
	
	h1 {
		padding-bottom: 50px;
	}

	table, th, td {
		border: 1px solid black;
		border-collapse: collapse;
		font-weight: bold;
	}
	
	th, td {
		width: 150px;
		text-align: center;
	}
	
	th {
		background-color: orange;
		color: white;
	}
	
	th:nth-child(1) {
		width: 50px
	}
	
	td:nth-child(1) {
		width: 50px
	}
</style>
<!-- JQuery 파일을 불러온다. -->
<script src="/js/jquery-3.7.1.min.js"></script>
<script>
	function del(id) {
		if (confirm(id + " 회원 정보를 정말 삭제하시겠습니까?")) {
			location.href = "deleteUser?id=" + id;
		}
	}
	
	// ready 함수 안에서 삭제버튼(class가 delButton임)에 click 이벤트 처리
	$(document).ready(function () {
		$(".delButton").click(function() {
			if (!confirm("삭제하시겠습니까?")) {
				return;
			}
			
			// 이벤트가 발생한 버튼 객체의 data-id를 읽어옴
			// let id1 = $(this).attr("data-id");
			// ".data()"는 값을 미리 읽어오기 때문에 ".attr()"보다 속도 면에서 더 빠르다!
			// ".data()"의 경우에는 어차피 "data"가 붙은 속성만 가져올 수 있기에
			// 아래와 같이 "data-"를 생략한 "id" 값만으로 값을 가져올 수 있음!
			let id2 = $(this).data("id");
			
			// 삭제 경로로 요청
			location.href = "deleteUser?id=" + id2;
		});
	});
</script>
</head>
<body>
	<div>
		<h1>[ 회원 전체조회 결과 ]</h1>
		
		<table>
	      <tr>
	      	<th>NO.</th>
	        <th>ID</th>
	        <th>ID2</th>
	        <th>삭제</th>
	        <th>삭제2</th>
	        <th>삭제3</th>
	      </tr>
	      <tr th:if="${personList == null or personList.isEmpty()}">
	      	<td colspan="4">조회 결과가 없습니다.</td>
	      </tr>
	      <tr th:if="${personList}" th:each="person, num : ${personList}">
			<td th:text="${num.count}"></td>
			<td>
				<a th:href="|view?id=${person.id}|" th:text="${person.id}"></a>
			</td>
			<td>
				<a th:href="@{/info/{userid}(userid=${person.id})}" th:text="${person.id}"></a>
			</td>
			<!-- 경로 : /info/abc -->
			
			<td>
				<a th:href="|deleteUser?id=${person.id}|" th:text="${person.id}">삭제</a>
			</td>
			<!-- /deleteUser?id=abc -->
			
			<td>
				<button id="delBtn">
					<a th:href="|javascript:del('${person.id}')|">삭제</a>
				</button>
			</td>
			
			<!-- JQuery로 아래 버튼의 클릭 이벤트 처리하여 삭제 -->
			<td>
				<button class="delButton" th:data-id="${person.id}">삭제</button>
			</td>
		  </tr>
	    </table>
	</div>
	
</body>
</html>

 

 

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

package net.datasa.web3;

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.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RequiredArgsConstructor
@Controller
public class PersonController {
	
	private final PersonService personService;
	
	@GetMapping("test")
	public String test() {
		personService.test();
		return "redirect:/";
	}
	
	/**
	 * 입력 폼으로 이동
	 * @return Form이 있는 HTML 파일 경로
	 * */
	@GetMapping("save")
	public String save() {
		return "inputForm";
	}
	
	/**
	 * form의 입력값을 받아서 저장
	 * */
	@PostMapping("save")
	public String save(@ModelAttribute PersonDTO dto) {
		log.debug("전달된 값 : {}", dto);
		
		personService.save(dto);
		
		return "redirect:/";
	}
	
	/**
	 * 검색 form으로 이동
	 * @return HTML 파일 경로
	 * */
	@GetMapping("select")
	public String select() {
		return "selectForm";
	}
	
	@PostMapping("select")
	public String select(@RequestParam("id") String id, Model model) {
		PersonDTO dto = personService.select(id);
		
		model.addAttribute("id", id);
		model.addAttribute("person", dto);
		
		return "select";
	}
	
	// 삭제 form으로 이동
	@GetMapping("delete")
	public String delete() {
		return "deleteForm";
	}
	
	// 삭제
	@PostMapping("delete")
	public String delete(@RequestParam("id") String id, Model model) {
		boolean result = personService.delete(id);
		
		// 삭제 여부와 삭제한 아이디를 모델에 저장하고 HTML로 포워딩
		// 1. XXX : 없는 아이디입니다.
		// 2. XXX 회원정보를 삭제했습니다.
		
		model.addAttribute("id", id);
		model.addAttribute("result", result);
		
		return "delete";
	}
	
	// 모든 회원 보기
	@GetMapping("selectAll")
	public String selectAll(Model model) {
		List<PersonDTO> dtoList = personService.selectAll();
		
		// 리스트를 모델에 저장하고 selectAll.html로 포워딩
		// 결과를 화면에 표 형태로 출력한다.
		model.addAttribute("personList", dtoList);
		
		return "selectAll";
	}
	
	// 1명의 회원 상세보기
	@GetMapping("view")
	public String view(@RequestParam("id") String id, Model model) {
		PersonDTO dto = personService.select(id);
		
		model.addAttribute("id", id);
		model.addAttribute("person", dto);
		
		return "select";
	}
	
	// 1명의 회원 상세보기(새로운 버전)
	// 바로 위의 코드와 결과는 동일하지만 주소 보안성이 더 좋다(주소 상 노출되는 정보가 적어 사용자가 임의로 주소부분 값을 수정하여 페이지를 접속할 수 없다)
	// 그래서 위의 방식보다 아래 방식을 더 추천함!
	@GetMapping("/info" + "/{id}")
	public String info(@PathVariable("id") String id, Model model) {
		PersonDTO dto = personService.select(id);
		
		model.addAttribute("id", id);
		model.addAttribute("person", dto);
		
		return "select";
	}
	
	@GetMapping("deleteUser")
	public String deleteUser(@RequestParam("id") String id) {
		personService.delete(id);
		
		return "redirect:selectAll";
	}
}

 

 

(3) 결과 화면

첫 접속 화면

 

 

"모든 회원 보기" 문구 클릭 시 화면

 

 

삭제, 삭제2, 삭제3 내용 클릭 시 결과 화면 : ID가 "xyz"인 회원

(삭제 Column의 "abc" 클릭, 삭제2 Column의 "삭제" 버튼 클릭, 삭제3 Column "삭제" 버튼 클릭)

 

 

삭제2 Column의 "삭제" 버튼 클릭 시 Confirm 창 화면(확인 버튼 클릭 : 해당 회원 정보 삭제, 취소 버튼 클릭 : 삭제 취소)

 

 

삭제3 Column의 "삭제" 버튼 클릭 시 Confirm 창 화면(확인 버튼 클릭 : 해당 회원 정보 삭제, 취소 버튼 클릭 : 삭제 취소)

 

 

 

1-2) 추가 정리사항

// 경로가 http://localhost:8888/info/1/30일 경우
// 아래와 같은 형식으로 코드를 작성한다!
// @GetMapping("/info" + "/{a}" + "/{b}")
// public String info(@PathVariable("a") String a, @PathVariable("b") String b, Model model) {}

@GetMapping("/info" + "/{id}")
public String info(@PathVariable("id") String id, Model model) {
	PersonDTO dto = personService.select(id);
		
	model.addAttribute("id", id);
	model.addAttribute("person", dto);
		
	return "select";
}

 

"/{id}"@PathVariable("id")"id" 값이 반드시 서로 같아야 한다!

이 두 값은 html로부터 전달받은 데이터 값이라고 보면 된다.

 

Thymeleaf 형식("${~~}")을 사용할 경우에는 해당 속성명 앞에 반드시 "th:"를 붙여야 한다!