TIL/academy

국비 TIL(Today I Learned) 20220818 스프링 ajax로 추가, 상세, 수정, 삭제, mem테이블 실습

토희 2022. 8. 18. 15:53
728x90

어제 list.jsp 에서

if문 삭제 (완전히 비동기 형식일때는 if문 넣는게 맞는데, 우리는 동기 섞여있으니)

 

이 방식으로! else문 추가됨

 

동기랑 섞인 형태일떄는 이 방식이 맞데

 

T폴더에

그리고 insert, update, detail, delete 기능 추가하고,

 

Ajax : 목록조회, 등록, 수정, 삭제

동기화: 단건 조회, 단순 이동

ajax일때 흐름도

 

 

MEM 테이블 ajax로 변경(실습)

이렇게 폴더, 파일 만듬

 

 

전체 코드

testa/T/list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판</title>
<!-- Common CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/cmn.css" />
<!-- Popup CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/popup.css" />
<style type="text/css">
#searchTxt{
width: 160px;
height: 30px; 
padding: 0px 2px;
text-indent: 5px;
vertical-align: middle;
border: 1px solid #d7d7d7; 
outline-color: #70adf9;
box-sizing: border-box;
}
.search_area{
	width: 800px;
	text-align: right;
	margin: 0 auto;
}
.board_area{
	width: 800px;
	margin: 0 auto;
}

</style>
<script type="text/javascript" src="resources/script/jquery/jquery-1.12.4.min.js"></script>
<script type="text/javascript" 
		src="resources/script/common/popup.js"></script>
<script type="text/javascript">
$(document).ready(function () {
	if("${params.searchGbn}" != ""){
		$("#searchGbn").val("${param.searchGbn}");
	} else {
		$("#oldGbn").val("0");
	}
	
	//목록 조회
	reloadList();
	
	//검색버튼
	$("#searchBtn").on("click", function () {
		$("#page").val("1");
		// 이동을 안하다보니 문제가 기존검색값 셋팅을 안해줌
		// 그래서  신규 상태 적용
		$("#oldGbn").val($("#searchGbn").val());
		$("#oldTxt").val($("#searchTxt").val());
		
		
		// 데이터만 가져와서 다시 그려줌, 화면 이동 없음
		reloadList();
	});
	
	//페이징 버튼
	$(".paging_area").on("click", "span", function () {
		// 기존 검색상태 유지
		$("#searchGbn").val($("#oldGbn").val());
		$("#searchTxt").val($("#oldTxt").val());
			
		
		$("#page").val($(this).attr("page"));
		
		reloadList();
	})
	
	// 등록버튼
	$("#insertBtn").on("click", function () {
		// 기존 검색상태 유지
		$("#searchGbn").val($("#oldGbn").val());
		$("#searchTxt").val($("#oldTxt").val());
		
		$("#actionForm").attr("action", "ATInsert");
		$("#actionForm").submit();
	})
	
	$("tbody").on("click", "tr", function () {
		$("#no").val($(this).attr("no"));
		
		$("#searchGbn").val($("#oldGbn").val());
		$("#searchTxt").val($("#oldTxt").val());
		
		$("#actionForm").attr("action", "ATDetail");
		$("#actionForm").submit();
	})
});

// 목록 조회 호출, ajax불러오기
function reloadList() {
	var params = $("#actionForm").serialize();
	
	$.ajax({
		url : "ATListAjax", //경로
		type : "POST", // 전송방식(GET: 주소형태, POST : 주소 헤더 형태)
		dataType: "json", // 데이터 형태
		data: params, // 보낼데이터
		success : function(res) { //성공했을 때 결과를 res에 받고 함수 실행
			console.log(res); // 콘솔에  pd랑 list 값이 보임
			drawList(res.list);
			drawPaging(res.pd);
		},
		error : function(request, status, error) { // 실패했을 때 함수실행
			console.log(request.responseText); // 실패 상세 태역
		}
	});
	
}

function drawList(list) {
	var html = "";
	
	// list에는 map이 들어있으니까 하나씩 꺼내오겠다
	for(var data of list){
		html += "<tr no=\"" + data.NO + "\">";
		html += "<td>" + data.NO + "</td>";
		html += "<td>" + data.TITLE + "</td>";
		html += "<td>" + data.MEM_NM + "</td>";
		html += "<td>" + data.DT + "</td>";
		html += "<td>" + data.HIT + "</td>";
		html += "</tr>";
	}   
	
	$("tbody").html(html);
}

function drawPaging(pd) {
	var html = "";
	
	html += "<span class=\"page_btn page_first\" page=\"1\">처음</span>";
	// 이전
	if($("#page").val() == "1"){
		html += "<span class=\"page_btn page_prev\" page=\"1\">이전</span>";
	} else{
		// 문자열을 숫자로 바꾸기위해 *1
		html += "<span class=\"page_btn page_prev\" page=\"" + ($("#page").val() *1 - 1) + "\">이전</span>";
	}
	
	for(var i = pd.startP; i <= pd.endP; i++){
		if($("#page").val() * 1 == i){ // 현재 페이지
			html += "<span class=\"page_btn_on\" page=\"" + i + "\">" + i + "</span>";
		} else { // 다른 페이지
			html += "<span class=\"page_btn\" page=\"" + i + "\">" + i + "</span>";
		}
	}
	
	if($("#page").val() *1 == pd.endP){ // 현재페이지가 마지막 페이지라면
		html += "<span class=\"page_btn page_next\" page=\"" +pd.maxP+ "\">다음</span>";
	} else {
		html += "<span class=\"page_btn page_next\" page=\"" + ($("#page").val() *1 + 1) + "\">다음</span>";
	}
	
	html += "<span class=\"page_btn page_last\" page=\"" +pd.maxP+ "\">마지막</span>";
	
	$(".paging_area").html(html);
                                                                     
}
</script>		
</head>
<body>
<c:import url="/testAHeader"></c:import>
<hr/>
<!-- 페이징 때 기존 검색 내용 유지용 -->
<input type="hidden" id="oldGbn" value="${param.searchGbn}"/>
<input type="hidden" id="oldTxt" value="${param.searchTxt}"/>

<!-- 데이터 후 처리해서 로딩이 빨라 -->
<div class="search_area">
	<!--  method="post"는 나중에 쓸 예정, no 보낼때 -->
	<form action="#" id="actionForm" method="post">
	<input type="hidden" name="no" id="no" />
		<input type="hidden" name="page" id="page" value="${page}" />
		<select name="searchGbn" id="searchGbn">
			<option value="0">제목</option>
			<option value="1">작성자</option>
		</select>
		<input type="text" name="searchTxt" id="searchTxt" value="${param.searchTxt}" />
		<div class="cmn_btn_ml" id="searchBtn">검색</div>
		<c:if test="${!empty sMemNo}">
			<div class="cmn_btn_ml" id="insertBtn">등록</div>
		</c:if>
	</form>
</div>
<div class="board_area">
<table class="board_table">
	<colgroup>
		<col width="100" />
		<col width="400" />
		<col width="100" />
		<col width="100" />
		<col width="100" />
	</colgroup>
	<thead>
		<tr>
			<th>번호</th>
			<th>제목</th>
			<th>작성자</th>
			<th>작성일</th>
			<th>조회수</th>
		</tr>
	</thead>
	<tbody></tbody>
</table>
<div class="paging_area"></div>
</div>
</body>
</html>

testa/T/insert.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>글쓰기</title>
<!-- Common CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/cmn.css" />
<!-- Popup CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/popup.css" />
<style type="text/css">
.wrap{
	width: 800px;
	margin: 0 auto;
}


</style>
<script type="text/javascript" src="resources/script/jquery/jquery-1.12.4.min.js"></script>
<script type="text/javascript" 
		src="resources/script/common/popup.js"></script>
<!-- CKEditor -->
<!-- 제이쿼리 뒤에 나와야함, 제이쿼리 기반으로 동작하기 때문에 -->
<script type="text/javascript" src="resources/script/ckeditor/ckeditor.js"></script>
<script type="text/javascript">
$(document).ready(function () {
	// 에디터 연결
	// CKEDITOR.replace(아이디, 옵션)
	CKEDITOR.replace("con", {
		resize_enabled: false, // resize_enabled : 크기조절기능 활용여부
		language : "ko", // 사용언어
		enterMode: "2", // 엔터키처리방법. 2번이면 <br/>
		width : "100%", // 숫자일경우 px, 문자열일경우 css크기
		height : 400
	});
	
	$("#listBtn").on("click", function () {
		$("#backForm").submit();
	});
	
	$("#insertBtn").on("click", function () {
		// CKEditor의 값 취득
		// CKEDITOR.instances[아이디] : CKEditor중 아이디가 같은 것을 찾겠다.
		//.getData() : 작성중인 내용을 취득하겠다.
		$("#con").val(CKEDITOR.instances['con'].getData());
		
		if($.trim($("#title").val()) == ""){
			makeAlert("알림","제목 입력하세요." , function () {
				$("#title").focus();
			})
		} else if($.trim($("#con").val()) == ""){
			makeAlert("알림","내용을 입력하세요." , function () {
				$("#con").focus();
			})
		} else {
			var params = $("#actionForm").serialize();
			
			$.ajax({
				url : "ATAction/insert", //restful api라는게 여기서 시작한다고?
				type : "POST", 
				dataType: "json", 
				data: params, 
				success : function(res) { 
					switch(res.msg){
					case "success" : 
						location.href ="ATList";
						break;
					case "fail" :
						makeAlert("알림" , "등록에 실패하였습니다.");
						break;
					case "error" :
						makeAlert("알림" , "등록 중 문제가 발생하였습니다.");
						break;
					}
				},
				error : function(request, status, error) { 
					console.log(request.responseText); 
				}
			});
			
		}
	});
});

</script>
</head>
<body>
<c:import url="/testAHeader"></c:import>
<form action="ATList" id="backForm" method="post">
	<input type="hidden" name="page" value="${param.page}" />
	<input type="hidden" name="searchGbn" value="${param.searchGbn}"/>
	<input type="hidden" name="searchTxt" value="${param.searchTxt}"/>
</form>
<!-- ajax쓰기 때문에 gbn 지움 -->
<div class="wrap">
	<form action="#" id="actionForm" method="post">
	<!--gbn : 구분, 혹은 flag
	구분: i - insert, u - update, d - delete  -->
	<!-- <input type="hidden" name="gbn" value="i"/> -->
		<table class="board_detail_table">
			<tr>
				<th>제목</th>
				<td><input type="text" name="title" id="title" /></td>
			</tr>
			<tr>
				<th>작성자</th>
				<td>${sMemNm}<input type="hidden" name="memNo" value="${sMemNo}" /><br/></td>
			</tr>
			<tr>
				<th colspan="2">내용</th>
			</tr>
			<tr>
				<th colspan="2"><textarea rows="10" cols="30" name="con" id="con"></textarea></th>
			</tr>
		</table>
	</form>
	<div class="cmn_btn_ml float_right_btn" id="listBtn">목록</div>
	<div class="cmn_btn_ml float_right_btn" id="insertBtn">등록</div>
</div>
</body>
</html>

testa/T/detail.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상세보기</title>
<!-- Common CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/cmn.css" />
<!-- Popup CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/popup.css" />
<style type="text/css">
.wrap{
	width: 800px;
	margin: 0 auto;
}
.con{
text-align: left; 
min-height: 400px;
}
</style>
<script type="text/javascript" 
		src="resources/script/jquery/jquery-1.12.4.min.js"></script>
<script type="text/javascript" 
src="resources/script/common/popup.js"></script>
<script type="text/javascript">
$(document).ready(function () {
	$("#listBtn").on("click", function() {
		$("#actionForm").attr("action","ATList"); 
		$("#actionForm").submit();
	});
	
	// ajax사용 예정
	$("#deleteBtn").on("click", function () {
		  makePopup({
		         title : "알림",
		         contents : "삭제하시겠습니까?",
		         // draggable : true,
		         buttons : [{
		            name : "삭제",
		            func:function() {
		            	var params = $("#actionForm").serialize();
		    			
		    			$.ajax({
		    				url : "ATAction/delete", //restful api라는게 여기서 시작한다고?
		    				type : "POST", 
		    				dataType: "json", 
		    				data: params, 
		    				success : function(res) { 
		    					switch(res.msg){
		    					case "success" : 
		    						location.href ="ATList";
		    						break;
		    					case "fail" :
		    						makeAlert("알림" , "삭제에 실패하였습니다.");
		    						break;
		    					case "error" :
		    						makeAlert("알림" , "삭제 중 문제가 발생하였습니다.");
		    						break;
		    					}
		    				},
		    				error : function(request, status, error) { 
		    					console.log(request.responseText); 
		    				}
		    			});
		            }
		         }, {
		            name : "취소"
		    }]
		});
	});
	
	$("#updateBtn").on("click", function () {
		$("#actionForm").attr("action","ATUpdate");
		$("#actionForm").submit();
	});
});

</script>
</head>
<body>
<c:import url="/testAHeader"></c:import>
<form action="#" id="actionForm" method="post">
	<input type="hidden" name="gbn" value="d"> <!-- selRes는 gbn을 받게 되어있어서 값을 추가해줘야함 -->
	<input type="hidden" name="no" value="${data.NO}">
	<input type="hidden" name="page" value="${param.page}" /> <!-- 전 화면에서 넘어온 페이지 정보 -->
		<!-- 전 화면에서 넘어온 검색 정보 -->
	<input type="hidden" name="searchGbn" value="${param.searchGbn}"/>
	<input type="hidden" name="searchTxt" value="${param.searchTxt}"/>
</form>
<div class="wrap">
<table class="board_detail_table">
	<tr>
		<th>번호</th>
		<td>${data.NO}</td>
	</tr>
	<tr>
		<th>제목</th>
		<td>${data.TITLE}</td>
	</tr>
	<tr>
		<th>작성자</th>
		<td>${data.MEM_NM}</td>
	</tr>
	<tr>
		<th>조회수</th>
		<td> ${data.HIT}</td>
	</tr>
	<tr>
		<th>작성일</th>
		<td> ${data.DT}</td>
	</tr>
	<tr>
		<th colspan="2">내용</th>
	</tr>
	<tr>
		<td class="con" colspan="2">${data.CON}</td>
	</tr>
</table>
	<div class="cmn_btn_ml float_right_btn" id="listBtn">목록</div>
	<c:if test="${sMemNo eq data.MEM_NO}">
		<div class="cmn_btn_ml float_right_btn" id="deleteBtn">삭제</div>
		<div class="cmn_btn_ml float_right_btn" id="updateBtn">수정</div>
	</c:if>
</div>
</body>

testa/T/update.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>글수정</title>
<!-- Common CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/cmn.css" />
<!-- Popup CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/popup.css" />
<style type="text/css">
.wrap{
	width: 800px;
	margin: 0 auto;
}


</style>
<script type="text/javascript" src="resources/script/jquery/jquery-1.12.4.min.js"></script>
<script type="text/javascript" 
		src="resources/script/common/popup.js"></script>
<!-- CKEditor -->
<!-- 제이쿼리 뒤에 나와야함, 제이쿼리 기반으로 동작하기 때문에 -->
<script type="text/javascript" src="resources/script/ckeditor/ckeditor.js"></script>
<script type="text/javascript">
$(document).ready(function () {
	// 에디터 연결
	// CKEDITOR.replace(아이디, 옵션)
	CKEDITOR.replace("con", {
		resize_enabled: false, // resize_enabled : 크기조절기능 활용여부
		language : "ko", // 사용언어
		enterMode: "2", // 엔터키처리방법. 2번이면 <br/>
		width : "100%", // 숫자일경우 px, 문자열일경우 css크기
		height : 400
	});
	
	$("#cancelBtn").on("click", function () {
		$("#backForm").submit();
	});
	
	$("#updateBtn").on("click", function () {
		// CKEditor의 값 취득
		// CKEDITOR.instances[아이디] : CKEditor중 아이디가 같은 것을 찾겠다.
		//.getData() : 작성중인 내용을 취득하겠다.
		$("#con").val(CKEDITOR.instances['con'].getData());
		
		if($.trim($("#title").val()) == ""){
			makeAlert("알림","제목 입력하세요." , function () {
				$("#title").focus();
			})
		} else if($.trim($("#con").val()) == ""){
			makeAlert("알림","내용을 입력하세요." , function () {
				$("#con").focus();
			})
		} else {
			var params = $("#actionForm").serialize();
			
			$.ajax({
				url : "ATAction/update", //restful api라는게 여기서 시작한다고?
				type : "POST", 
				dataType: "json", 
				data: params, 
				success : function(res) { 
					switch(res.msg){
					case "success" : 
						$("#backForm").submit();
						break;
					case "fail" :
						makeAlert("알림" , "수정에 실패하였습니다.");
						break;
					case "error" :
						makeAlert("알림" , "수정 중 문제가 발생하였습니다.");
						break;
					}
				},
				error : function(request, status, error) { 
					console.log(request.responseText); 
				}
			});
			
		}
	});
});

</script>
</head>
<body>
<c:import url="/testAHeader"></c:import>
<form action="ATDetail" id="backForm" method="post">
	<input type="hidden" name="no" value="${data.NO}" />
	<input type="hidden" name="page" value="${param.page}" />
	<input type="hidden" name="searchGbn" value="${param.searchGbn}"/>
	<input type="hidden" name="searchTxt" value="${param.searchTxt}"/>
</form>
<!-- ajax쓰기 때문에 gbn 지움 -->
<div class="wrap">
	<form action="#" id="actionForm" method="post">
	<input type="hidden" name="no" value="${data.NO}" />
		<table class="board_detail_table">
			<tr>
				<th>번호</th>
				<td>${data.NO}</td>
			</tr>
			<tr>
				<th>제목</th>
				<td><input type="text" name="title" id="title" value="${data.TITLE}"/></td>
			</tr>
			<tr>
				<th>작성자</th>
				<td>${sMemNm}</td>
			</tr>
			<tr>
				<th colspan="2">내용</th>
			</tr>
			<tr>
				<th colspan="2"><textarea rows="10" cols="30" name="con" id="con">${data.CON}</textarea></th>
			</tr>
		</table>
	</form>
	<div class="cmn_btn_ml float_right_btn" id="cancelBtn">취소</div>
	<div class="cmn_btn_ml float_right_btn" id="updateBtn">수정</div>
</div>
</body>
</html>

 

ATController.java

package com.spring.sample.web.testa.Controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.spring.sample.common.service.IPagingService;
import com.spring.sample.web.testa.dao.IACDao;

@Controller
public class ATController {
	@Autowired
	public IACDao iACDao;

	@Autowired
	public IPagingService ips;

	@RequestMapping(value = "/ATList")
	public ModelAndView ATList(@RequestParam HashMap<String, String> params, ModelAndView mav) {

		// 비동기가 되면 일단 아무것도 처음에 셋팅 X,
		// 페이지만 셋팅
		int page = 1;

		if (params.get("page") != null && params.get("page") != "") {
			page = Integer.parseInt(params.get("page"));
		}

		mav.addObject("page", page);
		mav.setViewName("testa/T/list");

		return mav;
	}

	@RequestMapping(value = "/ATListAjax", method = RequestMethod.POST, produces = "text/json;charset=UTF-8")
	@ResponseBody
	public String ATListAjax(@RequestParam HashMap<String, String> params) throws Throwable {
		ObjectMapper mapper = new ObjectMapper();
		Map<String, Object> model = new HashMap<String, Object>();

		// 페이지 받아오게 되어있음
		int cnt = iACDao.getInt("T.getTCnt", params);

		HashMap<String, Integer> pd = ips.getPagingData(Integer.parseInt(params.get("page")), cnt, 10, 5);

		params.put("start", Integer.toString(pd.get("start")));
		params.put("end", Integer.toString(pd.get("end")));

		List<HashMap<String, String>> list = iACDao.getList("T.getTList", params);

		model.put("list", list);
		model.put("pd", pd);

		return mapper.writeValueAsString(model);
	}

	@RequestMapping(value = "/ATInsert")
	public ModelAndView aTInsert(HttpSession session, ModelAndView mav) {
		if (session.getAttribute("sMemNm") != null && session.getAttribute("sMemNm") != "") {
			mav.setViewName("testa/T/insert");
		} else {
			mav.setViewName("redirect:testALogin");
		}
		return mav;
	}

	@RequestMapping(value = "/ATAction/{gbn}", method = RequestMethod.POST, produces = "text/json;charset=UTF-8")
	@ResponseBody
	public String ATAction(@PathVariable String gbn, @RequestParam HashMap<String, String> params) throws Throwable {
		ObjectMapper mapper = new ObjectMapper();
		Map<String, Object> model = new HashMap<String, Object>();

		int cnt = 0;

		try {
			switch (gbn) {
			case "insert":
				cnt = iACDao.insert("T.insertT", params);
				break;
			case "update":
				cnt = iACDao.update("T.updateT", params);
				break;
			case "delete":
				cnt = iACDao.update("T.deleteT", params);
				break;
			}

			if (cnt > 0) {
				model.put("msg", "success");
			} else {
				model.put("msg", "fail");
			}
		} catch (Exception e) {
			e.printStackTrace();
			model.put("msg", "error");
		}

		return mapper.writeValueAsString(model);
	}

	// 가져오고 변경되는게 없기 때문에 비동기 처리로 안되도 됨
	@RequestMapping(value = "/ATDetail")
	public ModelAndView aTDetail(@RequestParam HashMap<String, String> params, ModelAndView mav) throws Throwable {
		// 글번호 안 넘어왔을때 처리
		if (params.get("no") != null && params.get("no") != "") {
			// 조회수
			iACDao.update("T.updateTHit", params);
			HashMap<String, String> data = iACDao.getMap("T.getT", params);

			mav.addObject("data", data);

			mav.setViewName("testa/T/detail");
		} else {
			mav.setViewName("redirect:ATList");
		}

		return mav;
	}

	@RequestMapping(value = "/ATUpdate")
	public ModelAndView aTUpdate(@RequestParam HashMap<String, String> params, ModelAndView mav) throws Throwable {
		// 글번호 안 넘어왔을때 처리
		if (params.get("no") != null && params.get("no") != "") {
			HashMap<String, String> data = iACDao.getMap("T.getT", params);

			mav.addObject("data", data);

			mav.setViewName("testa/T/update");
		} else {
			mav.setViewName("redirect:ATList");
		}

		return mav;
	}

}

 

 

testa/Mem/list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판</title>
<!-- Common CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/cmn.css" />
<!-- Popup CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/popup.css" />
<style type="text/css">
#searchTxt{
width: 160px;
height: 30px; 
padding: 0px 2px;
text-indent: 5px;
vertical-align: middle;
border: 1px solid #d7d7d7; 
outline-color: #70adf9;
box-sizing: border-box;
}
.search_area{
	width: 800px;
	text-align: right;
	margin: 0 auto;
}
.board_area{
	width: 800px;
	margin: 0 auto;
}

</style>
<script type="text/javascript" src="resources/script/jquery/jquery-1.12.4.min.js"></script>
<script type="text/javascript" 
		src="resources/script/common/popup.js"></script>
<script type="text/javascript">
$(document).ready(function () {
	if("${params.searchGbn}" != ""){
		$("#searchGbn").val("${param.searchGbn}");
	} else {
		$("#oldGbn").val("0");
	}
	
	//목록 조회
	reloadList();
	
	$("#actionForm").on("keypress","input", function(event) {

		if(event.keyCode == 13){
			$("#searchBtn").click();
			return false;
		
		}
	})
	
	//검색버튼
	$("#searchBtn").on("click", function () {
		$("#page").val("1");
		// 이동을 안하다보니 문제가 기존검색값 셋팅을 안해줌
		// 그래서  신규 상태 적용
		$("#oldGbn").val($("#searchGbn").val());
		$("#oldTxt").val($("#searchTxt").val());
		
		
		// 데이터만 가져와서 다시 그려줌, 화면 이동 없음
		reloadList();
	});
	
	//페이징 버튼
	$(".paging_area").on("click", "span", function () {
		// 기존 검색상태 유지
		$("#searchGbn").val($("#oldGbn").val());
		$("#searchTxt").val($("#oldTxt").val());
			
		
		$("#page").val($(this).attr("page"));
		
		reloadList();
	})
	
	// 등록버튼
	$("#insertBtn").on("click", function () {
		// 기존 검색상태 유지
		$("#searchGbn").val($("#oldGbn").val());
		$("#searchTxt").val($("#oldTxt").val());
		
		$("#actionForm").attr("action", "AMInsert");
		$("#actionForm").submit();
	})
	
	$("tbody").on("click", "tr", function () {
		$("#no").val($(this).attr("no"));
		
		$("#searchGbn").val($("#oldGbn").val());
		$("#searchTxt").val($("#oldTxt").val());
		
		$("#actionForm").attr("action", "AMDetail");
		$("#actionForm").submit();
	})
});

// 목록 조회 호출, ajax불러오기
function reloadList() {
	var params = $("#actionForm").serialize();
	
	$.ajax({
		url : "AMListAjax", //경로
		type : "POST", // 전송방식(GET: 주소형태, POST : 주소 헤더 형태)
		dataType: "json", // 데이터 형태
		data: params, // 보낼데이터
		success : function(res) { //성공했을 때 결과를 res에 받고 함수 실행
			console.log(res); // 콘솔에  pd랑 list 값이 보임
			drawList(res.list);
			drawPaging(res.pd);
		},
		error : function(request, status, error) { // 실패했을 때 함수실행
			console.log(request.responseText); // 실패 상세 태역
		}
	});
	
}

function drawList(list) {
	var html = "";
	
	// list에는 map이 들어있으니까 하나씩 꺼내오겠다
	for(var data of list){
		html += "<tr no=\"" + data.MEM_NO + "\">";
		html += "<td>" + data.MEM_NO + "</td>";
		html += "<td>" + data.MEM_ID + "</td>";
		html += "<td>" + data.MEM_NM + "</td>";
		html += "<td>" + data.REG_DT + "</td>";
		html += "</tr>";
	}   
	
	$("tbody").html(html);
}

function drawPaging(pd) {
	var html = "";
	
	html += "<span class=\"page_btn page_first\" page=\"1\">처음</span>";
	// 이전
	if($("#page").val() == "1"){
		html += "<span class=\"page_btn page_prev\" page=\"1\">이전</span>";
	} else{
		// 문자열을 숫자로 바꾸기위해 *1
		html += "<span class=\"page_btn page_prev\" page=\"" + ($("#page").val() *1 - 1) + "\">이전</span>";
	}
	
	for(var i = pd.startP; i <= pd.endP; i++){
		if($("#page").val() * 1 == i){ // 현재 페이지
			html += "<span class=\"page_btn_on\" page=\"" + i + "\">" + i + "</span>";
		} else { // 다른 페이지
			html += "<span class=\"page_btn\" page=\"" + i + "\">" + i + "</span>";
		}
	}
	
	if($("#page").val() *1 == pd.endP){ // 현재페이지가 마지막 페이지라면
		html += "<span class=\"page_btn page_next\" page=\"" +pd.maxP+ "\">다음</span>";
	} else {
		html += "<span class=\"page_btn page_next\" page=\"" + ($("#page").val() *1 + 1) + "\">다음</span>";
	}
	
	html += "<span class=\"page_btn page_last\" page=\"" +pd.maxP+ "\">마지막</span>";
	
	$(".paging_area").html(html);
                                                                     
}





</script>
</head>
<body>
<input type="hidden" id="oldGbn" value="${param.searchGbn}"/>
<input type="hidden" id="oldTxt" value="${param.searchTxt}"/>
<div class="search_area">
	<!--  method="post"는 나중에 쓸 예정, no 보낼때 -->
	<form action="#" id="actionForm" method="post">
	<input type="hidden" name="no" id="no" />
		<input type="hidden" name="page" id="page" value="${page}" />
		<select name="searchGbn" id="searchGbn">
			<option value="0">아이디</option>
			<option value="1">이름</option>
		</select>
		<input type="text" name="searchTxt" id="searchTxt" value="${param.searchTxt}" />
		<div class="cmn_btn_ml" id="searchBtn">검색</div>
		<div class="cmn_btn_ml" id="insertBtn">등록</div>
	</form>
</div>
<div class="board_area">
<table class="board_table">
	<colgroup>
		<col width="100" />
		<col width="100" />
		<col width="100" />
		<col width="100" />
	</colgroup>
	<thead>
		<tr>
			<th>번호</th>
			<th>아이디</th>
			<th>이름</th>
			<th>등록일</th>
		</tr>
	</thead>
	<tbody></tbody>
</table>
<div class="paging_area"></div>
</div>


</body>
</html>

testa/Mem/insert.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>글쓰기</title>
<!-- Common CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/cmn.css" />
<!-- Popup CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/popup.css" />
<style type="text/css">
.wrap{
	width: 800px;
	margin: 0 auto;
}
</style>
<script type="text/javascript" src="resources/script/jquery/jquery-1.12.4.min.js"></script>
<script type="text/javascript" 
		src="resources/script/common/popup.js"></script>
<script type="text/javascript">
$(document).ready(function () {

	$("#listBtn").on("click", function () {
		$("#backForm").submit();
	});
	
	$("#insertBtn").on("click", function () {
		
		if($.trim($("#memId").val()) == ""){
			makeAlert("알림","아이디 입력하세요." , function () {
				$("#memId").focus();
			})
		} else if($.trim($("#memPw").val()) == ""){
			makeAlert("알림","비밀번호를 입력세요." , function () {
				$("#memPw").focus();
			})
		} else if($.trim($("#memPw").val()) != $.trim($("#repw").val())){
			makeAlert("알림","비밀번호가 일치하지 않습니다." , function () {
				$("#memPw").val("");
				$("#repw").val("");
				$("#memPw").focus();
			})
		} else if($.trim($("#memNm").val()) == ""){
			makeAlert("알림","이름을 입력하세요." , function () {
				$("#memNm").focus();
			})
		} else if($.trim($("#memBirth").val()) == ""){
			makeAlert("알림","생년월일을 입력하세요" , function () {
				$("#memBirth").focus();
			})
		} else {
			var params = $("#actionForm").serialize();
			
			$.ajax({
				url : "AMAction/insert", //restful api라는게 여기서 시작한다고?
				type : "POST", 
				dataType: "json", 
				data: params, 
				success : function(res) { 
					switch(res.msg){
					case "success" : 
						location.href ="AMList";
						break;
					case "fail" :
						makeAlert("알림" , "등록에 실패하였습니다.");
						break;
					case "error" :
						makeAlert("알림" , "등록 중 문제가 발생하였습니다.");
						break;
					}
				},
				error : function(request, status, error) { 
					console.log(request.responseText); 
				}
			});
			
		}
	});
});

</script>
</head>
<body>
	<form action="ATList" id="backForm" method="post">
	<input type="hidden" name="page" value="${param.page}" />
	<input type="hidden" name="searchGbn" value="${param.searchGbn}"/>
	<input type="hidden" name="searchTxt" value="${param.searchTxt}"/>
</form>
<!-- ajax쓰기 때문에 gbn 지움 -->
<div class="wrap">
	<form action="#" id="actionForm" method="post">
	<!--gbn : 구분, 혹은 flag
	구분: i - insert, u - update, d - delete  -->
	<!-- <input type="hidden" name="gbn" value="i"/> -->
		<table class="board_detail_table">
			<tr>
				<th>아이디</th>
				<td><input type="text" name="memId" id="memId" /></td>
			</tr>
			<tr>
				<th>비밀번호</th>
				<td><input type="password" name="memPw" id="memPw" /></td>
			</tr>
			<tr>
				<th>비밀번호 확인</th>
				<td><input type="password" id="repw" /></td>
			</tr>
			<tr>
				<th>이름</th>
				<td><input type="text" name="memNm" id="memNm" /></td>
			</tr>
			<tr>
				<th>생년월일</th>
				<td><input type="date" name="memBirth" id="memBirth" /></td>
			</tr>
		</table>
	</form>
	<div class="cmn_btn_ml float_right_btn" id="listBtn">목록</div>
	<div class="cmn_btn_ml float_right_btn" id="insertBtn">등록</div>
</div>
</body>
</html>

 

testa/Mem/detail.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상세보기</title>
<!-- Common CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/cmn.css" />
<!-- Popup CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/popup.css" />
<style type="text/css">
.wrap{
	width: 800px;
	margin: 0 auto;
}
</style>
<script type="text/javascript" 
		src="resources/script/jquery/jquery-1.12.4.min.js"></script>
<script type="text/javascript" 
src="resources/script/common/popup.js"></script>
<script type="text/javascript">
$(document).ready(function () {
	$("#listBtn").on("click", function() {
		$("#actionForm").attr("action","AMList"); 
		$("#actionForm").submit();
	});
	
	// ajax사용 예정
	$("#deleteBtn").on("click", function () {
		  makePopup({
		         title : "알림",
		         contents : "삭제하시겠습니까?",
		         // draggable : true,
		         buttons : [{
		            name : "삭제",
		            func:function() {
		            	var params = $("#actionForm").serialize();
		    			
		    			$.ajax({
		    				url : "AMAction/delete", //restful api라는게 여기서 시작한다고?
		    				type : "POST", 
		    				dataType: "json", 
		    				data: params, 
		    				success : function(res) { 
		    					switch(res.msg){
		    					case "success" : 
		    						location.href ="AMList";
		    						break;
		    					case "fail" :
		    						makeAlert("알림" , "삭제에 실패하였습니다.");
		    						break;
		    					case "error" :
		    						makeAlert("알림" , "삭제 중 문제가 발생하였습니다.");
		    						break;
		    					}
		    				},
		    				error : function(request, status, error) { 
		    					console.log(request.responseText); 
		    				}
		    			});
		            }
		         }, {
		            name : "취소"
		    }]
		});
	});
	
	$("#updateBtn").on("click", function () {
		$("#actionForm").attr("action","AMUpdate");
		$("#actionForm").submit();
	});
});
</script>
</head>
<body>
<form action="#" id="actionForm" method="post">
	<input type="hidden" name="no" value="${data.MEM_NO}">
	<input type="hidden" name="page" value="${param.page}" /> <!-- 전 화면에서 넘어온 페이지 정보 -->
		<!-- 전 화면에서 넘어온 검색 정보 -->
	<input type="hidden" name="searchGbn" value="${param.searchGbn}"/>
	<input type="hidden" name="searchTxt" value="${param.searchTxt}"/>
</form>
<div class="wrap">
<table class="board_detail_table">
	<tr>
		<th>번호</th>
		<td>${data.MEM_NO}</td>
	</tr>
	<tr>
		<th>아이디</th>
		<td>${data.MEM_ID}</td>
	</tr>
	<tr>
		<th>이름</th>
		<td>${data.MEM_NM}</td>
	</tr>
	<tr>
		<th>생년월일</th>
		<td>${data.MEM_BIRTH}</td>
	</tr>
	<tr>
		<th>등록일</th>
		<td>${data.REG_DT}</td>
	</tr>

</table>
	<div class="cmn_btn_ml float_right_btn" id="listBtn">목록</div>
	<div class="cmn_btn_ml float_right_btn" id="deleteBtn">삭제</div>
	<div class="cmn_btn_ml float_right_btn" id="updateBtn">수정</div>
</div>
</body>
</html>

testa/Mem/update.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>글수정</title>
<!-- Common CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/cmn.css" />
<!-- Popup CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/common/popup.css" />
<style type="text/css">
.wrap{
	width: 800px;
	margin: 0 auto;
}

</style>
<script type="text/javascript" src="resources/script/jquery/jquery-1.12.4.min.js"></script>
<script type="text/javascript" 
		src="resources/script/common/popup.js"></script>
<script type="text/javascript">
$(document).ready(function () {
	
	$("#cancelBtn").on("click", function () {
		$("#backForm").submit();
	});
	
	$("#updateBtn").on("click", function () {
		
		// $.trim(값) : 값 앞 뒤 공백제거	
		if($.trim($("#memId").val()) == ""){
			alert("아이디 입력하세요");
			$("#memId").focus();
		}  else if($.trim($("#memNm").val()) == ""){
			alert("이름을 입력하세요");
			$("#memNm").focus();
		} else if($.trim($("#memPw").val()) !="" // 이 부분이 업데이트에 추가됨 
				&& $.trim($("#memPw").val()) != $.trim($("#repw").val())){
			alert("비밀번호가 일치하지 않습니다.");
			$("#memPw").val("");
			$("#repw").val("");
			$("#memPw").focus();
		} else if($.trim($("#memBirth").val()) == ""){
			alert("생년월일을 입력하세요");
			$("#memBirth").focus();
		} else {
			var params = $("#actionForm").serialize();
			
			$.ajax({
				url : "AMAction/update", //restful api라는게 여기서 시작한다고?
				type : "POST", 
				dataType: "json", 
				data: params, 
				success : function(res) { 
					switch(res.msg){
					case "success" : 
						$("#backForm").submit();
						break;
					case "fail" :
						makeAlert("알림" , "수정에 실패하였습니다.");
						break;
					case "error" :
						makeAlert("알림" , "수정 중 문제가 발생하였습니다.");
						break;
					}
				},
				error : function(request, status, error) { 
					console.log(request.responseText); 
				}
			});
			
		}
	});
});


</script>
</head>
<body>
<form action="AMDetail" id="backForm" method="post">
	<input type="hidden" name="no" value="${data.MEM_NO}" />
	<input type="hidden" name="page" value="${param.page}" />
	<input type="hidden" name="searchGbn" value="${param.searchGbn}"/>
	<input type="hidden" name="searchTxt" value="${param.searchTxt}"/>
</form>
<!-- ajax쓰기 때문에 gbn 지움 -->
<div class="wrap">
	<form action="#" id="actionForm" method="post">
	<input type="hidden" name="no" value="${data.MEM_NO}" />
		<table class="board_detail_table">
			<tr>
				<th>아이디</th>
				<td><input type="text" name="memId" id="memId" value="${data.MEM_ID}"/></td>
			</tr>
			<tr>
				<th>이름</th>
				<td><input type="text" name="memNm" id="memNm"  value="${data.MEM_NM}"/></td>
			</tr>
			<tr>
				<th>비밀번호</th>
				<td><input type="password" name="memPw" id="memPw"  value="${data.MEM_PW}"/></td>
			</tr>
			<tr>
				<th>비밀번호확인</th>
				<td><input type="password" id="repw" /></td>
			</tr>
			<tr>
				<th>생년월일</th>
				<td><input type="date" name="memBirth" id="memBirth" value="${data.MEM_BIRTH}"/></td>
			</tr>
		</table>
	</form>
	<div class="cmn_btn_ml float_right_btn" id="cancelBtn">취소</div>
	<div class="cmn_btn_ml float_right_btn" id="updateBtn">수정</div>
</div>
</body>
</html>

AMController.java

package com.spring.sample.web.testa.Controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.spring.sample.common.service.IPagingService;
import com.spring.sample.web.testa.dao.IACDao;

@Controller
public class AMController {
	@Autowired
	public IACDao iACDao;

	@Autowired
	public IPagingService ips;

	@RequestMapping(value = "/AMList")
	public ModelAndView AMList(@RequestParam HashMap<String, String> params, ModelAndView mav) {

		// 비동기가 되면 일단 아무것도 처음에 셋팅 X,
		// 페이지만 셋팅
		int page = 1;

		if (params.get("page") != null && params.get("page") != "") {
			page = Integer.parseInt(params.get("page"));
		}

		mav.addObject("page", page);
		mav.setViewName("testa/Mem/list");

		return mav;
	}

	@RequestMapping(value = "/AMListAjax", method = RequestMethod.POST, produces = "text/json;charset=UTF-8")
	@ResponseBody
	public String AMListAjax(@RequestParam HashMap<String, String> params) throws Throwable {
		ObjectMapper mapper = new ObjectMapper();
		Map<String, Object> model = new HashMap<String, Object>();

		// 페이지 받아오게 되어있음
		int cnt = iACDao.getInt("mem.getMemCnt", params);

		HashMap<String, Integer> pd = ips.getPagingData(Integer.parseInt(params.get("page")), cnt, 10, 5);

		params.put("start", Integer.toString(pd.get("start")));
		params.put("end", Integer.toString(pd.get("end")));

		List<HashMap<String, String>> list = iACDao.getList("mem.getMemList", params);

		model.put("list", list);
		model.put("pd", pd);

		return mapper.writeValueAsString(model);
	}

	@RequestMapping(value = "/AMInsert")
	public ModelAndView aTInsert(ModelAndView mav) {

		mav.setViewName("testa/Mem/insert");

		return mav;
	}

	@RequestMapping(value = "/AMAction/{gbn}", method = RequestMethod.POST, produces = "text/json;charset=UTF-8")
	@ResponseBody
	public String AMAction(@PathVariable String gbn, @RequestParam HashMap<String, String> params) throws Throwable {
		ObjectMapper mapper = new ObjectMapper();
		Map<String, Object> model = new HashMap<String, Object>();

		int cnt = 0;

		try {
			switch (gbn) {
			case "insert":
				cnt = iACDao.insert("mem.insertMem", params);
				break;
			case "update":
				cnt = iACDao.update("mem.updateMem", params);
				break;
			case "delete":
				cnt = iACDao.update("mem.deleteMem", params);
				break;
			}

			if (cnt > 0) {
				model.put("msg", "success");
			} else {
				model.put("msg", "fail");
			}
		} catch (Exception e) {
			e.printStackTrace();
			model.put("msg", "error");
		}

		return mapper.writeValueAsString(model);
	}

	// 가져오고 변경되는게 없기 때문에 비동기 처리로 안되도 됨
	@RequestMapping(value = "/AMDetail")
	public ModelAndView AMDetail(@RequestParam HashMap<String, String> params, ModelAndView mav) throws Throwable {
		// 글번호 안 넘어왔을때 처리
		if (params.get("no") != null && params.get("no") != "") {

			HashMap<String, String> data = iACDao.getMap("mem.getMem", params);

			mav.addObject("data", data);

			mav.setViewName("testa/Mem/detail");
		} else {
			mav.setViewName("redirect:AMList");
		}

		return mav;
	}

	@RequestMapping(value = "/AMUpdate")
	public ModelAndView aTUpdate(@RequestParam HashMap<String, String> params, ModelAndView mav) throws Throwable {
		// 글번호 안 넘어왔을때 처리
		if (params.get("no") != null && params.get("no") != "") {
			HashMap<String, String> data = iACDao.getMap("mem.getMem", params);

			mav.addObject("data", data);

			mav.setViewName("testa/Mem/update");
		} else {
			mav.setViewName("redirect:AMList");
		}

		return mav;
	}

}

 

 

사용했던 sql, 기존꺼 활용

T_SQL.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="T">
	<select id="getTCnt" resultType="Integer" parameterType="hashmap">
		SELECT COUNT(*) AS CNT
		FROM TBOARD T INNER JOIN MEM M ON T.MEM_NO = M.MEM_NO
		AND M.DEL = 1
		WHERE T.DEL = 1
		<if test="searchTxt != null and searchTxt !=''">
			<choose>
				<when test="searchGbn eq 0">
					AND T.TITLE LIKE '%' || #{searchTxt} || '%'
				</when>
				<when test="searchGbn eq 1">
					AND M.MEM_NM LIKE '%' ||  #{searchTxt} || '%'
				</when>
			</choose>
		</if>
	</select>
	
	<select id="getTList" resultType="hashmap" parameterType="hashmap">
		SELECT T.NO, T.TITLE, T.MEM_NM, T.HIT, T.DT
		FROM(
		SELECT T.NO, T.TITLE, M.MEM_NM, T.HIT,
		CASE WHEN TO_CHAR(DT,'YY.MM.DD') = TO_CHAR(SYSDATE, 'YY.MM.DD')
		        THEN TO_CHAR(DT, 'HH24:MI')
		        ELSE TO_CHAR(DT, 'YY.MM.DD')
		        END AS DT,
		        ROW_NUMBER() OVER(ORDER BY T.NO DESC) AS RNUM
				FROM TBOARD T INNER JOIN MEM M ON T.MEM_NO = M.MEM_NO
				AND M.DEL = 1
		WHERE T.DEL = 1
		<if test="searchTxt != null and searchTxt !=''">
			<choose>
				<when test="searchGbn eq 0">
					AND T.TITLE LIKE '%' || #{searchTxt} || '%'
				</when>
				<when test="searchGbn eq 1">
					AND M.MEM_NM LIKE '%' ||  #{searchTxt} || '%'
				</when>
			</choose>
		</if>) T
		WHERE T.RNUM BETWEEN #{start} AND #{end}
	</select>
	
	<insert id="insertT" parameterType="hashmap">
		INSERT INTO TBOARD(NO, TITLE, MEM_NO, CON)
		VALUES (TBOARD_SEQ.NEXTVAL, #{title} , #{memNo}, #{con})
	</insert>
	 
	<select id="getT" parameterType="hashmap"  resultType="hashmap">
		SELECT T.NO, T.TITLE, M.MEM_NO, M.MEM_NM, T.CON, T.HIT,
	    TO_CHAR(T.DT, 'YYYY-MM-DD') AS DT
		FROM TBOARD T INNER JOIN MEM M ON T.MEM_NO = M.MEM_NO
		AND M.DEL = 1
		WHERE T.DEL = 1
		AND T.NO = #{no}
	</select>
	
	<update id="updateTHit" parameterType="hashmap">
		UPDATE TBOARD SET HIT = HIT + 1
		WHERE NO = #{no}
	</update>
	
	<update id="deleteT"  parameterType="hashmap">
		UPDATE TBOARD SET DEL = 0
		WHERE NO = #{no}
	</update>
	
	<update id="updateT"  parameterType="hashmap">		
		UPDATE TBOARD SET TITLE = #{title},
		CON = #{con}
		WHERE NO = #{no}
	</update>
</mapper>

 

Mem_SQL.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace : 클래스와 동일, 이 파일의 대표명 -->
<mapper namespace="mem">
	<!-- select : 조회 
		id: 구분자, 메소드명과 동일
		resultType : 조회 결과 중 한줄에 대한 자료 형태를 지정
		hashmap: mybatis-config.xml에서 별칭 지정해놔서 줄여쓸수있는거임
		쿼리 삽입시 주의사항: ;이 있는경우 문제가 발생한다. 이유는 해당 쿼리 실행시 자동으로 추가되기 때문
	-->
	<select id="getMemList" resultType="hashmap" parameterType="hashmap">
		SELECT S.MEM_NO, S.MEM_ID, S.MEM_NM, S.REG_DT
		FROM (SELECT MEM_NO, MEM_ID, MEM_NM, TO_CHAR(REG_DT,'YYYY-MM-DD') AS REG_DT,
       		  ROW_NUMBER() OVER(ORDER BY REG_DT DESC, MEM_NO DESC) AS RNK
			  FROM MEM
			  WHERE DEL = 1
			<if test="searchTxt != null and searchTxt != ''"> <!-- 검색어가 있다면 -->
				<choose>
					<when test="searchGbn == 0"> <!-- 아이디 -->
						AND MEM_ID LIKE '%' || #{searchTxt} || '%'
					</when>
					<when test="searchGbn == 1"> <!-- 이름 -->
						AND MEM_NM LIKE '%' || #{searchTxt} || '%'
					</when>
				</choose>
			</if>
             ) S
		WHERE S.RNK BETWEEN #{start} AND #{end}
	</select>
	
	<!-- 
		parameterType : 실행시 받는 값 
		#{키} : 헤당위치에 문자열로 키에 해당하는 값을 넣어준다
		ex) no에 3이 들어있는 경우
		WHERE SELL_NO = #{no}
		=> WHERE SELL_NO = '3' // 문자열이기 때문에  ' '이 들어감
		parameterType dao받는값, resultType값이 db실행결과
	-->
	<select id="getMem" resultType="hashmap" parameterType="hashmap">
		SELECT MEM_NO, MEM_ID, MEM_NM, TO_CHAR(MEM_BIRTH,'YYYY-MM-DD') AS MEM_BIRTH, TO_CHAR(REG_DT,'YYYY-MM-DD') AS REG_DT
		FROM MEM
		WHERE MEM_NO = #{no}
	</select>
	
	<!-- insert는 resultType 이 없음 -->
	<insert id="insertMem" parameterType="hashmap">
		INSERT INTO MEM(MEM_NO, MEM_ID, MEM_PW, MEM_NM, MEM_BIRTH)
		VALUES(MEM_SEQ.NEXTVAL, #{memId}, #{memPw}, #{memNm}, #{memBirth})
	</insert>
	
	
	<update id="deleteMem" parameterType="hashmap">
		UPDATE MEM SET DEL = 0
		WHERE MEM_NO = #{no}
	</update>
	
	<update id="updateMem" parameterType="hashmap">
		UPDATE MEM SET MEM_ID = #{memId},
                MEM_NM = #{memNm},
                <if test="memPw != null and memPw != ''">
                	 MEM_PW = #{memPw},
                </if>
                MEM_BIRTH = #{memBirth}
       	WHERE MEM_NO = #{no}
	</update>
	
	<select id="getMemCnt" parameterType="hashmap" resultType="Integer">
		SELECT COUNT(*) AS CNT 
		FROM MEM
		WHERE DEL = 1
		<if test="searchTxt != null and searchTxt != ''"> <!-- 검색어가 있다면 -->
			<choose>
				<when test="searchGbn == 0"> <!-- 품목 -->
					AND MEM_ID LIKE '%' || #{searchTxt} || '%'
				</when>
				<when test="searchGbn == 1"> <!-- 수량 -->
					AND MEM_NM = #{searchTxt}
				</when>
			</choose>
		</if>
	</select>
	
	
</mapper>

 

 

 

 

 

궁금증

1. VO객체

스프링에서 ajax 사용 이유, 사용법 이렇게 구글링하면 VO라는 말을 많이 볼수있는데,

https://yulfsong.tistory.com/76

 

Ajax data를 Controller에서 받는 두 가지 방법 : Vo / Map

Ajax의 data를 Controller에서 받아야할 때가 자주 있는데 Vo를 만들어서 받는 방법이 있고 Map을 이용하는 방법이 있다. 1. Vo로 받는 방법 var memberId = $("#memberId").val(); var memberPass = $("#memberPa..

yulfsong.tistory.com

VO 객체가 bean이래

데이터 추가 삭제때마다 getter/ setter 만들어야하고, 변수전언해야해서 우리는 Map으로 하는거임

 

 

 

2. ajax 추가할때, Restful api에 대해

데이터만 가져옴, 화면을 못 그림, 대부분의 오픈 api가 이렇게 되어있음, 내일 다시 한데

샘플스프링에 데이터 있음

728x90