백엔드/Database

Jdbc(ojdbc) 페이징 쿼리 | TIL_138

ran4 2022. 8. 29. 21:43

https://www.youtube.com/playlist?list=PLq8wAnVUcTFWxwoc41CqmwnO-ZyRDL0og

강의를 듣고 정리한 내용입니다

 


 

페이징을 위한 쿼리 만들기

1부터 10까지의 ROWNUM을 검색하는 SQL문

SELECT ROWNUM, NOTICE. * FROM NOTICE

WHERE ROWNUM BETWEEN 1 AND 10;

 

위 구문의 문제점 : BETWEEN 2 AND 10;인 경우 조회되지 않는다

 

해결법 : 서브쿼리를 이용한다(안에서 만들어진 번호)

SELECT * FROM ( SELECT ROWNUM NUM, NOTICE. * FROM NOTICE)

WHERE NUM BETWEEN 2 AND 10;

 

 

 

최신글 순서대로 정렬하기

SQL문

SELECT * FROM NOTICE ORDER BY REGDATE DESC;

 

서브 쿼리 활용(제대로 출력되지 않음)

SELECT * FROM (SELECT ROWNUM NUM, NOTICE.* FROM NOTICE ORDER BY REGDATE DESC)

WHERE NUM BETWEEN 1 AND 10;

-> ROWNUM을 구한 다음에 정렬되기 때문에 일련번호가 엉키게 된다

-> 서브쿼리가 한 개 더 필요하다

 

 

서브 쿼리 활용(바꾼 버전)

SELECT * FROM (SELECT ROWNUM NUM, N.* FROM

(SELECT * FROM NOTICE ORDER BY REGDATE DESC) N //N은 Notice의 별칭

) WHERE NUM BETWEEN 11 AND 20;

 

 

 

페이징 쿼리 이용하기


만든 서브 쿼리를 NoticeService에 넣고 코드를 수정한다

1. getList에 int page값을 넣어준다

public List<Notice> getList(int page) throws Exception

String sql = "SELECT * FROM (" + " SELECT ROWNUM NUM, N.* FROM (" +
" SELECT * FROM NOTICE ORDER BY REGDATE DESC" + " ) N " +
") " + "WHERE NUM BETWEEN ? AND ?";

 

 

2. 위치 홀더인 “?“가 있기 때문에 Statement를 Preparedstatement로 바꾼다

PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, start); //값을 할당한다
pstmt.setInt(2, end);
ResultSet rs = pstmt.executeQuery();

 

 

-> pstmt에서 sql을 불러왔기 때문에 executeQuery()에서는 sql을 없애야 한다

 

 

3. start와 end 값을 넣어준다

int start = 1 + (page - 1) * 10; //등차수열 활용 1, 11, 21, 31

int end = 10 * page; //10, 20, 30

 

 

NoticeService 바뀐코드 전체 정리 

더보기
public List<Notice> getList(int page) throws ClassNotFoundException, SQLException {

int start = 1 + (page - 1) * 10; //등차수열 활용 1, 11, 21, 31
int end = 10 * page; //10, 20, 30

String sql = "SELECT * FROM (" + " SELECT ROWNUM NUM, N.* FROM (" +
" SELECT * FROM NOTICE ORDER BY REGDATE DESC" + " ) N " +
") " + "WHERE NUM BETWEEN ? AND ?";

Class.forName(driver);
Connection conn = DriverManager.getConnection(url, userId, pwd);
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, start); 
pstmt.setInt(2, end);
ResultSet rs = pstmt.executeQuery();

 

 

NoticeConsole

service.getList(); 괄호안에 값을 할당하여 출력을 확인한다

List<Notice> list = service.getList(1);

List<Notice> list = service.getList(2);

 

 

 

목록을 위한 View 생성하기

view를 만드는 sql문

CREATE VIEW NOTICE_VIEW AS
SELECT * FROM (SELECT ROWNUM NUM, N.* FROM
(SELECT * FROM NOTICE ORDER BY REGDATE DESC) N(별칭)
);

VIEW를 이용하면 긴 서브쿼리 대신 코드 한 줄로도 조회가 가능하다
SELECT * FROM NOTICE_VIEW WHERE NUM BETWEEN 11 AND 20;

 

현재 자바 코드의 문제점 : 문자열들을 더하는 작업이 많고 내려쓰기가 너무 많다

-> NoticeService.java 코드 수정

 

수정 전

String sql = "SELECT * FROM (" + " SELECT ROWNUM NUM, N.* FROM (" +

" SELECT * FROM NOTICE ORDER BY REGDATE DESC" + " ) N " +

") " + "WHERE NUM BETWEEN ? AND ?";

 

 

수정 후

String sql = "SELECT * FROM NOTICE_VIEW WHERE NUM BETWEEN ? AND ?";

 

 

이전 / 다음 구현하기

1. 페이지를 기록하기 위한 상태 변수 생성

int page;

 

 

2. NoticeConsole이 페이지의 상태값을 가지고 있도록 선언 한다 

private int page;

public NoticeConsole() {
service = new NoticeService();
page = 1;
}

 

 

3. Program5로 돌아와서 switch문의 case 2와 case 3를 수정한다

while(true) {
console.printNoticeList();
int menu = console.inputNoticeMenu();

switch(menu) {
case 1 : //상세조회
break;

case 2 : //이전
console.movePrevList();
break;

case 3 : //다음
console.moveNextList();
break;

 

 

4. NoticeConsole movePrevList() 메서드 생성

public void movePrevList() {
if(page == 1) {
System.out.println("이전 페이지가 없습니다.");
return;
}
page--;
}

// moveNextList() 메서드
public void moveNextList() {
page++;
}

 

 

마지막 페이지를 알 수 없기에 마지막 페이지를 구하는 로직이 필요하다

-> printNoticeList() 메서드의 list값을 page로 바꾼다

List<Notice> list = service.getList(page);