본문 바로가기
개발/jqgrid

★jqgrid 페이징 구현(쿼리) --> count추가 2016.12.21

by areumtb 2016. 12. 12.

jqgrid 페이징에서 local형식 외에(JSON...) 데이터로 구현을할때는 서버단에서 값을 계산해서 보내줘야 한다. 



그리드 페이징 분리를 찾다가 그리드먼저 해결하자는 마음으로 먼저 해결하였다.


지금까지 내가 구현한 jqgrid는 페이징이 안되있었다. 페이지를 넘기면 처음 로딩된 데이터가 그대로 남아있었다. 

그래서 서버단에서 페이지에따른 데이터값을 계산해서 보내기로 결정



1. 그리드를 실행하면은 records : 20,page :1, rows :5, total :20, sord :asc, sidx:name 값들이 넘어오는것을 이용


한 페이지에서 보여줄 데이터의 갯수는 rows이다. 총 레코드는 records(이건 db에서 계산해야함), 레코드 갯수에따른 총 페이지도 계산해야함


1
2
3
4
5
6
7
8
9
--총 페이지수
    <select id="totalCount" resultType="int" parameterType="int">
        select
        round((count(*)/#{rows})+1) from employee
    </select>

--총 레코드갯수
    <select id="totalRecords" resultType="int" parameterType="int">
        select
        count(*) from employee
    </select>
cs




2. 위에거 계산한 값들은 jqgrid로 넘겨주어서 화면에 표시됨 

3. 페이징을 위하여 쿼리를 수정 


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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
    <select id="AllEmployeeList" resultMap="EmployeeMapper"
        parameterType="map">
 
<!--     원래 쿼리 : 페이지에따른 값을 가져오는것이 아니라 그냥 전체를 가져옴
    SELECT 
        E.UCODE,E.DCODE,E.ENAME,E.NAME,E.BIRTHDAY,E.PHONE,E.EXNUM,E.EMAIL,E.ADDRESS,E.BIREDAY,E.NOTE,
        DE.DESCRIPTION AS DEPARTMENT,
        PO.DESCRIPTION AS POSITION,
        PR.DESCRIPTION AS PRESENT 
        FROM CODE_TABLE PO,CODE_TABLE PR,CODE_TABLE DE ,EMPLOYEE E 
        WHERE 
        DE.CODE = E.DEPARTMENT AND
        PO.CODE = E.POSITION AND
        PR.CODE = E.PRESENT 
        order by ${SIDX}
        <if test="SORD == ('asc')">ASC</if>
        <if test="SORD == ('desc')">DESC</if> -->
 
 
-- 페이지값에따른 데이터를 가져옴
 
 SELECT
    AAA.*
FROM(   
    SELECT 
   ROW_NUMBER() OVER (
   order by ${SIDX}
        <if test="SORD == ('asc')">ASC</if>
        <if test="SORD == ('desc')">DESC</if>
    ) RNUM,
        E.UCODE,E.DCODE,E.ENAME,E.NAME,E.BIRTHDAY,E.PHONE,E.EXNUM,E.EMAIL,E.ADDRESS,E.BIREDAY,E.NOTE,
        DE.DESCRIPTION AS DEPARTMENT,
        PO.DESCRIPTION AS POSITION,
        PR.DESCRIPTION AS PRESENT
        FROM CODE_TABLE PO,CODE_TABLE PR,CODE_TABLE DE ,EMPLOYEE E 
        WHERE 
        DE.CODE = E.DEPARTMENT AND
        PO.CODE = E.POSITION AND
        PR.CODE = E.PRESENT 
) AAA
WHERE
    AAA.RNUM 
    BETWEEN   ${startCount} AND ${endCount}
   
    
    
    
    </select>
cs


1.ROW_NUMBER()을 사용해서 정렬된 그리드에 번호를 부여



 ROW_NUMBER()  이용


페이징을 위해서는 정렬된 데이터값에 번호를 부여하여 데이터를 가져와야한다.

그리기 위해서는 오라클에선  ROW_NUMBER()  함수를 이용한다.


 ROW_NUMBER() OVER(정렬) , RANK() OVER (정렬) : 정렬된 데이터값을 기준으로 번호를 부여함



SELECT USERID, SCORE, RANK() OVER (ORDER BY SCORE DESC) RANK FROM TMP_TABLE;

SELECT USERID, SCORE, ROW_NUMBER() OVER (ORDER BY SCORE DESC) RANK FROM TMP_TABLE;


이런식으로 사용



2. 페이지에따른 값을 가져와야하기 떄문에 BETWEEN  함수 사용

한 화면에서 보여줄 데이터값은 10개 때문에 1페이지에선 1~10까지에 데이터, 2페이지엔 11~20까지의 데이터 이런식으로 

데이터를 가져와야함 =>  그래서 BETWEEN 사용


그래서 시작값과 끝값을 계산해야함. (페이징 쿼리를 참고였다.)

controller에서



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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// 사원정보 jqgrid, json으로 변형한 데이터
        @RequestMapping(value = "/gridView.do", method = RequestMethod.POST)
        @ResponseBody
        // json으로 변환
        public HashMap<String, Object> gridView(
                EmployeeVO vo,
                Model model,
                @RequestParam(value = "page", required = false, defaultValue = "1"int page,
                @RequestParam(value = "rows", required = false, defaultValue = "20"int rows,
                @RequestParam(value = "total", required = false, defaultValue = "20"int total,
                @RequestParam(value = "records", required = false, defaultValue = "20"int records,
                @RequestParam(value = "sord", required = false, defaultValue = "sort"String sord,
                @RequestParam(value = "sidx", required = falseString sidx) {
 
            logger.info("사원정보jqgrid");
             System.out.println("records :"+records+" page :"+page+", rows :"+rows+", total :"+total+", sord :"+sord+", sidx :"+sidx);
            // records : 20,page :1, rows :5, total :20, sord :asc, sidx:name
             

//startCount와 endCount값을 계산
             int startCount = (page - 1* rows + 1;
           int endCount = page * rows;  
             
            List<EmployeeVO> empVo = null;
            // empVo = employeeServiceimp.AllEmployeeList();

//map에 넣어 xml에서 매핑
            HashMap<String, Object> order = new HashMap<String, Object>();
            order.put("SORD", sord);
            order.put("SIDX", sidx);
            order.put("startCount", startCount);
          order.put("endCount", endCount);
            
            
            
 
            empVo = employeeServiceimp.AllEmployeeList(order);
 
            HashMap<String, Object> resMap = new HashMap<String, Object>();
            total = employeeServiceimp.totalCount(rows);
            records = employeeServiceimp.totalRecords();
 
            resMap.put("page", page);
            resMap.put("total", total); // 총페이지
            resMap.put("records", records); // 총레코드
            resMap.put("rows", empVo);
            
            return resMap;
        }

cs






완성~~  이제 페이지를 넘기면은 해당 페이지에따른 값을 가져와서 뿌릴거임





gridView




- 사원번호,이름,상세 검색







-----------------------------------------------------------------------------------------------------------------------------------------------------

2016.12.21


- 총 count구하기 


사용자 이름,사원번호,상세검색에서 페이징 구현중 records의 값을 따로 구해야한는것을 깨닳음 


int records = emp.size(); 로 했는데 emp의 갯수를 between start and end 으로 설정을 해놔서 (한페이지에 10개의 데이터가 보이도록) 

 검색된 데이터는 더 있더라고 10개의 데이터를 담기때문에 records=10으로 값이 주어졌었다. 

그래서 count를 할수있는 쿼리를 찾다가 count over()을 발견...



참고 : http://javaexpert.tistory.com/503


1
2
3
4
5
6
7
SELECT *
    FROM (SELECT ROW_NUMBER () OVER 
    (ORDER BY 정렬 AS ROW_NUMBER,
    COUNT (*) OVER () AS row_count,
    검색조건)
    WHERE 번호 BETWEEN 시작번호 AND 끝번호 
 
cs


1. ROW_NUMBER () OVER (정렬) 을 통해 row번호를 매겨줌
2. COUNT (*) OVER (),조건 을 이용해 뒤에 조건을통해 검색된 데이터의 총 갯수를 구해줌
3. 번호 BETWEEN 시작번호 AND 끝번호 : 검색된 값들중 몇번부터 몇번의 데이터를 꺼낼것인지 지정


※ row_count을 담은 vo 혹은 map를 미리 설정해서 담아야한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    <select id="userSearchDcode" resultMap="EmpSearchMapper"
        parameterType="map">
        
    SELECT *
    FROM (SELECT ROW_NUMBER () OVER 
    (ORDER BY ${sidx}
        <if test="sord == ('asc')">ASC</if>
        <if test="sord == ('desc')">DESC</if>
        ) AS ROW_NUMBER,
    COUNT (*) OVER () AS row_count,
    E.ENAME,E.NAME,E.DCODE,BIREDAY,
    DE.DESCRIPTION AS DEPARTMENT,
    PO.DESCRIPTION AS POSITION,
    PR.DESCRIPTION AS PRESENT
    FROM CODE_TABLE PO,CODE_TABLE PR, CODE_TABLE DE ,EMPLOYEE E
    WHERE DE.CODE = E.DEPARTMENT AND
    PO.CODE = E.POSITION AND
    PR.CODE = E.PRESENT
    AND DCODE like '%'||${DCODE}||'%')
    WHERE ROW_NUMBER BETWEEN  ${startCount} AND ${endCount}
        
    </select> 
cs












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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
- controller
@RequestMapping(value = "/userSearchName.do", method = RequestMethod.POST, produces = "application/json; charset=UTF-8")
        public @ResponseBody
        HashMap<String, Object> userSearchName(
                @RequestParam String NAME,
                @RequestParam(value = "page", required = falseint page,             // 그리드에서 전송된 page,rows,sort,sidx를 받자
                @RequestParam(value = "rows", required = falseint rows,
                @RequestParam(value = "sord", required = false, defaultValue = "sort"String sord,
                @RequestParam(value = "sidx", required = falseString sidx) {
        
             
             int startCount = (page - 1* rows + 1;    // 시작번호와 끝번호를 계산
             int endCount = page * rows;  
             
            
            Map<String, Object> map = new HashMap<>();   // 쿼리에서필요한 데이터를 map에 담음
            map.put("NAME", NAME);
            map.put("sidx", sidx);
            map.put("sord", sord);
            map.put("startCount", startCount);
            map.put("endCount", endCount);
            
            List<Emp_SearchVo> emp = null;
            emp = employeeServiceimp.userSearchName(map);  //검색조건을 담은map을 파라미터로 쿼리를 실행후 결과를 list에담음
            
            HashMap<String, Object> resMap = new HashMap<String, Object>(); //다시 그리드로 리턴하기위한 값들을 담기위해 map선언
            
            int records;   // 총 데이터수 
            if(emp.size()==0){  // 검색된 값이 없으면 총 데이터의수를 0으로 
                records = 0;
            }else{
                
                records = emp.get(0).getRow_count();  // 검색된값이 1개라도 있으면 list에담겨있는 Row_count꺼내 records에 담음
            }
            int total = (records/rows)+1// 총 페이지수를 계산
            
            if(records==10){ // 총 레코드의수가 10개일경우 10/10(rows:한 화면에 보여줄 데이터수)를 나누면 1이다 그런데 위에서 계산후에 1을 더하니까 그냥 
                total=1;     //  레코드수가 10이면 total의수를 1로 
            }
            
            resMap.put("page", page);
            resMap.put("total", total); // 총페이지
            resMap.put("records", records); // 총레코드
            resMap.put("rows", emp);
            
    
            
            return resMap;
 
        }
 
cs



'개발 > jqgrid' 카테고리의 다른 글

jqgrid 기본설정,옵션  (0) 2016.12.22
★jqgrid 페이징 분리  (0) 2016.12.14
jqgrid loadComplete , gridComplete  (0) 2016.12.08
그리드 리로드 + 체크박스 유지  (0) 2016.12.07
JQGRID  (0) 2016.12.06

댓글