JSP - 24. 페이징, 검색, MyBatis

갓김치·2020년 12월 21일
1

JSP+Spring

목록 보기
25/43

이번주 학습내용

프레임워크

  • Mybatis
  • hibernate validator

태그

  • EL
  • JSTL



  • 개발 전 다이어그램/도식화 그려보고 시작하기

페이징 + 검색기능

페이징


항목식별자계산수식
총 게시물 수totalRecord100개테이블에서 총 카운트 조회
한 페이지당 리스트 수screenSize10임의의 값
한 화면에 보여줄 페이지 수blockSize5임의의 값
총 페이지 수totalPage10(totalRecord + 9) / screenSize
(offset: 9=screenSize - 1)
현재 페이지currentPage8번클라이언트가 선택한 페이지, 없으면 1
시작 페이지startPage6번((currentSize - 1)/blockSize) * blockSize + 1
종료 페이지endPage10번startPage + blockSize - 1
시작 게시물 번호startRow71endRow - (screenSize - 1)
종료 게시물 번호endRow80currentpage * screenSize
이전 페이지이전startPage - 1if(startPage > 1) 이전 페이지 설정
다음 페이지다음endpage + 1if(endPage < totalPage) 다음 페이지 설정

DB로 검산

배경지식

  • rownum: pseudo column
  • 쿼리 실행 순서: FROM - WHERE - GROUP BY - HAVING - SELECT - ORDER BY
  1. FROM : SQL은 구문이 들어오면 테이블을 가장 먼저 확인
  2. WHERE : 테이블명을 확인했으니, 테이블에서 주어진 조건에 맞는 데이터들을 추출
  3. GROUP BY : 조건에 맞는 데이터가 추출되었으니, 공통적인 데이터들끼리 묶어 그룹핑
  4. HAVING : 공통적인 데이터들이 묶여진 그룹 중, 주어진 주건에 맞는 그룹들을 추출
  5. SELECT : 최종적으로 추출된 데이터들을 조회
  6. ORDER BY : 추출된 데이터들을 정렬
    출처: 티스토리 [Data Makes Our Future]

1차 시도 (잘못된 rownum 조건 설정)

  • rownum >= 11, rownum >= 20 로 하면 FROM, WHERE, SELECT 순으로 실행되기때문에 결과가 나오지 않음
SELECT ROWNUM RNUM
      ,MEMBER.MEM_ID
  FROM MEMBER  
 WHERE ROWNUM >= 11
   AND ROWNUM <= 20;

2차 시도 (ROWNUM 사용시에는 인라인뷰를 활용할 것!)

SELECT A.*
  FROM ( SELECT ROWNUM RNUM
                ,MEMBER.MEM_ID
           FROM MEMBER) A
 WHERE RNUM >= 11
   AND RNUM <=20;

3차 시도 (ROWID 로 정렬)

SELECT ROWNUM RNUM
       ,MEMBER.MEM_ID
  FROM MEMBER
ORDER BY ROWID DESC

  • rowid 내림차순 정렬시, 최근에 저장된 것이 맨위로 오게됨

SELECT A.*
FROM (  SELECT ROWNUM RNUM
               ,MEMBER.MEM_ID
          FROM MEMBER
        ORDER BY ROWID DESC ) A
WHERE RNUM >= 11
AND RNUM <= 20;

  • RNUM이 정해진 후 정렬하기때문에 정렬된 내용은 맞지만 RNUM이 역순으로 나옴.

SELECT A.*
FROM (  SELECT ROWNUM RNUM
               ,MEMBER.MEM_ID
          FROM MEMBER
        ORDER BY ROWID DESC ) A
WHERE RNUM >= 11
  AND RNUM <= 20
ORDER BY A.RNUM;

  • ORDER BY를 뒤에 부여하면, RNUM따라 재정렬되기때문에 ROWID로 정렬시킨 것이 효과가 없음

4차 시도 (2번의 인라인뷰 사용!)

SELECT B.*                              --6
  FROM (SELECT ROWNUM RNUM              --4
               ,A.*Z`
          FROM ( SELECT MEMBER.MEM_ID   --2
                   FROM MEMBER          --1
               ORDER BY ROWID DESC ) A  --3
               )B
WHERE RNUM >= 11                        --5
  AND RNUM <= 20;

  • ROWID, RNUM 모두 정렬이 잘 된 모습...^ㅡ^



mybatis

  • ibatis 버전업
  • ibatis나 mybatis나 내부적으로는 jdbc프로그래밍
  • classloader로 리소르를 읽기때문에 classpath형태로 리소스를 관리함 -> resources 밑에 db config파일을 넣어두어야함
  • 매핑파일 생성시 MyBatis XML Mapper 이용
  • https://mybatis.org/mybatis-3/ko/getting-started.html
  • mybatis는 내부적으로 sqlexception을 persistence exception으로 바꾼다, persistence는 unchecked exception이다

ibatis vs. mybatis

  • mybatis에서는...
    • namespace 필수
    • type alias는 configuration.xml에서만 등록 가능
    • sqlsession이 SqlMapClient의 역할

sqlsessionfactory, session

sqlsessionfactory = 어플리케이션 통틀어 싱글톤

session = 커넥션1개

  • open + close

OGNL

  • https://commons.apache.org/proper/commons-ognl/language-guide.html
  • 일종의 표현언어
  • 내부적으로 스크립트언어형태여서 객체 접근할때 연상배열 으로도 접근 가능
  • StringUtils의 static method를 사용하고 싶다면...
    • static 호출 방법: @class@method(args)
    • @org.apache.commons.lang3.StringUtils@isNotBlank(searchVO.searchWord))



DB 쿼리

a001의 기본 데이터 + 구매한 상품의 목록조회

SELECT A.MEM_NAME
       ,A.MEM_HP
       ,A.MEM_MAIL
       ,B.CART_NO
       ,B.CART_PROD
       ,C.PROD_NAME
       ,B.CART_QTY
  FROM MEMBER A
LEFT OUTER JOIN CART B ON (A.MEM_ID = B.CART_MEMBER)
LEFT OUTER JOIN PROD C ON (B.CART_PROD=C.PROD_ID)
WHERE A.MEM_ID = 'a001'
ORDER BY B.CART_NO ASC;
  • 하지만 이렇게 하면 상품명 중복이 생기죠

상품명 중복을 없애쇼

1차 시도) 다짜고짜 DISTINCT

SELECT DISTINCT MEM_NAME,
                MEM_HP,
                MEM_MAIL,
                C.*
  FROM MEMBER A
LEFT OUTER JOIN CART B ON (MEM_ID = CART_MEMBER)
LEFT OUTER JOIN PROD C ON (CART_PROD = PROD_ID)
 WHERE MEM_ID = 'a001';
ORA-00932: inconsistent datatypes: expected - got CLOB
00932. 00000 -  "inconsistent datatypes: expected %s got %s"
*Cause:    
*Action:
16행, 47열에서 오류 발생
  • LOB 타입에 DISTINCT 못쓰는 오류 발생...

2차 시도) LOB 없을때 인라인 뷰로 먼저 DISTINCT

SELECT MEM_NAME,
       MEM_HP,
       MEM_MAIL,
       C.*
  FROM MEMBER A 
LEFT OUTER JOIN ( SELECT DISTINCT CART_MEMBER, CART_PROD
                    FROM CART) B ON (MEM_ID = CART_MEMBER)
LEFT OUTER JOIN PROD C ON (CART_PROD = PROD_ID)
 WHERE MEM_ID = 'a001';

3차 시도) WITH구문: inline view 분리

WITH CARTB AS (
    SELECT DISTINCT CART_MEMBER, CART_PROD
    FROM CART
)
SELECT MEM_NAME,
       MEM_HP,
       MEM_MAIL,
       C.*
  FROM MEMBER A
LEFT OUTER JOIN CARTB B ON (MEM_ID = CART_MEMBER)
LEFT OUTER JOIN PROD  C ON (CART_PROD = PROD_ID)
WHERE MEM_ID = 'n001';

테이블 조인시

조인 테이블 따로 담을 vo가 있어야함

MEMBER 1:N PROD => HAS MANY

  • 한명의 회원이 그동안 구매한 상품의 목록
  • 1:N은 HAS MANY 관계
  • 이 관계를 표현하기 위해 MemberVO에 List ProdVO 가 추가..
  • Member has many Prod
  • collection 사용하여 resultMap바인딩

PROD 1:1 BUYER => HAS A

  • ProdVO안에 BuyerVO가 하나 들어가있음
  • Prod has a Buyer
  • association 사용하여 resultMap 바인딩
profile
갈 길이 멀다

1개의 댓글

comment-user-thumbnail
2020년 12월 21일

갓김치님 항상 잘보구 있습니당 : ) 감사해여

답글 달기