일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 다른사람 프로젝트 수정전 가져야할 자세
- select
- Test 룸북 사용하기
- 비밀번호 변경 명령어
- linux
- it
- 추천 사이트
- BindingResult
- 순서 보장
- 프로젝트 클린
- 추천 프로그램
- 하모니카 OS 5
- Intellij
- 리눅스
- 타임리프와 스프링
- 스프링부트
- StringUtils.hasText
- 함수 인자값 id
- 룸북
- 개발시작전 자세
- Java
- 명령어
- 타임리프
- js
- JSON
- 자바스크립트 인라인
- cmd
- 설정
- #{..}
- 시퀀스 조회
Archives
- Today
- Total
웹개발 블로그
[SpringProject] SQL댓글 본문
프로젝트 : copySampleString
테이블 : OB
🔼결과
DBMS : ORACLE
MYBATIS 사용
<!-- 댓글있는 쿼리문 전체 조회-->
<select id="getObList2" parameterType="hashmap" resultType="hashmap">
SELECT *
FROM(
SELECT ROWNUM RM,O.P_NO, O.NO, O.DEPTH, O.MEM_NO, 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, (SELECT MEM_NM FROM MEM M WHERE O.MEM_NO = M.MEM_NO) AS MEM_NM
FROM(
SELECT * FROM OB
WHERE DEL = 1
START WITH DEPTH = 0
CONNECT BY PRIOR NO = P_NO)O
WHERE USE != 'N'
)
WHERE RM BETWEEN #{start} AND #{end}
<if test="searchText != null and searchText != ''">
<choose>
<when test="searchGbn eq 0">
<!--작성자 검색 -->
AND MEM_NM LIKE '%' || #{searchText} || '%'
</when>
<when test="searchGbn eq 1">
<!--내용 검색 -->
AND CON LIKE '%' || #{searchText} || '%'
</when>
</choose>
</if>
</select>
<!-- 페이징을 위해서 -->
<select id="getObCnt2" parameterType="hashmap" resultType="Integer">
SELECT count(*)
FROM(
SELECT ROWNUM RM,O.*, (SELECT MEM_NM FROM MEM M WHERE O.MEM_NO = M.MEM_NO) AS MEM_NM
FROM(
SELECT * FROM OB
WHERE DEL = 1
START WITH DEPTH = 0
CONNECT BY PRIOR NO = P_NO)O
)
WHERE USE != 'N'
<if test="searchText != null and searchText != ''">
<choose>
<when test="searchGbn eq 0">
<!--작성자 검색 -->
AND MEM_NM LIKE '%' || #{searchText} || '%'
</when>
<when test="searchGbn eq 1">
<!--내용 검색 -->
AND CON LIKE '%' || #{searchText} || '%'
</when>
</choose>
</if>
</select>
<!-- 삭제대신에 사용유무 수정 (단점, 이렇게 하면 1dept까지만 됌)-->
<update id="UpdateUse" parameterType="hashmap" >
UPDATE OB
SET USE = 'N'
WHERE OB.NO IN (
SELECT NO FROM OB WHERE p_no IN ( SELECT P_NO FROM OB WHERE P_NO = #{no}) or no = #{no}
)
</update>
SQL
✨계층형 쿼리(depth가 늘어나도 상관없음)
🔽수정
select *from 테이블명
WHERE 번호 IN (SELECT CATEGORY_IDX FROM 테이블명
START WITH 번호 = 165 --글번호
CONNECT BY PRIOR 번호 = 부모번호)
AND 사용유무 ='Y';
🔽수정
UPDATE 테이블명
SET 사용유무 = 'Y'
WHERE CATEGORY_IDX IN (SELECT CATEGORY_IDX FROM KRT.NASA_IVR_GROUP_CATEGORY
START WITH 번호 = 165 --글번호
CONNECT BY PRIOR 번호 = 부모번호)
package com.gdj51.test.web.test2.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.gdj51.test.common.service.IPagingService;
import com.gdj51.test.web.test2.dao.IACDao;
@Controller
public class AOBControllerTest {
@Autowired
public IACDao dao; //OB_SQL.XML과 직결
@Autowired
public IPagingService ips;
@RequestMapping(value="AOB2")
public ModelAndView aob2(ModelAndView mav) {
mav.setViewName("testa/AOB/ob2");
return mav;
}
//전체조회
@RequestMapping(value="/AOBList2",
method=RequestMethod.POST,
produces = "text/json;charset=UTF-8")
@ResponseBody
public String AOBList2(ModelAndView mav, @RequestParam HashMap<String, String> params)throws Throwable{
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> model = new HashMap<String, Object>();
int cnt =dao.getIntData("ob.getObCnt2", params);
HashMap<String, Integer> pd = ips.getPagingData(Integer.parseInt(params.get("page")),cnt, 3, 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.getObList2", params);
model.put("list",list);
model.put("pd", pd);
//json형태로 바꿔줘야지 script에서 받을 수 있다.
return mapper.writeValueAsString(model);
}
//AOBAction
@RequestMapping(value="/AOBAction2/{gbn}",
method = RequestMethod.POST,
produces = "text/json;charset=UTF-8")
@ResponseBody
public String AOBAction2(HttpSession session,
@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 "reply":
cnt = dao.update("ob.ReplyOb",params);
break;
case "delete":
cnt = dao.update("ob.UpdateUse", 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);
}
}
AOBControllerTest.java
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- taglib : 커스텀 태그를 사용하겠다. -->
<!-- prefix : 사용할 태그 명칭 -->
<!-- jstl은 자바 라이브러리 이다. -->
<%@ 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" />
<!-- 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 -->
<script type="text/javascript" src="resources/script/jquery/jquery.slimscroll.js"></script>
<style type="text/css">
.wrap{
width:800px;
margin: 0 auto;
}
.mtb {
margin: 5px 0px;
}
.login {
vertical-align:baseline;
}
.con {
width: calc(100% - 22px);
height: 60px;
border: 1px solid #d7d7d7;
resize:none;
padding:10px;
}
.update{
display: none;
}
.reply{
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;
}
.re_reply{
padding-left: 69px;
}
</style>
<script type="text/javascript">
$(document).ready(function() {
/*문제가 좀 많아서 ㅠㅠ body에 overflow: auto;주면 됨.
$('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");
}
});//$("#insertBtn") function End
$("#replyInsertBtn").on("click", function() {
if($.trim($("#con").val()) == "") {
makeAlert("알림", "내용을 입력하세요.", function() {
$("#con").focus();
});
}else{
action("reply");
}
});//$("#insertBtn") function End
//페이징 클릭시
$(".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");//1 중요
//기존 값 새 값으로 변경
$("#oldGbn").val($("#searchGbn").val());
$("#oldText").val($("#searchText").val());
//다시 조회
reloadList();
});//searchBtn
//목록의 삭제버튼 클릭시
$("tbody").on("click", ".delete_btn", function() { //문서를 로드했을 때 <tbody>는 있지만 안에 내용들은 스크립트가 실행되고 나서야 생성됨. 그래서 이렇게 적은거다.
var no = $(this).parent().parent().attr("no");//내가 버튼이고 버튼의 부모는 td고 td의 부모는 tr이다. tr이 no를 가지고 있다.(관리자도구로 보면 이해됨.)
var p_no = $(this).parent().parent().attr("p_no");
makePopup({
title:"알림",
contents : "삭제 하시겠습니까?",
buttons : [{
name:"삭제",
func : function(){
$("#no").val(no);//서버에 삭제할 게시글 번호 전송!!!
$("#p_no").val(p_no);//서버에 삭제할 게시글 번호 전송!!!
action("delete");//삭제 로직 처리
closePopup();//제일 위의 팝업 닫기!!!(이게 없으면 삭제되고 나서도 팝업창이 유지된다.)
}
},{
name:"취소"
}]
});//makePopup
});//delete_btn
//목록의 수정 버튼 클릭 시
$("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(/</gi, "<");//textarea에는 꺽세표시가 잘됨.(db에도 똑같이 넣어주려고 substring을 해서 db에도 해주면되지만 어짜피 바꿔줘야하기에~~...?)
con = con.replace(/>/gi, ">");//textarea에는 꺽세표시가 잘됨.
$("#con").val(con);
//등록버튼 감추기 + (수정,취소버튼 나타내기)
$(".insert").hide();//display:none;
$(".reply").hide();
$(".update").show();//display:display;
//작성영역에 포커스
$("#con").focus();
});
//목록의 댓글 버튼 클릭 시
$("tbody").on("click", ".reply_btn", function() {
var no = $(this).parent().parent().attr("no");
$("#p_no").val(no);
$("#depth").val(no);
//eq(인덱스번호) : 자식 중 인덱스 몇번째 인지 찾아서 취득
var con = $(this).parent().parent().children().eq(1).html();
//수정 내용 넣기 전 < > 변환
con = con.replace(/</gi, "<");//textarea에는 꺽세표시가 잘됨.(db에도 똑같이 넣어주려고 substring을 해서 db에도 해주면되지만 어짜피 바꿔줘야하기에~~...?)
con = con.replace(/>/gi, ">");//textarea에는 꺽세표시가 잘됨.
$("#con").val('');
//등록버튼 감추기 + (댓글,수정,취소버튼 나타내기)
$(".insert").hide();//display:none;
$(".update").hide();//display:display;
$(".reply").show();//display:display;
//작성영역에 포커스
$("#con").focus();
});
//수정 영역의 취소 버튼
$("thead #cancelBtn").on("click", function() {
//입력 내용 초기화
$("#no").val("");//hidden이라 보이지는 않음.
$("#con").val("");
//등록버튼 나타내기 + (수정,취소버튼 숨기기)
$(".reply").hide();
$(".update").hide();
$(".insert").show();
});
//수정 영역의 수정 버튼
$("thead #updateBtn").on("click", function() {
action("update"); //여기까지는 쉬움!
});
});//$(document)
var msg={
"insert" : "등록",
"update" : "수정",
"delete" : "삭제",
"reply" : "댓글"
}
function action(flag) {//비동기 등록, 수정, 삭제
//con의 <들을 웹문자로 변환
$("#con").val($("#con").val().replace(/</gi, "<"));
//con의 >들을 웹문자로 변환
$("#con").val($("#con").val().replace(/>/gi, ">"));
//이제 복호화 작업을 해야함!!!(수정버튼 눌렀을때, 목록 수정버튼 눌를 시 주석을 찾아서 가보면 158라인~159라인)
//JavaScript Object에서의 [] : 해당 키값으로 내용을 불러오거나 넣을 수 있다.
// java의 Map에서 get, put역할
console.log(msg[flag]); //ex)문자로 insert가 넘어온 거임
var params = $("#actionForm").serialize();
$.ajax({
url : "AOBAction2/"+flag, //동일한 작업을 해야함.
type : "POST",
dataType : "json",
data : params,
success : function(res) {
switch(res.msg){
case "success":
//내용초기화
$("#con").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;
case "reply":
$("#page").val("1");//첫페이지에서 나타나게 하려고
$("#searchGbn").val("0");
$("#searchText").val("");
$("#oldGbn").val("0");
$("#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(flag) function End
function reloadList() {
var params = $("#searchForm").serialize();
$.ajax({
url : "AOBList2", //경로
type : "POST", //전송방식(GET : 주소형태, POST : 주소 헤더 형태)
dataType : "json",//데이터 형태
data : params,
success : function(res) {//성공했을 때 결과를 res에 받고 함수 실행
//res는 list와 pd가 넘어온다.
drawList(res.list);//실행하고 넘어온 것중에 list만 보내겠따.
drawPaging(res.pd);//실행하고 넘어온 것중에 pd만 보내겠따.
},
error : function(request, status, error) {// 실패했을 때 함수 실행
console.log(request.responseText); //실패 상세 내역
}
});//ajax
}
function drawList(list) {//값 들어갈 위치에 "++"
var html = "";
for(var data of list){
if(data.DEPTH == 0){
html += "<tr no = \""+data.NO+"\">";
html += "<td>"+data.MEM_NM+"</td>";
html += "<td>"+data.CON+"</td>";
html += "<td>"+data.DT+"</td>";
html += "<td>";
}else{
console.log(data.P_NO);
html += "<tr no = \""+data.NO+"\" p_no=\""+data.P_NO+"\" class='re_reply'>";
html += "<td>"+data.MEM_NM+"</td>";
html += "<td>"+data.CON+"</td>";
html += "<td>"+data.DT+"</td>";
html += "<td>";
}
if("${sMemNo}" == data.MEM_NO){//작성자가 같으면
if(data.DEPTH == 0){
html += "<div class=\"cmn_btn mtb reply_btn\">댓글</div><br/>";
}
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);
}
function drawPaging(pd) {//비동기화 페이징
var html = "";
//ctrl + f
html += "<span class=\"page_btn page_first\" page=\""+1+"\">처음 </span>"; //처음은 무조건 1
if($("#page").val() == "1"){ //이전페이지 page가 1이면 1, 아니면 page -1
// 1이면 page = 1
html += "<span class=\"page_btn page_prev\" page=\""+1+"\">이전</span>";
}else{
//아니면 page -1
html += "<span class=\"page_btn page_prev\" page=\""+($("#page").val() * 1 - 1)+"\">이전</span>"; //(*1)을 해주면 문자로 받은 것을 숫자로 바뀜
}
for(var i = pd.startP; i<=pd.endP; i++){
if($("#page").val()*1 == i){
//현재 페이지
html += "<span style=\"color:red;\" class=\"page_btn\" 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"/>
<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 mtb 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="p_no" id="p_no"/> <!-- 부모 번호-->
<input type="hidden" name="depth" id="depth"/> <!-- 깊이-->
<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>
<div class="reply">
<div class="cmn_btn mtb" id="replyInsertBtn">등록</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> </th>
</tr>
</thead>
<tbody>
<!-- <tr no = 1>
<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">
<!-- EL은 숫자로 받지만, 서버에는 SPRING으로 받는다. -->
<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>
ob2.jsp