#9-2 / notice list + category 검색기능( 동적 query문 ), delete
👀 start 시 파일 생성 👀
- notice table
- dao
package api;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class notice_dao {
int nidx;
String n_title,n_pass,n_subject,n_text,n_date;
}
=>
// config.xml 에 해당 dao 연결 추가
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD configuration 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias alias="noticeDAO" type="api.notice_dao"/>
</typeAliases>
</configuration>
- controller
@Controller
public class notice_controller {
@Resource(name="notice")
private notice_module nm;
}
- module
package api;
import javax.annotation.Resource;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.stereotype.Repository;
@Repository("notice")
public class notice_module {
@Resource(name="template2")
private SqlSessionTemplate tm;
}
/* template2 는 config.xml에서 세팅한 bean id값 => databae 연결 */
<bean id="template2" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="close">
<constructor-arg name="sqlSessionFactory" ref="sqlfact2"></constructor-arg>
</bean>
=> config.xml에서 https://dev-eunse.tistory.com/240 요렇게 db 연결함
/*--------------------- list 출력 (+ 검색 select ) ----------------------*/
1. notice_list.jsp
<body>
<table border="1">
<thead>
<tr height="30">
<th width="500">제목</th>
<th width="100">글쓴이</th>
<th width="100">등록일자</th>
</tr>
</thead>
<tbody>
<cr:forEach var="data" items="${result}">
<tr height="30">
<td align="left">${data.n_subject}</td>
<td>${data.n_title}</td>
<td>${data.n_date}</td>
</tr>
</cr:forEach>
</tbody>
</table>
<br><br>
<form id="frm" onsubmit="search_gopage()">
<select name="search_part" select_data="${search_part}" id="search_part">
<option value="0" class="option">제목 + 내용</option>
<option value="1" class="option">제목</option>
<option value="2" class="option">글쓴이</option>
</select>
<input type="text" name="search_word" value="${search_word}">
<input type="submit" value="검색">
</form>
</body>
<script type="text/javascript">
//현재 select한 category selected 처리
var ea = document.getElementById("search_part").children.length;
var tg = document.querySelectorAll("option")
var w=0;
while(w<ea){
if(tg[w].value == document.getElementById("search_part").getAttribute("select_data")){
tg[w].setAttribute("selected","selected");
}
w++;
}
function search_gopage(){
if(frm.search_word.value == ""){
alert("검색할 단어를 입력하세요")
frm.search_word.focus();
return false;
}else{
frm.method="get";
frm.action="./notice_list.do";
frm.submit();
}
}
</script>
2. mapper.xml - list 출력시 만들어 놓은 일일데이터만 출력하는 mapper 재사용!
<!-- 동적쿼리문 -->
<mapper namespace="noticeDB">
<select id="notice_all" resultType="noticeDAO">
select * from notice order by nidx desc;
</select>
<select id="notice_search" resultType="noticeDAO" parameterType="Map">
select * from notice
<where>
<if test="search_part==0"> <!-- 제목+내용으로 검색할 경우 -->
n_subject like concat('%',#{search_word},'%') or
n_text like concat('%',#{search_word},'%')
</if>
<if test="search_part==1"> <!-- 제목으로 검색할 경우 -->
n_subject like concat('%',#{search_word},'%')
</if>
<if test="search_part==2"> <!-- 글쓴이로 검색할 경우 -->
n_title = #{search_word}
</if>
</where>
order by nidx desc;
</select>
</mapper>
❗ 동적 쿼리문
<select></select>안에 where if 문 사용 가능!
where 태그는 sql에 where문과 동일한 방법으로 사용
조건문 사용시 주의사항 :
숫자는 ' ' 있이 , 문자는 ' ' 없이 핸들링 (!! 우리가 알고있는거랑 반대 !!)
and , or을 이용하여 추가 조건을 핸들링 할 수 있음
choose -> when -> where 쓰는 경우도 있음
❗ map으로 담아서 던지는 경우 parameterType="map" 으로 받아야함!
❗ concat
mybatis에서 사용하는 검색 class (cmd에서는 사용 x) - like 검색시 사용
mysql , mariadb => like concat('%',변수값) / like concat('%',변수값,'%')
oracle => like concat('%'||변수) / like concat('%'||변수||'%')
mssql => like '%'+변수 / like '%'+변수+'%'
3. @Controller
@GetMapping("/notice/notice_list.do")
public String notice_list(Model m,
@RequestParam(defaultValue = "", required = false) String search_part,
@RequestParam(defaultValue = "", required = false) String search_word,
HttpServletResponse res) {
//@RequestParam : 값 필수 여부 지정
//검색값에 따라 조건문으로 result값이 나뉘어야해서 전역변수로 올림
List<notice_dao> result = null;
try {
if(search_part.equals("") && search_word.equals("")) {
result = nm.alldata();
}else {
result = nm.alldata(search_part,search_word);
m.addAttribute("search_part",search_part);
m.addAttribute("search_word",search_word);
}
//=> 다른 모듈임!
m.addAttribute("result",result);
}catch(Exception e) {
System.out.println(e);
System.out.println("query error");
}
return "/notice/notice_list";
}
4. Module
//게시판 게시물 전체 출력 메소드
public List<notice_dao> alldata() {
List<notice_dao> rs = new ArrayList<notice_dao>();
rs = tm.selectList("noticeDB.notice_all");
return rs;
}
//게시판 게시물 검색 메소드
public List<notice_dao> alldata(String search_part, String search_word) {
List<notice_dao> rs = new ArrayList<notice_dao>();
//mapper에 인자값은 단 한개의 값만 적용할 수 있음
Map<String, String> m = new HashMap<String, String>();
m.put("search_part", search_part);
m.put("search_word", search_word);
//무조건 값은 하나만 던질 수 있음 => 키배열로 던짐
rs = tm.selectList("noticeDB.notice_search",m);
return rs;
}
❗ mapper에 인자값은 단 한개의 값만 적용할 수 있음 (seletOne,selectList,insert 등 모든 클래스)
=> 값이 여러개여서 map 으로 배열화시킨 후 던짐!
/*------------------------ 삭제 --------------------------*/
<table border="1">
<thead>
<tr height="30">
<th><input type="checkbox" id="all"></th>
<th width="500">제목</th>
<th width="100">글쓴이</th>
<th width="100">등록일자</th>
</tr>
</thead>
<tbody>
<cr:forEach var="data" items="${result}">
<tr height="30">
<td><input type="checkbox" name="ck" value="${data.nidx}"></td>
<td align="left" title="${data.n_text}">${data.n_subject}</td>
<td>${data.n_title}</td>
<td>${data.n_date}</td>
</tr>
</cr:forEach>
</tbody>
</table>
<!---- script ---->
<script>
var allck = document.getElementById("all");
var ck = document.getElementsByName("ck");
allck.addEventListener("click",function(){
var cked = this.checked
var w=0;
while(w<ck.length){
ck[w].checked = cked;
w++;
}
})
var sum=0;
var ww=0;
while(ww<ck.length){
ck[ww].addEventListener("click",function(){
if(this.checked == true){
sum++;
}else{
sum--;
}
if(sum == ck.length){
allck.checked=true;
}else{
allck.checked=false;
}
})
ww++;
}
function select_del(){
if(sum == 0){
alert('아무것도 선택 안하셨습니다');
}else{
if(confirm("정말 삭제하시겠습니까?")){
frm2.method = 'POST';
frm2.action = './notice_deleteok.do';
frm2.submit();
}
}
}
</script>
- mappaer
<delete id="notice_del">
delete from notice where nidx=#{del} order by nidx desc;
</delete>
<!--
5,6 이런식으로 get으로 받을경우 이렇게 처리해도 됨
단, module에서 map 배열로 변환 후 전달해야함!
-->
<!-- mapper - 배열을 ,기준으로 foreach를 이요하여 순서대로 삭제(다중처리) -->
<delete id="notice_del3">
delete from notice where nidx in(
<foreach collection="array" item="list" separator=",">
#{list}
</foreach>
)
</delete>
<!-- module - 이렇게 -->
public int notice_del(String nidx) {
String list[] = nidx.split(",");
int callback = tm.delete("noticeDB.notice_del",list);
return callback;
}
- controller
@PostMapping("/notice/notice_deleteok.do")
public void notice_delteok(String[] ck,HttpServletResponse res) throws Exception{
res.setContentType("text/html;charset=utf-8");
this.pw = res.getWriter();
try {
int callback = nm.notice_del(ck);
System.out.println(callback); //삭제한 체크박스수만큼 출력됨
if(callback > 0) {
this.pw.write("<script>"
+ "alert('모두 삭제 완료했습니다');"
+ "location.href = './notice_list.do';"
+ "</script>");
}else {
this.pw.write("<script>"
+ "alert('데이터 오류로 인해 삭제 실패');"
+ "location.href = './notice_list.do';"
+ "</script>");
}
}catch(Exception e) {
System.out.println(e);
System.out.println("database 오류 발생!");
}finally {
this.pw.close();
}
}
- module
public int notice_del(String ck) {
int result = 0;
int w=0;
while(w<ck.length) {
result += tm.delete("noticeDB.notice_del",ck[w]);
w++;
}
return result;
}
❗ 반복문은 module에 적는걸 추천 ( controller에 뭘 쓰려구 하지 마세요... )