학원/수업 기록

TBOARD 수정, CATE 생성(카테고리) 실습

60cod 2022. 8. 25. 10:54

TBOARD 수정

 

카테고리 번호 컬럼 추가

 

 

새 테이블 CATE 만들기

0번 자유게시판 추가

새 외래키 달아서 티보드와 연결

 

 

CATE 시퀀스 만들어줌

 

 

 

혼자 풀어본 거라.. 맞는진 모름 근데 일단 잘 굴러감

ACateController

더보기
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.IACateDao;

@Controller
public class ACateController {
	@Autowired
	public IACateDao iACateDao;
	
	@Autowired
	public IPagingService ips;
	
	@RequestMapping(value = "ACategory")
	public ModelAndView aob(ModelAndView mav) {
		mav.setViewName("testa/category/cate");
      
		return mav;
	}
	
	@RequestMapping(value = "/ACategoryList",
			method = RequestMethod.POST,
			produces = "text/json;charset=UTF-8")
		@ResponseBody
		public String ACategory (
				@RequestParam HashMap<String, String> params) throws Throwable {
		      ObjectMapper mapper = new ObjectMapper ();
		      
		      Map<String, Object> model = new HashMap<String, Object>();
		      
		      int cnt = iACateDao.getInt("C.getCCnt", 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 = iACateDao.getList("C.getCList", params);
				
		      model.put("list", list);
		      model.put("pd", pd);
				
		      return mapper.writeValueAsString(model);
		      
		   }
	
	@RequestMapping(value = "/ACAction/{gbn}",
	         method = RequestMethod.POST,
	         produces = "text/json;charset=UTF-8")
	   @ResponseBody
	   public String ACAction(
	         @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 = iACateDao.insert("C.insertC", params);
	            break;
	         case "update" : cnt = iACateDao.update("C.updateC", params);
	            break;
	         case "delete" : cnt = iACateDao.update("C.deleteC", 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);
	   }
}

 

IACateDao

더보기
package com.spring.sample.web.testa.dao;

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

public interface IACateDao {
	//이렇게 쌍으로 다님
	//숫자 취득
	public int getInt(String sql) throws Throwable; //값 안 받고 조회만
	public int getInt(String sql, HashMap<String, String> params) throws Throwable;
	
	//문자열 취득
	public String getString(String sql) throws Throwable;
	public String getString(String sql, HashMap<String, String> params) throws Throwable;
	
	//HashMap 취득
	public HashMap<String, String> getMap(String sql) throws Throwable;
	public HashMap<String, String> getMap(String sql, HashMap<String, String> params) throws Throwable;
	
	//문자열 취득
	public List<HashMap<String, String>> getList(String sql) throws Throwable;
	public List<HashMap<String, String>> getList(String sql, HashMap<String, String> params) throws Throwable;
	
	//등록
	public int insert(String sql) throws Throwable;
	public int insert(String sql, HashMap<String, String> params) throws Throwable;

	//수정
	public int update(String sql) throws Throwable;
	public int update(String sql, HashMap<String, String> params) throws Throwable;
	
	//삭제
	public int delete(String sql) throws Throwable;
	public int delete(String sql, HashMap<String, String> params) throws Throwable;
	
}

 

ACateDao

더보기
package com.spring.sample.web.testa.dao;

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

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class ACateDao implements IACateDao {
	@Autowired
	public SqlSession sqlSession;

	@Override
	public int getInt(String sql) throws Throwable {
		return sqlSession.selectOne(sql);
	}

	@Override
	public int getInt(String sql, HashMap<String, String> params) throws Throwable {
		return sqlSession.selectOne(sql, params);
	}

	@Override
	public String getString(String sql) throws Throwable {
		return sqlSession.selectOne(sql);
	}

	@Override
	public String getString(String sql, HashMap<String, String> params) throws Throwable {
		return sqlSession.selectOne(sql, params);
	}

	@Override
	public HashMap<String, String> getMap(String sql) throws Throwable {
		return sqlSession.selectOne(sql);
	}

	@Override
	public HashMap<String, String> getMap(String sql, HashMap<String, String> params) throws Throwable {
		return sqlSession.selectOne(sql, params);
	}

	@Override
	public List<HashMap<String, String>> getList(String sql) throws Throwable {
		return sqlSession.selectList(sql);
	}

	@Override
	public List<HashMap<String, String>> getList(String sql, HashMap<String, String> params) throws Throwable {
		return sqlSession.selectList(sql, params);
	}

	@Override
	public int insert(String sql) throws Throwable {
		return sqlSession.insert(sql);
	}

	@Override
	public int insert(String sql, HashMap<String, String> params) throws Throwable {
		return sqlSession.insert(sql, params);
	}

	@Override
	public int update(String sql) throws Throwable {
		return sqlSession.update(sql);
	}

	@Override
	public int update(String sql, HashMap<String, String> params) throws Throwable {
		return sqlSession.update(sql, params);
	}

	@Override
	public int delete(String sql) throws Throwable {
		return sqlSession.delete(sql);
	}

	@Override
	public int delete(String sql, HashMap<String, String> params) throws Throwable {
		return sqlSession.delete(sql, params);
	}
	
	

}

 

Cate_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="C">
	<select id="getCCnt" parameterType="hashmap"
		resultType="Integer">
		SELECT COUNT(*) AS CNT
		FROM CATE
		WHERE DEL = 1
		<if test="searchTxt != null and searchTxt != ''">
			<choose>
				<when test="searchGbn eq 0">
					AND CATE_NO = #{searchTxt}
				</when>
				<when test="searchGbn eq 1">
					AND CATE_NM LIKE '%' || #{searchTxt} || '%'
				</when>
			</choose>
		</if>
	</select>

	<select id="getCList" parameterType="hashmap"
		resultType="hashmap">
		SELECT C.CATE_NO, C.CATE_NM
		FROM(SELECT CATE_NO, CATE_NM,
					ROW_NUMBER() OVER(ORDER BY CATE_NO DESC) AS RNUM
			FROM CATE
			WHERE DEL = 1
			<if test="searchTxt != null and searchTxt != ''">
				<choose>
					<when test="searchGbn eq 0">
						AND CATE_NO = #{searchTxt}
					</when>
					<when test="searchGbn eq 1">
						AND CATE_NM LIKE '%' || #{searchTxt} || '%'
					</when>
				</choose>
			</if>) C
		WHERE C.RNUM BETWEEN #{start} AND #{end}
	</select>

	<insert id="insertC" parameterType="hashmap">
		INSERT INTO CATE (CATE_NO, CATE_NM)
		VALUES(CATE_SEQ.NEXTVAL, #{con})
	</insert>

	<select id="getC" parameterType="hashmap" resultType="hashmap">
		SELECT CATE_NO, CATE_NM
		FROM CATE 
		WHERE DEL = 1
		AND CATE_NO = #{no}
	</select>

	<update id="deleteC" parameterType="hashmap">
		UPDATE CATE SET DEL = 0
		WHERE CATE_NO = #{no}
	</update>

	<update id="updateC" parameterType="hashmap">
		UPDATE CATE SET CATE_NM = #{con}
		WHERE CATE_NO = #{no}
	</update>
</mapper>

 

testa - category - category.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 : 161px;
   height: 28px;
   padding: 0px 2px;
   text-indent: 5px;
   vertical-align: middle;
   border : 1px solid #d7d7d7;
   outline-color : #70adf9;
}
.search_area {
   width : 800px;
   text-align: right;
   margin : 0 auto;
}
.board_area {
   width : 800px;
   margin : 0 auto;
}
.wrap {
   width : 800px;
   margin : 0 auto;
}
.mtb {
   margin : 5px 0px;
}
.login {
   vertical-align: baseline;
}
.con {
   width : calc(100% - 22px);
   height : 60px;
   border : 1px soild #d7d7d7;
   resize : none;
   padding : 10px;
}
.update {
   display : none;
}
.con_td {
   font-size : 0;
}
.paging_area {
   display: block;
   position: relative;
   left : 0;
   margin-bottom : 10px;
}
.search_area {
   text-align : center;
}

body {
	overflow: auto;
}
</style>
<!-- JQuery -->
<script type="text/javascript"
      src="resources/script/jquery/jquery-1.12.4.min.js"></script>
<!-- Popup JS -->
<script type="text/javascript" 
         src="resources/script/common/popup.js"></script>
<!-- Slimscroll JS -->
<script type="text/javascript" 
         src="resources/script/jquery/jquery.slimscroll.js"></script>
<script type="text/javascript">
$(document).ready(function() {
	reloadList();
   
   $("#insertBtn").on("click", function() {
      if($.trim($("#con").val()) == "") {
         makeAlert("알림", "내용을 입력하세요.", function() {
            $("#con").focus();
         });
      } else {
         action("insert");
      }
   });
	//페이징 클릭 시
	$(".paging_area").on("click", "span", function() {
		$("#page").val($(this).attr("page"));
		//기존 값 유지
		$("#searchGbn").val($("#oldGbn").val());
		$("#searchTxt").val($("#oldTxt").val());
	
		reloadList();
	});
	// 검색 버튼 클릭 시
	// 기존 것 넘겨줘도 됨
	$("#searchBtn").on("click", function() {
		$("#page").val("1");
		//기존 값 새 값으로 변경
		$("#oldGbn").val($("#searchGbn").val());
		$("#oldTxt").val($("#searchTxt").val());
	
		reloadList();
	});
	// 목록의 삭제 버튼 클릭시
	$("tbody").on("click", ".delete_btn", function() {
		// 삭제  버튼 눌렀을 때 그 글의 번호를 가져가려면 그 버튼을 가진 td의 tr까지 올라가야 함
		// 두 단계 올라가야 하고 길어서 변수에 담기
		var no = $(this).parent().parent().attr("no");
		// 팝업
		makePopup({
			title : "알림",
			contents : "삭제 하시겠습니까?",
			buttons : [{
				name : "삭제",
				func:function() {
					// 삭제 전에 번호 가져가야 함
					$("#no").val(no);
					action("delete");
					closePopup(); // 제일 위의 팝업 닫기
				}
			}, {
				name : "취소"
			}]
		});
	});
	// 목록의 수정 버튼 클릭 시
	$("tbody").on("click", ".update_btn", function() {
		var no = $(this).parent().parent().attr("no");
		$("#no").val(no);
		
		// eq(인덱스 번호) : 자식들 중 인덱스 몇 번째인지 찾아서 취득
		// 댓글 입력 칸에 수정하려고 클릭한 댓글 내용이 들어옴
		var con = $(this).parent().parent().children().eq(1).html();
		// 수정 내용 넣기 전 <>변환
		con = con.replace(/&lt;/gi, "<");
		con = con.replace(/&gt;/gi, ">");
		
		$("#con").val(con);
		
		// 등록 버튼 감추기 + 수정,취소 버튼 나타나게 하기
		$(".insert").hide();
		$(".update").show();
		
		//작성 영역에 포커스
		$("#con").focus();
	});
	// 수정 영역의 취소 버튼 클릭 시
	// 취소 버튼은 없었던 일로 하면 됨.
	// 취소 버튼은 thead에 있음
	$("thead #cancelBtn").on("click", function() {
		// 입력 내용 초기화
		$("#no").val("");
		$("#con").val("");
		// 등록 버튼 나타나기 + 수정,취소 버튼 감추기 (반대로 하는 거임)
		$(".insert").show();
		$(".update").hide();
	});
	// 수정 영역의 수정 버튼 클릭 시
	$("thead #updateBtn").on("click", function() {
		action("update");
	});
});

var msg = {
   "insert" : "등록",
   "update" : "수정",
   "delete" : "삭제",
}

function action(flag) {
	// con의 <,> 들을 웹 문자로 변환 -> 디비에도 저 글자로 들어감
	$("#con").val($("#con").val().replace(/</gi, "&lt;"));
	$("#con").val($("#con").val().replace(/>/gi, "&gt;"));
	
	
   // Javascript Object에서의 [] : 해당 키값으로 내용을 불러오거나 넣을 수 있다. Java의 Map에서 get, put역할
   console.log(msg[flag]);
   var params = $("#actionForm").serialize(); // 보낼수있는 형태로 만든 후 보낸다
   $.ajax({
      url : "ACAction/" + flag, // 경로
      type : "POST", // 전송방식(GET : 주소형태, POST : 주소 헤더형태)
      dataType : "json", // 데이터 형태
      data : params, // 보낼 데이터
      success : function(res) {// 성공했을때 경과를 res에 받고 함수 실행
         switch(res.msg) {
         case "success" :
            // 내용 초기화
            $("#con").val("");
            $("#no").val("");
            
            // 목록 재조회
            switch(flag) {
            case "insert" :
            case "delete" :            	
            	// 조회 데이터 초기화
            	$("#page").val("1");
            	$("#searchGbn").val("0");
            	$("#searchTxt").val("");
            	$("#oldGbn").val("0");
            	$("#oldTxt").val("");
            	break;
            case "update" :
            	//기존 값 유지
        		$("#searchGbn").val($("#oldGbn").val());
        		$("#searchTxt").val($("#oldTxt").val());
        		
        		// 수정한 뒤 다시 등록 버튼 활성화 시키기
        		// 입력 내용 초기화
        		$("#no").val("");
        		$("#con").val("");
        		// 등록 버튼 나타나기 + 수정,취소 버튼 감추기 (반대로 하는 거임)
        		$(".insert").show();
        		$(".update").hide();
            	break;
            }
            reloadList();
            break;
         case "fail" :
            makeAlert("알림", msg[flag] + "에 실패하였습니다.");
            break;
         case "error" :
            makeAlert("알림", msg[flag] + " 중 문제가 발생하였습니다.");
            break;
         }
      },
      error : function(request, status, error) { // 실패했을때 함수 실행
         console.log(request.responseText); // 실패 상세내역
      }
   }); // Ajax End
} // action Function End

//목록 조회 호출
function reloadList() {
	var params = $("#searchForm").serialize();
	
	$.ajax({
		url: "ACategoryList", 
		type: "POST", 
		dataType: "json",
		data : params, 
		success: function(res) {
			drawList(res.list); 
			drawPaging(res.pd);
		},
		error : function(request, status, error) {
			console.log(request.responseText);
		}
	});
}

function drawList(list) {
	var html = "";
	
	for(var data of list) {
		html += "<tr no=\"" + data.CATE_NO + "\">";
		html += "<td>" + data.CATE_NO + "</td>";
		html += "<td>" + data.CATE_NM + "</td>";
		html += "<td>";
			html +=   "<div class=\"cmn_btn mtb update_btn\">수정</div><br/>";
			html +=   "<div class=\"cmn_btn mtb delete_btn\">삭제</div>";
		html += "</td>";
		html += "</tr>";
	}
	
	$("tbody").html(html); // 누적된 html을 tbody에 붙여야 함
}

// testa - T - list.jsp에서 그대로 가져옴
function drawPaging(pd) {
	var html = "";
	
	//처음
	html += "<span class=\"page_btn page_first\" page=\"1\">처음</span>";
	
	//이전
	if($("#page").val() == "1") { //input에 들어가는 건 기본적으로 문자열이라 "1"
		html += "<span class=\"page_btn page_prev\" page=\"1\">이전</span>";
	} else {
		html += "<span class=\"page_btn page_prev\" page=\"" + ($("#page").val() * 1 - 1) + "\">이전</span>";
		//1 곱해주는 이유는 숫자로 만들어주는 것
	}
	
	for(var i = pd.startP; i <= pd.endP; i++) {
		//현재 페이지와 i가 같을 때 bold 줌
		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.maxP) { //현재 페이지가 마지막 페이지라면
		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>
<div class="wrap">
   <div class="board_area">
      <!-- 작성 또는 로그인 -->
      
      <!-- 목록 -->
      <table class="board_table">
         <colgroup>
            <col width="100" />
            <col width="*" />
            <col width="100" />
         </colgroup>
         <thead>
            <tr>
               <th>카테고리 이름 등록/수정</th>
               <td class="con_td">
                  <form action="#" id="actionForm">
                     <input type="hidden" name="no" id="no"/>
                     <textarea class="con" name="con" id="con"></textarea>
                  </form>
               </td>
               <th>
                  <div class="insert">
                     <div class="cmn_btn" id="insertBtn">등록</div>
                  </div>
                  
                  <div class="update">
                     <div class="cmn_btn mtb" id="updateBtn">수정</div><br/>
                     <div class="cmn_btn mtb" id="cancelBtn">취소</div>
                  </div>
               </th>
            </tr>
            <tr>
               <th>카테고리 번호</th>
               <th>카테고리 이름</th>
               <th>&nbsp;</th>
            </tr>
         </thead>
         <tbody>
         	<!-- reloadList로 그릴 거임 -->
            <!-- <tr>
               <td>홍길동</td>
               <td>테스트</td>
               <td>10:16</td>
               <td>
                  <div class="cmn_btn mtb">수정</div><br/>
                  <div class="cmn_btn mtb">삭제</div>
               </td>
            </tr> -->
         </tbody>
      </table>
      <!-- 페이징 -->
      <div class="paging_area"></div>
   </div>
   
   <div class="search_area">
   	<!-- 검색어 유지용 -->
   	<input type="hidden" id="oldGbn" value="0" />
   	<input type="hidden" id="oldTxt" />
      <form action="#" id="searchForm">
         <input type="hidden" name="page" id="page" value="1" />
         <select name="searchGbn" id="searchGbn">
            <option value="0">카테고리 번호</option>
            <option value="1">카테고리 이름</option>
         </select>
         <input type="text" name="searchTxt" id="searchTxt" />
         <div class="cmn_btn_ml" id="searchBtn">검색</div>
      </form>
   </div>
</div>
</body>
</html>