Spring

[Spring] 도서 정보 crud 2 - 목록 검색, 카테고리 (+EL태그)

아잠만_ 2024. 7. 25. 10:01

EL태그 정리 

  • == : eq(equal)
  • != : ne(not equal)
  • <  : lt(less than)
  • >  : gt(greater than)
  • <= : le(less equal)
  • >= : ge(greater equal)

list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="/resources/js/jquery.min.js"></script>
<title>도서목록</title>
<script type="text/javascript">
$(function(){
	$("#selCategory").on("change",function(){
		$("#searchForm").submit();
	})
	
	$("input[type='reset']").on("click",function(){
		window.location.href ="/list";
	})
})
</script>
</head>
<body>
<h1>책 목록</h1>

<div>
	<!-- 
	요청URI : /list?category=드라마
         요청파라미터 : category=드라마
         요청방식 : get
    
    URI 파라미터
    param : category=드라마
    param.category : 드라마
	-->
	<!-- <form id="searchForm" action="/list" method="get"> -->
	<form id="searchForm">
		<label for="selCategory">카테고리</label>
		<select id="selCategory" name="category">
			<option disabled="disabled" selected="selected">선택해주세요</option>
			<c:forEach var="category" items="${categories}">
				<option value="${category.CATEGORY}"
					<c:if test="${param.category==category.CATEGORY}">selected</c:if>
				>${category.CATEGORY}</option>
			</c:forEach>
		</select>
		<br/><br/>
		<label for="selGubun">제목/가격</label>
		<select id="selGubun" name="gubun">
			<option disabled="disabled" selected="selected">선택해주세요</option>
			<option value="title"
				<c:if test="${param.gubun=='title'}">selected</c:if> <%--GET방식으로 페이지가 이동되기 때문에 이동될때 저장될 목적--%>
			>제목</option>
			<option value="price"
				<c:if test="${param.gubun=='price'}">selected</c:if>
			>가격</option>
		</select>
		<input type="text" id="keyword" name="keyword" placeholder="검색어를 입력해주세요" value="${param.keyword}"/>
		<br/><br/>
		<input type="submit" value="검색">
		<input type="reset" value="초기화">
	</form>
</div>
<br>
<!-- 
	forEach 태그? 배열(String[], int[][]), Collection(List, Set) 또는 
	Map(HashTable, HashMap, SortedMap)에 저장되어 있는 값들을 
	순차적으로 처리할 때 사용함. 자바의 for, do~while을 대신해서 사용함
	var : 변수
	items : 아이템(배열, Collection, Map)
	varStatus : 루프 정보를 담은 객체 활용
   - index : 루프 실행 시 현재 인덱스(0부터 시작)
   - count : 실행 회수(1부터 시작. 보통 행번호 출력)
-->
<table border="1">
	<thead>
		<tr>
			<th>번호</th>
			<th>제목</th>
			<th>카테고리</th>
			<th>가격</th>
		</tr>	
	</thead>
	<tbody>
		<c:forEach var="bookVO" items="${BookVOList}" varStatus="stat">
		<tr>
			<td>${bookVO.rnum}</td>
			<td><a href="/detail?bookId=${bookVO.bookId}">${bookVO.title}</a></td>
			<td>${bookVO.category}</td>
			<td>${bookVO.price}</td>
		</tr>
		</c:forEach>
	</tbody>
</table>
</body>
</html>

java에서 페이지 처리하지 않고 list에서 작성 할 경우

<!-- EL태그 정리 
== : eq(equal)
!= : ne(not equal)
<  : lt(less than)
>  : gt(greater than)
<= : le(less equal)
>= : ge(greater equal)
-->
<p>${articlePage.startPage} to ${articlePage.endPage}</p>
<!-- startPage가 5보다 클 때에만 [이전] 활성화 -->
<c:if test="${articlePage.startPage gt 5}">
<a href="/list?currentPage=${articlePage.startPage-5}&keyword=${articlePage.keyword}&gubun=${articlePage.gubun}">[이전]</a>
</c:if>
<c:forEach var="pNo" begin="${articlePage.startPage}"
 			  end="${articlePage.endPage}">
<a href="/list?currentPage=${pNo}&keyword=${articlePage.keyword}&gubun=${articlePage.gubun}">[${pNo}]</a>
</c:forEach>
<!-- endPage < totalPages일때만 [다음]활성 -->
<c:if test="${articlePage.endPage lt articlePage.totalPages}">
<a href="/list?currentPage=${articlePage.startPage+5}&keyword=${articlePage.keyword}&gubun=${articlePage.gubun}">[다음]</a>
</c:if>

BookController.java

@RequestParam(value="name",required=false,defaultValue="") String name,

required 필수설정 - false인 경우 필수가 아님

defaultValue="" 값이 없을 시 들어갈 기본 값

package kr.or.ddit.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.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import kr.or.ddit.service.BookService;
import kr.or.ddit.vo.BookVO;
import lombok.extern.slf4j.Slf4j;

/*
	Controller 어노테이션
	스프링 프레임워크에게 "이 클래스는 웹 브라우저의 요청(request)를
	받아들이는 컨트롤러야" 라고 알려주는 것임.
	스프링은 servlet-context.xml의 context:component-scan의 설정에 의해
	이 클래스를 자바빈 객체로 등록(메모리에 바인딩).
*/
@Slf4j
@Controller
public class BookController {
	
	@Autowired
	BookService bookService;
	
	// 책 입력 화면
	/*
	    요청URI : /create
	    요청파라미터 : 없음
	    요청방식 : get
    */
	/*
	   method 속성은 http 요청 메소드를 의미함. 일반적인 웹 페이지 개발에서 GEt 메소드는
	   데이터를 변경하지 않는 경우에, POST 메소드는 데이터가 변경될 경우 사용
	   책 생성 화면은 웹 브라우저에 화면을 보여줄 뿐 데이터의 변경이 일어나지 않으므로
	      GET 메소드를 사용함
	*/
	@RequestMapping(value="/create", method=RequestMethod.GET)
	public ModelAndView create() {
		/*
	       ModelAndView
	       1) Model : Controller가 반환할 데이터(String, int, List, Map, VO..)를 담당
	       2) View : 화면을 담당(뷰(View : JSP)의 경로)
	       */
	      ModelAndView mav = new ModelAndView();
//	      <beans:property name="prefix" value="/WEB-INF/views/" />
//	      <beans:property name="suffix" value=".jsp" />
	      // prefix(접두어) : /WEB-INF/views/
	      // suffix(접미어) : .jsp
	      // /WEB-INF/views/ + book/create + .jsp
	      mav.setViewName("book/create");
	      
	      //forwarding
		return mav;
	}
	

	
	// 목록
		/*
		 * 카테고리 선택 요청
		 * 요청URI : /list?category=드라마
		 * 			/list?category=그림책&gubun=title&keyword=제목 
		 * 요청파라미터 : category=드라마 
		 * 요청방식 : get
		 * 
		 * @RequestParam(value="category",required=false,defaultValue="") String category
		 * required : 필수 설정
		 * defaultValue : 기본값 설정 (null 예외 처리)
		 */
		@RequestMapping(value="/list", method=RequestMethod.GET)
		public ModelAndView list(ModelAndView mav, 
				@RequestParam(value="category",required=false,defaultValue="") String category, // required 필수설정 false인 경우 필수가 아님
				@RequestParam(value="gubun", required=false,defaultValue="") String gubun,
				@RequestParam(value="keyword", required=false,defaultValue="") String keyword
				) {
			Map<String,Object> map = new HashMap<>();
			map.put("category", category);
			map.put("gubun", gubun);
			map.put("keyword", keyword);
			log.info("map : "+map);
			
			List<BookVO> BookVOList = this.bookService.list(map);
			mav.addObject("BookVOList", BookVOList);
			log.info("BookVOList : "+BookVOList);
			
			List<Map<String,Object>> categories = this.bookService.getCategories(); 
			mav.addObject("categories", categories);
			log.info("categories : "+categories);
			
			mav.setViewName("book/list");
			return mav;
		}
	
	/*
	Spring에서 파라미터 명과 매개변수 명이 같으면 파라미터 값이 매개변수 값으로 할당됨
	모든 파라미터는 문자. 그래서 price의 값도 숫자형 문자이다
	 */
	@RequestMapping(value="/createPost", method=RequestMethod.POST)
	public ModelAndView createPost(String title, String category, String price, BookVO vo) {
		log.info("title : "+title);
		log.info("category : "+category);
		log.info("price : "+price);
		log.info("vo : "+vo);
		
		/*
	      |    프리젠테이션 계층                |  서비스 계층              | 퍼시스턴스 계층 |
	                *Controller
	      뷰(JSP) -> Controller클래스 -> Service인터페이스
	                            *Service          *Repository
	                          -> ServiceImpl클래스 -> DAO클래스 -> 매퍼XML -> DB
	       */
		
		// 테이블에 도서를 등록
		int result = this.bookService.createPost(vo);
		System.out.println("createPost -> result : "+result);
		ModelAndView mav = new ModelAndView();
		
		mav.setViewName("redirect: /list");
		return mav;
	}
	
	@RequestMapping(value="/detail", method=RequestMethod.GET)
	public ModelAndView detail(BookVO vo) {
		ModelAndView mav = new ModelAndView();
		mav.setViewName("book/detail");
		log.info("vo : "+vo);
		vo = this.bookService.detail(vo);
		//Model : 데이터
		mav.addObject("vo", vo);
		
		//forwarding
		return mav;
	}
	
	@RequestMapping(value="/update", method=RequestMethod.POST)
	public ModelAndView update(BookVO vo) {
		ModelAndView mav = new ModelAndView();
		mav.setViewName("redirect:/detail?bookId="+vo.getBookId());
		log.info("vo : "+vo);
		
		int result = this.bookService.update(vo);
		
		//forwarding
		return mav;
	}
	
	@RequestMapping(value="/delete", method=RequestMethod.GET)
	public ModelAndView delete(BookVO vo) {
		ModelAndView mav = new ModelAndView();
		mav.setViewName("redirect:/list");
		
		int result = this.bookService.delete(vo);
		
		
		//forwarding
		return mav;
	}
}

book_SQL.xml

map으로 받을 경우 parameterType는 hashMap으로 할 것

ROW_NUMBER() OVER(ORDER BY BOOK_ID DESC) RNUM
  • ROW_NUMBER()
    • 결과 집합의 각 행에 대해 고유한 순번을 부여
    • 이 순번은 특정 기준에 따라 정렬
  • OVER()
    • 적용범위를 정의
    • 어떠한 기준으로 순번을 매길 것인지를 설정
  • RNUM
    • 별칭

<if test="조건">

  • <choose>
  • <when test="조건">
<?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="book">
	<insert id="createPost" parameterType="bookVo">
		<selectKey resultType="int" order="BEFORE" keyProperty="bookId">
			select nvl(max(book_id),0)+1 from book
		</selectKey>
		
		insert into book(BOOK_ID, TITLE, CATEGORY, PRICE, INSERT_DATE)
		values(#{bookId}, #{title}, #{category}, #{price}, SYSDATE)
	</insert>
	
	<!-- 도서 목록 
	return this.sqlSessionTemplate.selectList("book.list",map);
	
	//1) map{"category":"소설","gubun":"","keyword":"127"}
	//2) map{"category":"","gubun":"title","keyword":"127"}
	//3) map{"category":"소설","gubun":"price","keyword":"127"}
	-->
	<select id="list" parameterType="hashMap" resultType="bookVO">
		SELECT ROW_NUMBER() OVER(ORDER BY BOOK_ID DESC) RNUM
	         , BOOK_ID, TITLE, CATEGORY, PRICE, INSERT_DATE
	    FROM   BOOK
	    WHERE  1 = 1
	    <if test="category!=null and category!=''">
			AND    CATEGORY = #{category}
		</if>
		<if test="gubun!=null and gubun!=''">
			<choose>
				<when test="gubun=='title'">
					AND TITLE LIKE '%' || #{keyword} || '%'
				</when>
				<when test="gubun=='price'">
					AND TO_CHAR(PRICE) = #{keyword}
				</when>
			</choose>
		</if>
		<!-- 드모르간 정리
		A' . B'
		의 반대는
		A  + B
		 -->
		<if test="gubun==null or gubun==''">
			AND    (
		           TITLE LIKE '%' || #{keyword} || '%' 
		        OR TO_CHAR(PRICE) = #{keyword}
		    )
		</if>
	</select>
	
	<!-- 카테고리 목록 -->
	<select id="getCategories" resultType="hashMap">
		SELECT DISTINCT CATEGORY
		FROM   BOOK
		ORDER BY 1
	</select>
	
	<select id="detail" resultType="bookVo" parameterType="bookVo">
		select *
		from book
		where book_id = #{bookId}
	</select>
	
	<update id="update" parameterType="bookVo">
		update book
		set title=#{title},
		category=#{category},
		price=#{price}
		where book_id = #{bookId}
	</update>
	
	<delete id="delete" parameterType="bookVo">
		delete book
		where book_id = #{bookId}
	</delete>
</mapper>