학원/수업 기록

[Spring] 댓글 게시판 (OB, 전체 코드)

60cod 2022. 8. 23. 13:51

대괄호,
eq(인덱스번호)



AOBController 새로 만들었음

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

import java.util.HashMap;
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 AOBController {
   @Autowired
   public IACDao dao;
   
   @Autowired
   public IPagingService ips;

   @RequestMapping(value = "AOB")
   public ModelAndView aob(ModelAndView mav) {
      mav.setViewName("testa/AOB/ob");
      
      return mav;
   }
   
   @RequestMapping(value = "/AOBAction/{gbn}",
         method = RequestMethod.POST,
         produces = "text/json;charset=UTF-8")
   @ResponseBody
   public String AOBAction(
         @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 = dao.insert("ob.insertOb", params);
            break;
         case "update" : cnt = dao.update("ob.updateOb", params);
            break;
         case "delete" : cnt = dao.update("ob.deleteOb", 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);
   }
}


원래 있던 IACDao, ACDao 이용함.

testa - AOB - ob.jsp
새로 만들었음.
자바스크립트 Object에서의 [] : 해당 키 값으로 내용을 불러오거나 넣을 수 있다. 자바의 Map에서 get, put 역할.

<%@ 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;
}
</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>
<script type="text/javascript">
$(document).ready(function() {
   $(".board_table #loginBtn").on("click", function() {
      location.href = "testALogin";
   });
   
   $("#insertBtn").on("click", function() {
      if($.trim($("#con").val()) == "") {
         makeAlert("알림", "내용을 입력하세요.", function() {
            $("#con").focus();
         });
      } else {
         action("insert");
      }
   });
});

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

function action(flag) {
   // Javascript Object에서의 [] : 해당 키값으로 내용을 불러오거나 넣을 수 있다. Java의 Map에서 get, put역할
   console.log(msg[flag]);
   var params = $("#actionForm").serialize(); // 보낼수있는 형태로 만든 후 보낸다
   $.ajax({
      url : "AOBAction/" + flag, // 경로
      type : "POST", // 전송방식(GET : 주소형태, POST : 주소 헤더형태)
      dataType : "json", // 데이터 형태
      data : params, // 보낼 데이터
      success : function(res) {// 성공했을때 경과를 res에 받고 함수 실행
         switch(res.msg) {
         case "success" :
            // 내용 초기화
            $("#con").val("");
            
            // 목록 재조회
            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
</script>
</head>
<body>
<c:import url="/testAHeader"></c:import>
<hr/>
<div class="wrap">
   <div class="board_area">
      <!-- 작성 또는 로그인 -->
      
      <!-- 목록 -->
      <table class="board_table">
         <colgroup>
            <!-- 작성자 -->
            <col width="100" />
            <!-- 내용 -->
            <col width="500" />
            <!-- 날짜 -->
            <col width="100" />
            <!-- 버튼 -->
            <col width="100" />
         </colgroup>
         <thead>
            <c:choose>
               <c:when test="${empty sMemNo}"><!-- 비 로그인 시 -->
                  <tr>
                     <th colspan="4">
                        로그인이 필요한 서비스 입니다.
                        <div class="cmn_btn login" id="loginBtn">로그인</div>
                     </th>
                  </tr>
               </c:when>
               <c:otherwise><!-- 로그인 시 -->
                  <tr>
                     <th>${sMemNm}</th>
                     <td colspan="2" class="con_td">
                        <form action="#" id="actionForm">
                           <input type="hidden" name="no" id="no"/>
                           <input type="hidden" name="memNo" value="${sMemNo}"/>
                           <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>
               </c:otherwise>
            </c:choose>
            <tr>
               <th>작성자</th>
               <th>내용</th>
               <th>작성일</th>
               <th>&nbsp;</th>
            </tr>
         </thead>
         <tbody>
            <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">
      <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="searchText" id="searchText" />
         <div class="cmn_btn_ml" id="searchBtn">검색</div>
      </form>
   </div>
</div>
</body>
</html>


testa - login - main.jsp
댓글 창 주소 AOB 가는 링크 추가해주기

<%@ 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>Insert title here</title>
<script type="text/javascript"
		src="resources/script/jquery/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {

});
</script>
</head>
<body>
<c:import url="/testAHeader"></c:import>
<br/>
<a href="ATList">게시글 목록</a>
<br/>
<a href="AOB">댓글</a>
</body>
</html>


새 테이블 OB 만들기

제약조건 걸어주기

시퀀스 만들기




지각해서 여기부터 필기!


추가, 수정, 삭제, 목록

쿼리 짜기
일단 xml 파일 먼저 다 만들었다.


MEM 테이블 데이터는 현재 아래와 같음.

MEM 테이블


-추가
내가 회원 데이터가 4번부터 있어서 4번으로 했다.

INSERT INTO OB(NO, MEM_NO, CON)
VALUES (OB_SEQ.NEXTVAL, 4, 'TEST');
COMMIT;


-수정
넣는 거 한 번 실패해서 1번이 없고 2번부터 시작이라 2번을 바꿔줌

UPDATE OB SET CON = 'TEST_UPDATE'
WHERE NO = 2;
COMMIT;


-삭제
DEL 0으로 바꿔주는 건 업데이트로 똑같이 하고..

-페이징을 위한 카운트

SELECT COUNT(*) AS CNT
FROM OB O INNER JOIN MEM M
                ON O.MEM_NO = M.MEM_NO
                AND M.DEL = 1
WHERE O.DEL = 1
-- 작성자 검색
-- AND M.MEM_NM LIKE '%' || 'TEST' || '%'
-- 내용 검색
AND O.CON LIKE '%' || 'UPDATE' || '%'
;


-목록 조회

SELECT O.NO, O.MEM_NO, O.MEM_NM, O.CON, O.DT
FROM (SELECT O.NO, O.MEM_NO, M.MEM_NM, O.CON,
                CASE WHEN TO_CHAR(O.DT, 'YY.MM.DD') = TO_CHAR(SYSDATE, 'YY.MM.DD')
                    THEN TO_CHAR(O.DT, 'HH24:MI')
                    ELSE TO_CHAR(O.DT, 'YY.MM.DD')
                END AS DT,
                ROW_NUMBER() OVER(ORDER BY O.NO DESC) AS RNUM
        FROM OB O INNER JOIN MEM M
                        ON O.MEM_NO = M.MEM_NO
                        AND M.DEL = 1
        WHERE O.DEL = 1) O
WHERE O.RNUM BETWEEN 1 AND 10
;



OB_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="ob">
	<insert id="insertOb" parameterType="hashmap">
		INSERT INTO OB(NO, MEM_NO, CON)
		VALUES (OB_SEQ.NEXTVAL, #{memNo}, #{con})
	</insert>
	
	<update id="updateOb" parameterType="hashmap">
		UPDATE OB SET CON = #{con}
		WHERE NO = #{no}
	</update>
	
	<update id="deleteOb" parameterType="hashmap">
		UPDATE OB SET DEL = 0
		WHERE NO = #{no}
	</update>
	
	<select id="getObCnt" parameterType="hashmap" resultType="Integer">
		 SELECT COUNT(*) AS CNT
		FROM OB O INNER JOIN MEM M
		                ON O.MEM_NO = M.MEM_NO
		                AND M.DEL = 1
		WHERE O.DEL = 1
		<if test="searchText != null and searchText != ''">
			<choose>
				<when test="searchGbn eq 0">
					AND M.MEM_NM LIKE '%' || #{searchText} || '%'
				</when>
				<when test="searchGbn eq 1">
					AND O.CON LIKE '%' || #{searchText} || '%'
				</when>
			</choose>
		</if>
	</select>
		
	<select id="getObList" parameterType="hashmap" resultType="hashmap">
		SELECT O.NO, O.MEM_NO, O.MEM_NM, O.CON, O.DT
		FROM (SELECT O.NO, O.MEM_NO, M.MEM_NM, O.CON,
		                CASE WHEN TO_CHAR(O.DT, 'YY.MM.DD') = TO_CHAR(SYSDATE, 'YY.MM.DD')
		                    THEN TO_CHAR(O.DT, 'HH24:MI')
		                    ELSE TO_CHAR(O.DT, 'YY.MM.DD')
		                END AS DT,
		                ROW_NUMBER() OVER(ORDER BY O.NO DESC) AS RNUM
		        FROM OB O INNER JOIN MEM M
		                        ON O.MEM_NO = M.MEM_NO
		                        AND M.DEL = 1
		        WHERE O.DEL = 1
		        <if test="searchText != null and searchText != ''">
					<choose>
						<when test="searchGbn eq 0">
							AND M.MEM_NM LIKE '%' || #{searchText} || '%'
						</when>
						<when test="searchGbn eq 1">
							AND O.CON LIKE '%' || #{searchText} || '%'
						</when>
					</choose>
				</if>) O
		WHERE O.RNUM BETWEEN #{start} AND #{end}
	</select>
	
</mapper>

카운트는 resultType이 Integer




주소 http://localhost:8090/SampleSpring/AOB
들어가서

로그인

댓글 창 링크 클릭

댓글 작성


아직 목록 상에서는 안 뜨지만
디벨로퍼 가서 데이터 보면 들어와 있음.




목록 페이징


ob.jsp
testa - T - list.jsp에서 drawPaging 복사해서 넣기

// 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);
}



목록 띄우기


drawList 함수 만들어서
바디 안의 td 내용 잘라와서 넣고 html 변수에 누적시키기
수정, 삭제 버튼에 아직 아무것도 안 달았으니까 클래스 다르게 추가해주기. update_btn, delete_btn

역슬래시 쉽게 달아주는 방법
드래그 해서 ctrl + F
" 찾아서 \" 로 교체
이때 Scope 확인하기!

function drawList(list) {
	var html = "";
	
	for(var data of list) {
		html += "<tr no=\"" + data.NO + "\">";
		html += "<td>" + data.MEM_NM + "</td>";
		html += "<td>" + data.CON + "</td>";
		html += "<td>" + data.DT + "</td>";
		html += "<td>";
		if("${sMemNo}" == data.MEM_NO) { // 작성자이면 수정,삭제 버튼 나타남
			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에 붙여야 함
}

for문이 끝났을 때 html에 누적되어 있을 테니 tbody의 내용을 갈아 엎어주기까지 해줘야 함.

그리고 document ready 안에 맨 위에 reloadList(); 추가까지!

<script type="text/javascript">
$(document).ready(function() {
	reloadList();




이제 내가 댓글을 등록할 때마다 리스트에서 바로 확인 할 수 있고
내가 작성자(rla)인 댓글만 수정, 삭제 버튼이 보인다.

다른 사용자가 쓴 댓글의 버튼은 안 보인다.


검색


검색어 유지용 추가

   <div class="search_area">
   	<!-- 검색어 유지용 -->
   	<input type="hidden" id="oldGbn" value="0" />
   	<input type="hidden" id="oldText" />
      <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="searchText" id="searchText" />
         <div class="cmn_btn_ml" id="searchBtn">검색</div>
      </form>
   </div>



document reasdy 안에
paging_area와 searchBtn에 대해 추가

	//페이징 클릭 시
	$(".paging_area").on("click", "span", function() {
		$("#page").val($(this).attr("page"));
		//기존 값 유지
		$("#searchGbn").val($("#oldGbn").val());
		$("#searchText").val($("#oldText").val());
	
		reloadList();
	});
	// 검색 버튼 클릭 시
	// 기존 것 넘겨줘도 됨
	$("#searchBtn").on("click", function() {
		$("#page").val("1");
		//기존 값 새 값으로 변경
		$("#oldGbn").val($("#searchGbn").val());
		$("#oldText").val($("#searchText").val());
	
		reloadList();
	});



success에 대해 switch문 추가
insert와 delete는 둘 다 동일하게 처리하고,
update 는 수정이라 1페이지로 갈 일 없음

function action(flag) {
   // Javascript Object에서의 [] : 해당 키값으로 내용을 불러오거나 넣을 수 있다. Java의 Map에서 get, put역할
   console.log(msg[flag]);
   var params = $("#actionForm").serialize(); // 보낼수있는 형태로 만든 후 보낸다
   $.ajax({
      url : "AOBAction/" + 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");
            	$("#searchText").val("");
            	$("#oldGbn").val("0");
            	$("#oldText").val("");
            	break;
            case "update" :
            	//기존 값 유지
        		$("#searchGbn").val($("#oldGbn").val());
        		$("#searchText").val($("#oldText").val());
            	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

댓글을 새로 작성하면 검색 결과가 없었던 걸로 되면서 1페이지로 돌아온다.


slimscroll


src - main - webapp - resources - script - jquery - jquery.slimscroll.js
추가할 거임
ob.jsp에서

<!-- Slimscroll JS -->
<script type="text/javascript" 
         src="resources/script/jquery/jquery.slimscroll.js"></script>
<script type="text/javascript">
$(document).ready(function() {
	$("body").slimscroll({
		height: "100%",
		axis: "y"
	});

써도 되는데 원래 사이즈가 있어서 바디에 그냥 스크롤 달아주는 게 이쁘다.
그니까 다시 주석처리하고 body에 overflow auto 주기


삭제 버튼


수정, 삭제 버튼은 클래스로 된 버튼이다.
그걸 클릭했을 때 번호를 가져가서 삭제 처리 해줘야 한다.
항상 떠있는 게 tbody라 이벤트는 tbody에 줄 거다.

document ready 안에 추가.
삭제 버튼을 눌렀을 때 그 글의 번호를 가져가려면 그 버튼을 가진 td의 tr까지 두 단계를 올라가야 한다.
길어서 변수 no 만들어서 담음.

	// 목록의 삭제 버튼 클릭시
	$("tbody").on("click", ".delete_btn", function() {
		var no = $(this).parent().parent().attr("no");
		// 팝업
		makePopup({
			title : "알림",
			contents : "삭제 하시겠습니까?",
			buttons : [{
				name : "삭제",
				func:function() {
					// 삭제 전에 번호 가져가야 함
					$("#no").val(no);
					action("delete");
					closePopup(); // 제일 위의 팝업 닫기
				}
			}, {
				name : "취소"
			}]
		});
	});

flag가 delete가 되어서 아래 action 작동해서 삭제 처리 됨.


수정 버튼


목록의 수정 버튼 클릭했을 때 그 댓글의 내용을 댓글 입력 창으로 가져와야 한다.
지금 내용은 두번째 자식으로 가지고 있다.
셀렉터로 가는 방법이 있고 eq로 가는 방법이 있음.
document ready 안에 추가.

eq(인덱스번호) : 자식들 중 인덱스 몇 번째인지 찾아서 취득.

	// 목록의 수정 버튼 클릭 시
	$("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").val(con);
		
		// 등록 버튼 감추기 + 수정,취소 버튼 나타나게 하기
		$(".insert").hide();
		$(".update").show();
	});
	// 수정 영역의 취소 버튼 클릭 시
	// 취소 버튼은 없었던 일로 하면 됨.
	// 취소 버튼은 thead에 있음
	$("thead #cancelBtn").on("click", function() {
		// 입력 내용 초기화
		$("#no").val("");
		$("#con").val("");
		
		// 등록 버튼 나타나기 + 수정,취소 버튼 감추기 (반대로 하는 거임)
		$(".insert").show();
		$(".update").hide();
	});



document ready 안에

	// 수정 영역의 수정 버튼 클릭 시
	$("thead #updateBtn").on("click", function() {
		action("update");
	});

action(flag) 함수 안에

            case "update" :
            	//기존 값 유지
        		$("#searchGbn").val($("#oldGbn").val());
        		$("#searchText").val($("#oldText").val());
        		
        		// 수정한 뒤 다시 등록 버튼 활성화 시키기
        		// 입력 내용 초기화
        		$("#no").val("");
        		$("#con").val("");
        		// 등록 버튼 나타나기 + 수정,취소 버튼 감추기 (반대로 하는 거임)
        		$(".insert").show();
        		$(".update").hide();
            	break;
            }
            reloadList();
            break;



포커스도 추가해주기

	// 목록의 수정 버튼 클릭 시
	$("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").val(con);
		
		// 등록 버튼 감추기 + 수정,취소 버튼 나타나게 하기
		$(".insert").hide();
		$(".update").show();
		
		//작성 영역에 포커스
		$("#con").focus();
	});



그럼 이제 수정도 되고 리스트에도 보임


여기에 글 번호를 달아주면 이 리스트가 그 글의 댓글들이 되는 거다.
글 상세보기의 글 번호가 이 댓글 리스트의 조건이 됨.



중요한 웹 문자 변환 작업!!

댓글 내용에 스크립트를 담아서 등록하면 터져버리는 문제가 있다.

내용에 꺽쇄가 들어가면 태그로 인식하기 때문.
태그로 인식하지 않고 화면에 그리도록 웹 문자로 변환해주는 작업이 필요하다.

1) 함수 안에

function action(flag) {
	// con의 <,> 들을 웹 문자로 변환 -> 디비에도 저 글자로 들어감
	$("#con").val($("#con").val().replace(/</gi, "&lt;"));
	$("#con").val($("#con").val().replace(/>/gi, "&gt;"));

2) 수정할 때도

	// 목록의 수정 버튼 클릭 시
	$("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, ">");


꺽쇄가 있어도 잘 들어가고 디비에는 꺽쇄 대신 lt, gt가 들어가있다.


이 처리를 안 해주면
꺽쇄 뒤가 주석 처리 되어버리는? SQL Injection 문제가 발생한다.
그래서 아무거나 입력해도 로그인이 되기도 하고 불법적인 데이터에 취약해진다.




전체 코드

AOBController

더보기
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 AOBController {
   @Autowired
   public IACDao dao;
   
   @Autowired
   public IPagingService ips;

   @RequestMapping(value = "AOB")
   public ModelAndView aob(ModelAndView mav) {
      mav.setViewName("testa/AOB/ob");
      
      return mav;
   }
   
   @RequestMapping(value = "/AOBAction/{gbn}",
         method = RequestMethod.POST,
         produces = "text/json;charset=UTF-8")
   @ResponseBody
   public String AOBAction(
         @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 = dao.insert("ob.insertOb", params);
            break;
         case "update" : cnt = dao.update("ob.updateOb", params);
            break;
         case "delete" : cnt = dao.update("ob.deleteOb", 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 = "/AOBList",
	         method = RequestMethod.POST,
	         produces = "text/json;charset=UTF-8")
	   @ResponseBody
	   public String AOBList(
	         @RequestParam HashMap<String, String> params) throws Throwable {
	      ObjectMapper mapper = new ObjectMapper ();
	      
	      Map<String, Object> model = new HashMap<String, Object>();
	      
	      int cnt = dao.getInt("ob.getObCnt", 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 = dao.getList("ob.getObList", params);
			
	      model.put("list", list);
	      model.put("pd", pd);
			
	      return mapper.writeValueAsString(model);
	      
	   }
}


IACDao

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

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

public interface IACDao {
	//이렇게 쌍으로 다님
	//숫자 취득
	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;
	
}


ACDao

더보기
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 ACDao implements IACDao {
	@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);
	}
}


ob.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() {
	/*$("body").slimscroll({
		 height: "100%",
		axis: "y" 
	});*/
	
	reloadList();
	
   $(".board_table #loginBtn").on("click", function() {
      location.href = "testALogin";
   });
   
   $("#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());
		$("#searchText").val($("#oldText").val());
	
		reloadList();
	});
	// 검색 버튼 클릭 시
	// 기존 것 넘겨줘도 됨
	$("#searchBtn").on("click", function() {
		$("#page").val("1");
		//기존 값 새 값으로 변경
		$("#oldGbn").val($("#searchGbn").val());
		$("#oldText").val($("#searchText").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 : "AOBAction/" + 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");
            	$("#searchText").val("");
            	$("#oldGbn").val("0");
            	$("#oldText").val("");
            	break;
            case "update" :
            	//기존 값 유지
        		$("#searchGbn").val($("#oldGbn").val());
        		$("#searchText").val($("#oldText").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: "AOBList", 
		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.NO + "\">";
		html += "<td>" + data.MEM_NM + "</td>";
		html += "<td>" + data.CON + "</td>";
		html += "<td>" + data.DT + "</td>";
		html += "<td>";
		if("${sMemNo}" == data.MEM_NO) { // 작성자이면 수정,삭제 버튼 나타남
			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>
<c:import url="/testAHeader"></c:import>
<hr/>
<div class="wrap">
   <div class="board_area">
      <!-- 작성 또는 로그인 -->
      
      <!-- 목록 -->
      <table class="board_table">
         <colgroup>
            <!-- 작성자 -->
            <col width="100" />
            <!-- 내용 -->
            <col width="500" />
            <!-- 날짜 -->
            <col width="100" />
            <!-- 버튼 -->
            <col width="100" />
         </colgroup>
         <thead>
            <c:choose>
               <c:when test="${empty sMemNo}"><!-- 비 로그인 시 -->
                  <tr>
                     <th colspan="4">
                        로그인이 필요한 서비스 입니다.
                        <div class="cmn_btn login" id="loginBtn">로그인</div>
                     </th>
                  </tr>
               </c:when>
               <c:otherwise><!-- 로그인 시 -->
                  <tr>
                     <th>${sMemNm}</th>
                     <td colspan="2" class="con_td">
                        <form action="#" id="actionForm">
                           <input type="hidden" name="no" id="no"/>
                           <input type="hidden" name="memNo" value="${sMemNo}"/>
                           <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>
               </c:otherwise>
            </c:choose>
            <tr>
               <th>작성자</th>
               <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="oldText" />
      <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="searchText" id="searchText" />
         <div class="cmn_btn_ml" id="searchBtn">검색</div>
      </form>
   </div>
</div>
</body>
</html>


testa - login - login.jsp

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<!-- cmn 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">
#actionForm {
	font-size: 11pt;
}
</style>
<!-- JQuery -->
<script type="text/javascript" 
		src="resources/script/jquery/jquery-1.12.4.min.js"></script>
<!-- popup -->
<script type="text/javascript" 
   src="resources/script/common/popup.js"></script>
<!-- cmn JQuery -->		
<script type="text/javascript" 
      src="resources/script/common/common.js"></script>
<script type="text/javascript">
$(document).ready(function(){
 	$("#actionForm").on("keypress", "input", function(event) {
		if(event.keyCode == 13) { 
			$("#loginBtn").click(); 
			return false;
		} 
	});
	
	$("#loginBtn").on("click", function(){ 
		if($.trim($("#id").val()) == "") {
			makeAlert("알림", "아이디를 입력하세요.", function(){
				$("#id").focus();
			});
		} else if($.trim($("#pw").val()) == "") {
			makeAlert("알림", "비밀번호를 입력하세요.", function(){
				$("#pw").focus();
			});
		} else {
			var params = $("#actionForm").serialize();
			
			$.ajax({
				url: "testALoginAjax", 
				type: "POST",
				dataType: "json", 
				data : params, 
				success: function(res) { 
					if(res.msg == "success") {
						location.href = "testAMain";
					} else {
						makeAlert("알림", "아이디나 비밀번호가 틀립니다.");
					}
				},
				error : function(request, status, error) { 
					console.log(request.responseText);
				}
			});
		}
	});
});
</script>
</head>
<body>
<form action="#" id="actionForm">
	아이디 <input type="text" name="id" id="id" /><br/>
	비밀번호 <input type="password" name="pw" id="pw" /><br/>
</form>
<input type="button" value="로그인" id="loginBtn" />
</body>
</html>


testa - login - header.jsp

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<script type="text/javascript">
$(document).ready(function() { //제이쿼리 없지만 동작할 거임
	$("#logoutBtn").on("click", function() {
		location.href = "testALogout";
	});
	
	$("#loginBtn").on("click", function() {
		location.href = "testALogin";
	});
});
</script>
<c:choose>
	<c:when test="${empty sMemNm}"> <!-- 세션이 비어 있다면 -->
		<input type="button" value="로그인" id="loginBtn" />
	</c:when>
	<c:otherwise>
		${sMemNm}님 어서오세요. <input type="button" value="로그아웃" id="logoutBtn" />
	</c:otherwise>
</c:choose>


testa - login - main.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>Insert title here</title>
<script type="text/javascript"
		src="resources/script/jquery/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {

});
</script>
</head>
<body>
<c:import url="/testAHeader"></c:import>
<br/>
<a href="ATList">게시글 목록</a>
<br/>
<a href="AOB">댓글</a>
</body>
</html>


OB_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="ob">
	<insert id="insertOb" parameterType="hashmap">
		INSERT INTO OB(NO, MEM_NO, CON)
		VALUES (OB_SEQ.NEXTVAL, #{memNo}, #{con})
	</insert>
	
	<update id="updateOb" parameterType="hashmap">
		UPDATE OB SET CON = #{con}
		WHERE NO = #{no}
	</update>
	
	<update id="deleteOb" parameterType="hashmap">
		UPDATE OB SET DEL = 0
		WHERE NO = #{no}
	</update>
	
	<select id="getObCnt" parameterType="hashmap" resultType="Integer">
		 SELECT COUNT(*) AS CNT
		FROM OB O INNER JOIN MEM M
		                ON O.MEM_NO = M.MEM_NO
		                AND M.DEL = 1
		WHERE O.DEL = 1
		<if test="searchText != null and searchText != ''">
			<choose>
				<when test="searchGbn eq 0">
					AND M.MEM_NM LIKE '%' || #{searchText} || '%'
				</when>
				<when test="searchGbn eq 1">
					AND O.CON LIKE '%' || #{searchText} || '%'
				</when>
			</choose>
		</if>
	</select>
		
	<select id="getObList" parameterType="hashmap" resultType="hashmap">
		SELECT O.NO, O.MEM_NO, O.MEM_NM, O.CON, O.DT
		FROM (SELECT O.NO, O.MEM_NO, M.MEM_NM, O.CON,
		                CASE WHEN TO_CHAR(O.DT, 'YY.MM.DD') = TO_CHAR(SYSDATE, 'YY.MM.DD')
		                    THEN TO_CHAR(O.DT, 'HH24:MI')
		                    ELSE TO_CHAR(O.DT, 'YY.MM.DD')
		                END AS DT,
		                ROW_NUMBER() OVER(ORDER BY O.NO DESC) AS RNUM
		        FROM OB O INNER JOIN MEM M
		                        ON O.MEM_NO = M.MEM_NO
		                        AND M.DEL = 1
		        WHERE O.DEL = 1
		        <if test="searchText != null and searchText != ''">
					<choose>
						<when test="searchGbn eq 0">
							AND M.MEM_NM LIKE '%' || #{searchText} || '%'
						</when>
						<when test="searchGbn eq 1">
							AND O.CON LIKE '%' || #{searchText} || '%'
						</when>
					</choose>
				</if>) O
		WHERE O.RNUM BETWEEN #{start} AND #{end}
	</select>
	
</mapper>