본문 바로가기
IT

스프링 페이징 처리..

by 바다하늘구름사랑 2022. 3. 17.

이번에 sybase 데이타베이스를 사용하게 되었다.

프로젝트는 일반 스프링 프로젝트로 보면 된다.

그런데 왜 sybase를 사용하냐고?

그냥 커스터머가 원하니까....

 

그런데 sybase는 MS-sql 계열이면서

스스로 RDB 로서 자기를 쓰지 말라고 하고 있다.

 

그래서 그런지 여러가지 면에서 

불편한점이 참 많다

 

일단 서브쿼리내에서 order by 가 안된다

그리고 페이징 쿼리가 매우 불편하고

최적화가 매우 어렵다

 

일반 프로젝트에서 페이징 쿼리가 되지않는것이

얼마나 불편할지는 개발자라면 모두 알 것이라고 본다.

 

여러가지를 고민하다가 두가지 방안을 사용해보았다

구글링 해봐도 별다른 수가 없다.

물론 밑에 제시하는 방법도 구글링의 결과물임을 부인할순 없지만

다 먹고 살려니 에휴 ㅡㅡ

 

1) top 이용한 방식

top 은 우리가 예상한대로 절대로 동작하지 않는다

order by , 잘라오기 등 제대로 동작하기를 기대하면 안된다

 

[1]

SELECT ${getdata2}
FROM  
(
SELECT ${getdata}
FROM  
(
SELECT  top ${pageRowCnt} --> sybase 에서만 사용
'' AS g2check
, T.g2total

//--||-----------[[    Custom 쿼리    ]]----------------------------------------||--//

,  R.*
, D.TITLE AS GRADE_NM
FROM  USERS R
LEFT OUTER JOIN CODE D ON D.ID =  R.GRADE

//--||-------------------------------------------------------------------------||--//

,  
(
SELECT COUNT(*) AS g2total
FROM
(   

//--||-----------[[    Custom 쿼리    ]]----------------------------------------||--//

SELECT  R.*
, D.TITLE AS GRADE_NM
FROM  USERS R
LEFT OUTER JOIN CODE D ON D.ID =  R.GRADE

//--||-------------------------------------------------------------------------||--//

) TOT
WHERE  1 = 1
${keycheck}
${simplesearch}
${filter}  
     ) T
WHERE  1 = 1
<if test="g2keymin != null and g2keymin != ''.toString()">
AND ${g2key} &lt; ${g2keymin} --> sybase 에서만 사용
</if>
${keycheck}
${simplesearch}
${filter}
   ) OOO
   ${groupby}
  ) IMS_XXX  
<if test="g2key != null and g2key != ''.toString()">
ORDER BY ${g2key} DESC --> sybase 에서만 사용
</if>

 

내가 사용하는 그리드의 쿼리이다

그중에 sybase에서만 사용하는 부분은 표시했다.

내용인즉 top으로 원하는 만큼의 로우수를 읽어온다

top으로 읽어오는 조건을 만들어 가져오도록 했다

조건을 만들어주기 위해서는

table에 auto increment 로 key 필드를 하나 만들어주고

이 필드를 이용하여 마지막 키이와 이전 키이등의 값을 가지고 처리한다

현재는 미완성이다.

서브쿼리로 원하는 페이지 top으로 가져와서 마지막 데이타를 읽어서 조건값으로 주는 처리를 하면

페이징 쿼리가 되지 않을까 싶다. 

다음 쿼리 때문에 이 부분은 미완성으로 두고 개발을 중단했다.

 

[2]

 

SELECT ${getdata2}
FROM  
(
SELECT ${getdata}
FROM  
(
SELECT  '' AS g2check
, T.g2total

//--||-----------[[    Custom 쿼리    ]]----------------------------------------||--//

,  R.*
, D.TITLE AS GRADE_NM
FROM  USERS R
LEFT OUTER JOIN CODE D ON D.ID =  R.GRADE

//--||-------------------------------------------------------------------------||--//

,  
(
SELECT COUNT(*) AS g2total
FROM
(   

//--||-----------[[    Custom 쿼리    ]]----------------------------------------||--//

SELECT  R.*
, D.TITLE AS GRADE_NM
FROM  USERS R
LEFT OUTER JOIN CODE D ON D.ID =  R.GRADE

//--||-------------------------------------------------------------------------||--//

) TOT  
WHERE  1 = 1
${keycheck}
${simplesearch}
${filter}  
     ) T
WHERE  1 = 1
${keycheck}    
${simplesearch}
${filter}
   ) OOO
   ${groupby}
  ) IMS_XXX  

 

아주 평범하다

그냥 쿼리만 선언해주고 페이징 처리 부분은 없다

이건 sqlsessiontemplate 의 selectList 의 rowbounds를 이용해서 처리한다.

 

int rowfirst  = Integer.parseInt((String)hm.get("rowFirst"));
int pagerowcnt  = Integer.parseInt((String)hm.get("pageRowCnt"));
RowBounds rowBounds = new RowBounds(rowfirst,pagerowcnt);
return sqlSession.selectList(mapper + ".listex", hm, rowBounds);

 

위와 같다.

우선은 sqlSession을 선언하고 sqlSessionTemplate 를 만들고 나서 

사용해야겠지만, 내 프레임은 이미 작동중이니

서비스 부분만 바꿔서 페이징 쿼리를 수행했다.

잘 작동한다.

 

RowBound는 첫번쨰 인자수만큼 건너뛰고 두번쨰 인수수만큼 읽어오도록 한다.

쉽고 또한 간단히 구현이 가능하고

범용성도 좋다.

다만 치명적은 문제는 데이타수가 많으면 뒤로 가면 갈수록 거북이가 된다는 점

메모리 사용이 많아진다는 점이다.

그래서 이 방법은 페이징 쿼리가 제대로 되지 않는 데이타베이스의 경우에 

대안으로 사용하는 것이 좋을듯 하다.

 

어찌되었든 sybase는 RDB로 사용하지 않는 것이 좋을듯 하다.