동적쿼리와 aop 처리를 실습해보기 위해 게시판을 완성하는 프로젝트를 만들어봤다.
일단 로그인 처리부터 보면
<!-- ID존재여부 -->
<select id="memberIdCount" resultType="int" parameterType="string">
SELECT COUNT(*) FROM webmember
WHERE id=#{id}
</select>
<!-- 비밀번호 확인 -->
<select id="memberGetPassword" resultType="com.sist.dao.MemberVO" parameterType="string">
SELECT pwd,name FROM webmember
WHERE id=#{id}
</select>
아이디가 존재하는지 확인하는 쿼리문, 비밀번호가 맞는지 확인하는 커리문장을 쓴다.
public String isLogin(String id, String pwd)
{
String result="";
int count=getSqlSession().selectOne("memberIdCount", id);
if(count==0)
{
result="NOID";
}
else
{
MemberVO vo=getSqlSession().selectOne("memberGetPassword", id);
String db_pwd=vo.getPwd();
String name=vo.getName();
if(db_pwd.equals(pwd))
{
result=name;
}
else
{
result="NOPWD";
}
}
return result;
}
그리고 나서 결과값에 따라 해당하는 string 문자열 값을 반환한다
@PostMapping("member/login_ok.do")
public String member_login_ok(String id,String pwd,Model model,HttpSession session)
{
// 세션은 DispatcherServlet으로부터 매개변수로 받아서 처리한다
String result=dao.isLogin(id, pwd);
if(!(result.equals("NOID")||result.equals("NOPWD")))
{
// 로그인된 상태
session.setAttribute("id", id);
session.setAttribute("name", result);
}
model.addAttribute("result", result);
return "member/login_ok";
}
로그인 처리는 세션에 값을 저장해야하기 때문에 매개변수로 session을 받아온다. 그리고 로그인에 성공하면
나온 result 문자열 결과값과 아이디를 세션에 저장하고, 그렇지 않으면 result만 반환한다.
이 화면처리는 사용자가 login_ok.do화면을 열었을때 호출되는 화면이다.
login_ok.jsp 에서는 아래와 같이 사용자에게 화면을 띄워준다
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:choose>
<c:when test="${result=='NOID' }">
<script>
alert("ID가 존재하지 않습니다");
history.back();
</script>
</c:when>
<c:when test="${result=='NOPWD' }">
<script>
alert("비밀번호가 틀립니다!");
history.back();
</script>
</c:when>
<c:otherwise>
<c:redirect url="../board/list.do"/>
</c:otherwise>
</c:choose>
로그인이 되면 게시판의 글 목록쪽으로 이동한다
상세보기, 수정, 삭제까지는 전부 이제까지와 동일한데 검색 부분이 이제까지 배우던 쿼리문장들과 달랐어서 이부분을 중점적으로 볼까 한다
<!-- 글쓰기 -->
<insert id="boardInsert" parameterType="BoardVO">
<selectKey keyProperty="no" resultType="int" order="BEFORE">
SELECT NVL(MAX(no)+1, 1) as no FROM spring_freeboard
</selectKey>
INSERT INTO spring_freeboard VALUES(
#{no},
#{name},
#{subject},
#{content},
#{pwd},
SYSDATE,
0
)
</insert>
그래도 이부분은 따로 봐줄 필요가 있다.
select key는 sequence처럼 사용이 가능하다. 먼저 no의 값을 올려주는 쿼리문장을 적성하고, 그 뒤에 글을 삽입해준다.
그리고 문제의...
동적쿼리를 배우기 위해 다양한것을 시도해봤던 검색 쿼리 부분
<!-- 찾기 -->
<sql id="dsql">
<trim prefix="(" suffix=")" prefixOverrides="OR">
<foreach collection="fsArr" item="fs">
<trim prefix="OR">
<choose>
<when test="fs=='N'.toString()">
name LIKE '%'||#{ss}||'%'
</when>
<when test="fs=='S'.toString()">
subject LIKE '%'||#{ss}||'%'
</when>
<when test="fs=='C'.toString()">
content LIKE '%'||#{ss}||'%'
</when>
</choose>
</trim>
</foreach>
</trim>
</sql>
<select id="boardFindData" resultType="BoardVO" parameterType="hashmap">
<bind name="pattern" value="'%'+ss+'%'"/>
SELECT no,subject,name,regdate,hit
FROM spring_freeboard
WHERE
<!-- WHERE ${fs} LIKE #{pattern}-->
<!--
fs=="name"
문자열 :
==
equals
-->
<!-- <if test='fs.equals("name")'>
WHERE name LIKE '%'||#{ss}||'%'
</if>
<if test='fs.equals("subject")'>
WHERE subject LIKE '%'||#{ss}||'%'
</if>
<if test='fs.equals("content")'>
WHERE content LIKE '%'||#{ss}||'%'
</if> -->
<!-- <choose>
<when test='fs=="name"'>
WHERE name LIKE #{pattern}
</when>
<when test='fs=="subject"'>
WHERE subject LIKE #{pattern}
</when>
<when test='fs=="content"'>
WHERE content LIKE #{pattern}
</when>
</choose> -->
<!--
SC
OR (name LIKE '%'||#{ss}||'%') OR (content LIKE '%'||#{ss}||'%')
S
N
(name LIKE '%'||#{ss}||'%')
NS
(name LIKE '%'||#{ss}||'%') OR (subject LIKE '%'||#{ss}||'%')
NSC
(name LIKE '%'||#{ss}||'%') OR (subject LIKE '%'||#{ss}||'%') OR(content LIKE '%'||#{ss}||'%')
-->
<include refid="dsql"/>
</select>
<select id="boardFindDataCount" resultType="int" parameterType="hashmap">
SELECT COUNT(*)
FROM spring_freeboard
WHERE
<!-- WHERE ${fs} LIKE '%'||#{ss}||'%'-->
<!--
fs=="name"
문자열 :
==
equals
-->
<!-- <if test='fs.equals("name")'>
WHERE name LIKE '%'||#{ss}||'%'
</if>
<if test='fs.equals("subject")'>
WHERE subject LIKE '%'||#{ss}||'%'
</if>
<if test='fs.equals("content")'>
WHERE content LIKE '%'||#{ss}||'%'
</if> -->
<!-- <choose>
<when test='fs=="name"'>
WHERE name LIKE '%'||#{ss}||'%'
</when>
<when test='fs=="subject"'>
WHERE subject LIKE '%'||#{ss}||'%'
</when>
<when test='fs=="content"'>
WHERE content LIKE '%'||#{ss}||'%'
</when>
</choose> -->
<include refid="dsql"/>
</select>
</mapper>
이전에 만들었던 검색 기능의 경우 그냥 제목, 혹은 작성자만 검색하는 식으로 만들어 줬었기 때문에 그렇게 크게 어렵지는 않았는데, 이번에는 7가지의 방법으로 검색이 가능하게 만들었다.
이름
제목
내용
이름+제목
이름+내용
제목+내용
이름+제목+내용
이렇게 검색이 가능하게 만들어봤다.
<td class="text-left">
<form method=post action="find.do">
Search:<select name="fs" class="input-sm">
<option value="N">이름</option>
<option value="S">제목</option>
<option value="C">내용</option>
<option value="NS">이름+제목</option>
<option value="NC">이름+내용</option>
<option value="SC">제목+내용</option>
<option value="NSC">이름+제목+내용</option>
</select>
<input type=text name=ss size=15 class="input-sm">
<button class="btn btn=sm btn-warning">검색</button>
</form>
</td>
이건 list.jsp에서 검색방법을 선택해주는 옵션이다. post 방식으로 value값을 넘겨서 어떤 방식으로 검색을 해줄 것인지 지정을 해줘야하기 때문에
이름이면 N
제목이면 S
내용이면 C
이렇게 처리를 해줬고, 이름+제목이면 NS 이렇게 알파벳을 조합해서 검색할 수 있도록 했다.
그리고 검색처리를 할 수 있게 FindVO 를 따로 만들어 준다
package com.sist.dao;
public class FindVO {
private String fs;
private String ss;
public String getFs() {
return fs;
}
public void setFs(String fs) {
this.fs = fs;
}
public String getSs() {
return ss;
}
public void setSs(String ss) {
this.ss = ss;
}
public String[] getFsArr()
{
return fs==null?new String[]{}:fs.split("");
}
}
fs에는 value값으로 받아온 N,S,C,NS,SC,SC,NSC 7문자중에 하나가 들어오게 된다.
ss는 사용자가 입력한 검색어이다.
그리고 한가지 더 처리해야 할 것은 fs가 2개 이상의 문자열 즉, NS,SC,SC,NSC의 형태로 들어왔을때 글자를 하나하나 잘라준다.
getFsArr()이라는 메소드를 실행하면 위와 같이 글자를 단어 하나 하나씩 쪼갤 수 있도록 만들어 둔다.
@PostMapping("board/find.do")
public String board_find(String fs,String ss,Model model)
{
FindVO vo=new FindVO();
vo.setFs(fs);
vo.setSs(ss);
Map map=new HashMap();
map.put("fs",fs);
map.put("ss", ss);
map.put("fsArr", vo.getFsArr());
List<BoardVO> list=service.boardFindData(map);
int count=service.boardFindDataCount(map);
model.addAttribute("list", list);
model.addAttribute("count", count);
return "board/find";
}
그러면 controller에서 위와 같이 처리를 해준다. fs는 검색방법, ss는 사용자 입력 검색어 이고, 이 두개를 FindVO에 대입하면 바로 getFsArr()의 값을 받아올 수 있다.
일단 select로 결과값을 받아와야하기 때문에 mapper에서 해당하는 쿼리문장을 작성해주면된다.
사실 동적쿼리를 배우기 위해 많은 방법으로 시도를 해봤는데, 사용법만 다를뿐 결과값은 모두 똑같이 나오는 것을 확인 할 수 있다.
먼저 공통적으로 사용되는 부분은 bind를 이용해서 묶음처리 해준다.
<select id="boardFindData" resultType="BoardVO" parameterType="hashmap">
<bind name="pattern" value="'%'+ss+'%'"/>
SELECT no,subject,name,regdate,hit
FROM spring_freeboard
WHERE
select ~ where까지는 공통적인 부분이기 때문에 pattern 이라는 명칭으로 같이 묶어줬다.
<include refid="dsql"/>
</select>
그리고 dsql이라는 부분에 검색 쿼리의 핵심 처리 부분을 담아서 include해줬다.
<sql id="dsql">
<trim prefix="(" suffix=")" prefixOverrides="OR">
<foreach collection="fsArr" item="fs">
<trim prefix="OR">
<choose>
<when test="fs=='N'.toString()">
name LIKE '%'||#{ss}||'%'
</when>
<when test="fs=='S'.toString()">
subject LIKE '%'||#{ss}||'%'
</when>
<when test="fs=='C'.toString()">
content LIKE '%'||#{ss}||'%'
</when>
</choose>
</trim>
</foreach>
</trim>
</sql>
쿼리 문장이 결국은 이런식으로 나와야하기 때문에,
SELECT no,subject,name,regdate,hit
FROM spring_freeboard
WHERE (name LIKE '%'||#{ss}||'%') OR (subject LIKE '%'||#{ss}||'%') OR (content LIKE '%'||#{ss}||'%')
맨 앞과 뒤에 trim을 사용해서 괄호로 묶어준다. 그리고 문장 앞 마다 OR을 붙여주는데,
맨 앞에는 붙이면 안되기 때문에 prefixOverrides를 통해 맨 앞의 OR을 제거 해준다.
foreach를 사용해서 fsArr의 길이 만큼 for문을 돌려주고, 그 안에서 choose - when 절을 사용해서 조건문을 수행하게끔 만들어 준다.
결과값은 dsql에 저장되어 select문장을 완성하게 된다.
이건 이름+제목+내용으로 검색어 '내'를 찾은 결과값이다. 이런식으로 결과를 보여 줄 수 있다.
'programming > Gukbi' 카테고리의 다른 글
국비 교육 88일차 - ajax이용 댓글창 띄우기 (0) | 2021.05.01 |
---|---|
국비 교육 87일차 - 동적쿼리연습, 대댓글 게시판 (0) | 2021.04.30 |
국비 교육 85일차 - transaction , AOP 프로그램 (0) | 2021.04.28 |
국비 교육 84일차 - spring tiles (0) | 2021.04.26 |
국비 교육 83일차 - AJAX 검색 기능 활용 (0) | 2021.04.26 |