728x90
오늘의 시험 내역
테이블명....
기존에 SELL테이블이 있어서 SELL1로 했더니 깎였고,
그리고 controller에서 delete할때 delete써야 하는데 update로 씀...
다른 코드에서는 삭제를 실제삭제가 아니고 테이블에서 del을 내용을 바꿔서 테이블에서 안보이게 했던것 때문에
delete로 수정해야 하는데 깜박함
밑에 코드는 수정완료한거
PshController.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 PshController {
@Autowired
public IACDao iACDao;
@Autowired
public IPagingService ips;
@RequestMapping(value = "/ASELLList")
public ModelAndView ASELLlList(@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/pshSell/pshlist");
return mav;
}
@RequestMapping(value = "/ASELLListAjax", method = RequestMethod.POST, produces = "text/json;charset=UTF-8")
@ResponseBody
public String ASELLListAjax(@RequestParam HashMap<String, String> params) throws Throwable {
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> model = new HashMap<String, Object>();
// 페이지 받아오게 되어있음
int cnt = iACDao.getInt("sell.getSellCnt", 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("sell.getSellList", params);
model.put("list", list);
model.put("pd", pd);
System.out.println(params.toString());
return mapper.writeValueAsString(model);
}
@RequestMapping(value = "/ASELLInsert")
public ModelAndView aTInsert(ModelAndView mav) {
mav.setViewName("testa/pshSell/pshinsert");
return mav;
}
@RequestMapping(value = "/ASELLAction/{gbn}", method = RequestMethod.POST, produces = "text/json;charset=UTF-8")
@ResponseBody
public String ASELLAction(@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("sell.insertSell", params);
break;
case "update":
cnt = iACDao.update("sell.updateSell", params);
break;
case "delete":
cnt = iACDao.delete("sell.deleteSell", 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 = "/ASELLDetail")
public ModelAndView ASELLDetail(@RequestParam HashMap<String, String> params, ModelAndView mav) throws Throwable {
// 글번호 안 넘어왔을때 처리
if (params.get("no") != null && params.get("no") != "") {
HashMap<String, String> data = iACDao.getMap("sell.getSell", params);
mav.addObject("data", data);
mav.setViewName("testa/pshSell/pshdetail");
} else {
mav.setViewName("redirect:ASELLList");
}
return mav;
}
@RequestMapping(value = "/ASELLUpdate")
public ModelAndView sellUpdate(@RequestParam HashMap<String, String> params, ModelAndView mav) throws Throwable {
// 글번호 안 넘어왔을때 처리
if (params.get("no") != null && params.get("no") != "") {
HashMap<String, String> data = iACDao.getMap("sell.getSell", params);
mav.addObject("data", data);
mav.setViewName("testa/pshSell/pshupdate");
} else {
mav.setViewName("redirect:ASELLList");
}
return mav;
}
}
pshlist.jap
<%@ 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("${param.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", "ASELLInsert");
$("#actionForm").submit();
})
$("tbody").on("click", "tr", function () {
$("#no").val($(this).attr("no"));
$("#searchGbn").val($("#oldGbn").val());
$("#searchTxt").val($("#oldTxt").val());
$("#actionForm").attr("action", "ASELLDetail");
$("#actionForm").submit();
})
});
// 목록 조회 호출, ajax불러오기
function reloadList() {
var params = $("#actionForm").serialize();
$.ajax({
url : "ASELLListAjax", //경로
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.SELL_NO + "\">";
html += "<td>" + data.SELL_NO + "</td>";
html += "<td>" + data.ITEM_NAME + "</td>";
html += "<td>" + data.COUNT + "</td>";
html += "<td>" + data.SELL_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>
pshinsert.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($("#ItemName").val()) == ""){
makeAlert("알림","상품명 입력하세요." , function () {
$("#ItemName").focus();
})
} else if($.trim($("#Count").val()) == ""){
makeAlert("알림","판매량를 입력세요." , function () {
$("#Count").focus();
})
} else if($("#Count").val()*1 < 1){
makeAlert("알림","판매량은 1개 이상이여야합니다." , function () {
$("#Count").focus();
})
} else if($.trim($("#SellDt").val()) == ""){
makeAlert("알림","판매일자를 입력하세요" , function () {
$("#SellDt").focus();
})
} else {
var params = $("#actionForm").serialize();
$.ajax({
url : "ASELLAction/insert", //restful api라는게 여기서 시작한다고?
type : "POST",
dataType: "json",
data: params,
success : function(res) {
switch(res.msg){
case "success" :
location.href ="ASELLList";
break;
case "fail" :
makeAlert("알림" , "등록에 실패하였습니다.");
break;
case "error" :
makeAlert("알림" , "등록 중 문제가 발생하였습니다.");
break;
}
},
error : function(request, status, error) {
console.log(request.responseText);
}
});
}
});
});
</script>
</head>
<body>
<form action="ASELLList" 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>
<div class="wrap">
<form action="#" id="actionForm" method="post">
<table class="board_detail_table">
<tr>
<th>상품명</th>
<td>
<select name="ItemName" id="ItemName">
<option value="감자">감자</option>
<option value="고구마">고구마</option>
<option value="애호박">애호박</option>
<option value="호박">호박</option>
<option value="호박고구마">호박고구마</option>
</select>
</td>
</tr>
<tr>
<th>판매량</th>
<td><input type="number" name="Count" id="Count" value="0" /></td>
</tr>
<tr>
<th>판매일자</th>
<td><input type="date" name="SellDt" id="SellDt" /></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>
pshdetail.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","ASELLList");
$("#actionForm").submit();
});
// ajax사용 예정
$("#deleteBtn").on("click", function () {
makePopup({
title : "알림",
contents : "삭제하시겠습니까?",
// draggable : true,
buttons : [{
name : "삭제",
func:function() {
var params = $("#actionForm").serialize();
$.ajax({
url : "ASELLAction/delete", //restful api라는게 여기서 시작한다고?
type : "POST",
dataType: "json",
data: params,
success : function(res) {
switch(res.msg){
case "success" :
location.href ="ASELLList";
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","ASELLUpdate");
$("#actionForm").submit();
});
});
</script>
</head>
<body>
<form action="#" id="actionForm" method="post">
<input type="hidden" name="no" value="${data.SELL_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.SELL_NO}</td>
</tr>
<tr>
<th>상품명</th>
<td>${data.ITEM_NAME}</td>
</tr>
<tr>
<th>판매량</th>
<td>${data.COUNT}</td>
</tr>
<tr>
<th>판매일자</th>
<td>${data.SELL_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>
pshupdate.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 () {
// 기존값으로 셀렉트박스 선택 내용 변경
$("#ItemName").val("${data.ITEM_NAME}");
$("#cancelBtn").on("click", function () {
$("#backForm").submit();
});
$("#updateBtn").on("click", function () {
if($.trim($("#ItemName").val()) == ""){
makeAlert("알림","상품명 입력하세요." , function () {
$("#ItemName").focus();
})
} else if($.trim($("#Count").val()) == ""){
makeAlert("알림","판매량를 입력세요." , function () {
$("#Count").focus();
})
} else if($("#Count").val()*1 < 1){
makeAlert("알림","판매량은 1개 이상이여야합니다." , function () {
$("#Count").focus();
})
} else if($.trim($("#SellDt").val()) == ""){
makeAlert("알림","판매일자를 입력하세요" , function () {
$("#SellDt").focus();
})
} else {
var params = $("#actionForm").serialize();
$.ajax({
url : "ASELLAction/update",
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="ASELLDetail" id="backForm" method="post">
<input type="hidden" name="no" value="${data.SELL_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.SELL_NO}" />
<table class="board_detail_table">
<tr>
<th>상품명</th>
<td>
<select name="ItemName" id="ItemName">
<option value="감자">감자</option>
<option value="고구마">고구마</option>
<option value="애호박">애호박</option>
<option value="호박">호박</option>
<option value="호박고구마">호박고구마</option>
</select>
</td>
</tr>
<tr>
<th>판매량</th>
<td><input type="text" name="Count" id="Count" value="${data.COUNT}" /></td>
</tr>
<tr>
<th>판매일자</th>
<td><input type="date" name="SellDt" id="SellDt" value="${data.SELL_DT}"/></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>
pshSell.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="sell">
<!-- select : 조회
id: 구분자, 메소드명과 동일
resultType : 조회 결과 중 한줄에 대한 자료 형태를 지정
hashmap: mybatis-config.xml에서 별칭 지정해놔서 줄여쓸수있는거임
쿼리 삽입시 주의사항: ;이 있는경우 문제가 발생한다. 이유는 해당 쿼리 실행시 자동으로 추가되기 때문
-->
<select id="getSellList" resultType="hashmap" parameterType="hashmap">
SELECT S.SELL_NO, S.ITEM_NAME, S.COUNT, S.SELL_DT
FROM (SELECT SELL_NO, ITEM_NAME, COUNT, TO_CHAR(SELL_DT,'YYYY-MM-DD') AS SELL_DT,
ROW_NUMBER() OVER(ORDER BY SELL_DT DESC, SELL_NO DESC) AS RNK
FROM SELL1
WHERE 1 = 1
<if test="searchTxt != null and searchTxt != ''"> <!-- 검색어가 있다면 -->
<choose>
<when test="searchGbn == 0"> <!-- 품목 -->
AND ITEM_NAME LIKE '%' || #{searchTxt} || '%'
</when>
<when test="searchGbn == 1"> <!-- 수량 -->
AND COUNT = #{searchTxt}
</when>
</choose>
</if>
) S
WHERE S.RNK BETWEEN #{start} AND #{end}
</select>
<select id="getSell" resultType="hashmap" parameterType="hashmap">
SELECT SELL_NO, ITEM_NAME, COUNT, TO_CHAR(SELL_DT,'YYYY-MM-DD') AS SELL_DT
FROM SELL1
WHERE SELL_NO = #{no}
</select>
<insert id="insertSell" parameterType="hashmap">
INSERT INTO SELL1(SELL_NO, ITEM_NAME, COUNT, SELL_DT)
VALUES(SELL1_SEQ.NEXTVAL, #{ItemName}, #{Count}, #{SellDt})
</insert>
<delete id="deleteSell" parameterType="hashmap">
DELETE FROM SELL1
WHERE SELL_NO = #{no}
</delete>
<update id="updateSell" parameterType="hashmap">
UPDATE SELL1 SET ITEM_NAME = #{ItemName},
COUNT = #{Count},
SELL_DT = #{SellDt}
WHERE SELL_NO = #{no}
</update>
<select id="getSellCnt" parameterType="hashmap" resultType="Integer">
SELECT COUNT(*) AS CNT
FROM SELL1
WHERE 1 = 1
<if test="searchTxt != null and searchTxt != ''"> <!-- 검색어가 있다면 -->
<choose>
<when test="searchGbn == 0"> <!-- 상품명 -->
AND ITEM_NAME LIKE '%' || #{searchTxt} || '%'
</when>
<when test="searchGbn == 1"> <!-- 개수 -->
AND COUNT = #{searchTxt}
</when>
</choose>
</if>
</select>
</mapper>
내일 배울 내용
관계 쪼개기??
resolve 특정행위를 했을때 납치하는거??
금요일 배울 내용
카테고리 나누기
728x90
'TIL > academy' 카테고리의 다른 글
국비 TIL(Today I Learned) 20220901 갤러리 실습 (0) | 2022.09.01 |
---|---|
국비 TIL(Today I Learned) 20220825 AOP(Aspect Oriented Programming) : 관점지향 프로그래밍 (0) | 2022.08.25 |
국비 TIL(Today I Learned) 20220823 한줄 게시판(댓글) 만들기 (0) | 2022.08.23 |
국비 TIL(Today I Learned) 20220822 ajaxForm으로 파일 첨부, 다운받기 (0) | 2022.08.22 |
국비 TIL(Today I Learned) 20220818 스프링 ajax로 추가, 상세, 수정, 삭제, mem테이블 실습 (0) | 2022.08.18 |