페이지 기술 원리와 구현된 Java+Oracle 코드 구현 페이지 나누기(2)

전편페이지 나누기 기술 원리와 실현의 페이지 나누기의 의미 및 방법(一)에 이어 본편은 페이지 나누기 기술을 계속 분석한다.전편에서 말한 것은 페이지 기술의 간단한 원리와 소개인데 이 글은 페이지 기술의 코드 실현을 깊이 있게 분석한다.
전편에서 마지막으로 페이지를 나누는 가장 좋은 실현은 데이터베이스 층에서 페이지를 나누는 것이고 서로 다른 데이터베이스는 서로 다른 페이지를 나누는 것이다. 예를 들어 Oracle은 3층 sql 플러그인으로 페이지를 나누는 것이고 MySQL은limit 키워드로 이루어진다(전편에서 언급했다).
이 글은 Java+Oracle을 바탕으로 코드 층의 실현을 설명한다.
평소에 우리가 페이지에서 본 바와 같이 페이지를 나눌 때 돌아오는 것은 조회의 결과집(List)뿐만 아니라 전체 페이지 수(pageNum), 현재 몇 페이지(pageNo) 등의 정보도 포함하기 때문에 우리는 조회 결과의 페이지 모델 클래스를 봉인한다. 코드는 다음과 같다.

package kane;
import java.util.List;
public class PageModel<E> {
 private List<E> list;
 private int pageNo;
 private int pageSize;
 private int totalNum;
 private int totalPage;

 public List<E> getList() {
 return list;
 }

 public void setList(List<E> list) {
 this.list = list;
 }

 public int getPageNo() {
 return pageNo;
 }

 public void setPageNo(int pageNo) {
 this.pageNo = pageNo;
 }

 public int getPageSize() {
 return pageSize;
 }

 public void setPageSize(int pageSize) {
 this.pageSize = pageSize;
 }

 public int getTotalNum() {
 return totalNum;
 }

 public void setTotalNum(int totalNum) {
 this.totalNum = totalNum;
 setTotalPage((getTotalNum() % pageSize) == 0 ? (getTotalNum() / pageSize)
 : (getTotalNum() / pageSize + 1));
 }

 public int getTotalPage() {
 return totalPage;
 }

 public void setTotalPage(int totalPage) {
 this.totalPage = totalPage;
 }

 //  
 public int getFirstPage() {
 return 1;
 }

 //  
 public int getLastPage() {
 return totalPage;
 }

 //  
 public int getPrePage() {
 if (pageNo > 1)
 return pageNo - 1;
 return 1;
 }

 //  
 public int getBackPage() {
 if (pageNo < totalPage)
 return pageNo + 1;
 return totalPage;
 }

 //  ' ' ‘ ' 
 public String isPreable() {
 if (pageNo == 1)
 return "disabled";
 return "";
 }

 //  ' ' ‘ ' 
 public String isBackable() {
 if (pageNo == totalPage)
 return "disabled";
 return "";
 }
}

그 중에서 범용형을 사용하는 것은 이 페이지 클래스를 다시 사용할 수 있도록 하기 위해서이다. 예를 들어 사용자를 조회할 때 User 대상을 봉인할 수 있고, 재무 중의 흐름표를 조회할 때 흐름표 FlowCard 클래스를 봉인할 수 있다.
우리는 쿼리 사용자를 예로 들면, 사용자가 쿼리 조건을 선택하면, 먼저 Servlet을 호출하여 쿼리 파라미터를 얻은 다음, 업무 논리층에 페이지 봉인 결과 클래스를 요청합니다.업무 논리는 Dao층을 호출하여 결과 집합을 얻고 기록된 숫자를 봉인하여 성분 페이지류를 얻는다.마지막으로 Servlet은 결과를 jsp 페이지에 표시합니다.
먼저 Servlet에 대해 설명합니다. 코드는 다음과 같습니다.

package kane;
import java.io.*;
import java.util.*;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kane.UserInfo;
import kane.UserInfoManage;
import kane.PageModel;

public class UserBasicSearchServlet extends HttpServlet {
 private static final long serialVersionUID = 1L;
 private int pageSize = 0;

 @Override
 public void init(ServletConfig config) throws ServletException {
 pageSize = Integer.parseInt(config.getInitParameter("pageSize"));
 }

 @Override
 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
 throws ServletException, IOException {
 doPost(req, resp);
 }

 @Override
 protected void doPost(HttpServletRequest req, HttpServletResponse resp)
 throws ServletException, IOException {
 // 1. 
 int pageNo = Integer.parseInt(req.getParameter("pageNo"));
 String sex = req.getParameter("gender");
 String home = req.getParameter("newlocation");
 String colleage = req.getParameter("colleage");
 String comingyear = req.getParameter("ComingYear");

 UserInfo u = new UserInfo();
 u.setSex(sex);
 u.setHome(home);
 u.setColleage(colleage);
 u.setCy(comingyear);

 // 2. 
 UserInfoManage userInfoManage = new UserInfoManage();
 PageModel<UserInfo> pagination = userInfoManage.userBasicSearch(u,
 pageNo, pageSize);
 List<UserInfo> userList = pagination.getList();

 // 3. 
 StringBuffer resultXML = new StringBuffer();
 try {
 resultXML.append("<?xml version='1.0' encoding='gb18030'?>/n");
 resultXML.append("<root>/n");
 for (Iterator<UserInfo> iterator = userList.iterator(); iterator
 .hasNext();) {
 UserInfo userInfo = iterator.next();
 resultXML.append("<data>/n");
 resultXML.append("/t<id>" + userInfo.getId() + "</id>/n");
 resultXML.append("/t<truename>" + userInfo.getTruename()
 + "</ truename >/n");
 resultXML.append("/t<sex>" + userInfo.getSex() + "</sex>/n");
 resultXML.append("/t<home>" + userInfo.getHome() + "</home>/n");
 resultXML.append("</data>/n");
 }
 resultXML.append("<pagination>/n");
 resultXML.append("/t<total>" + pagination.getTotalPage()
 + "</total>/n");
 resultXML.append("/t<start>" + pagination.getFirstPage()
 + "</start>/n");
 resultXML.append("/t<end>" + pagination.getLastPage() + "</end>/n");
 resultXML.append("/t<pageno>" + pagination.getPageNo()
 + "</pageno>/n");
 resultXML.append("</pagination>/n");

 resultXML.append("</root>/n");
 } catch (Exception e) {
 e.printStackTrace();
 }
 writeResponse(req, resp, resultXML.toString());

 }

 public void writeResponse(HttpServletRequest request,
 HttpServletResponse response, String result) throws IOException {
 response.setContentType("text/xml");
 response.setHeader("Cache-Control", "no-cache");
 response.setHeader("Content-Type", "text/xml; charset=gb18030");
 PrintWriter pw = response.getWriter();
 pw.write(result);
 pw.close();
 }
}
여기서 User 객체 코드는 다음과 같습니다.

package kane;
import java.util.Date;
public class UserInfo {
 private int id;
 private String username;
 private String password;
 private String truename;
 private String sex;
 private Date birthday;
 private String home;
 private String colleage;
 private String comingYear;

 public int getId() {
 return id;
 }

 public void setId(int id) {
 this.id = id;
 }

 public String getUsername() {
 return username;
 }

 public void setUsername(String username) {
 this.username = username;
 }

 public String getPassword() {
 return password;
 }

 public void setPassword(String password) {
 this.password = password;
 }

 public String getTruename() {
 return truename;
 }

 public void setTruename(String truename) {
 this.truename = truename;
 }

 public String getSex() {
 return sex;
 }

 public void setSex(String sex) {
 this.sex = sex;
 }

 public Date getBirthday() {
 return birthday;
 }

 public void setBirthday(Date birthday) {
 this.birthday = birthday;
 }

 public String getHome() {
 return home;
 }

 public void setHome(String home) {
 this.home = home;
 }

 public String getColleage() {
 return colleage;
 }

 public void setColleage(String colleage) {
 this.colleage = colleage;
 }

 public String getCy() {
 return comingYear;
 }

 public void setCy(String cy) {
 this. comingYear= cy;
 }
}
다음은 비즈니스 논리 레이어 코드입니다. 코드는 다음과 같습니다.

package kane;
import java.sql.Connection;

import kane.DBUtility;
import kane.PageModel;

public class UserInfoManage {
 private UserInfoDao userInfoDao = null;

 public UserInfoManage () {
 userInfoDao = new UserInfoDao();
 }

 public PageModel<UserInfo> userBasicSearch(UserInfo u, int pageNo,
 int pageSize) throws Exception {
 Connection connection = null;
 PageModel<UserInfo> pagination = new PageModel<UserInfo>();
 try {
 connection = DBUtility.getConnection();
 DBUtility.setAutoCommit(connection, false);
 pagination.setList(userInfoDao.getUserList(u, pageNo, pageSize));
 pagination.setPageNo(pageNo);
 pagination.setPageSize(pageSize);
 pagination.setTotalNum(userInfoDao.getTotalNum(u));
 DBUtility.commit(connection);
 } catch (Exception e) {
 DBUtility.rollBack(connection);
 e.printStackTrace();
 throw new Exception();
 } finally {
 DBUtility.closeConnection();
 }
 return pagination;
 }
}
여기서 DBUtility는 데이터베이스의 연결 패키지 클래스입니다.
마지막으로 Dao 레이어 코드 구현입니다. 코드는 다음과 같습니다.

package kane;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import kane.UserInfo;
import kane.DBUtility;

public class UserInfoDao {

 public List<UserInfo> getUserList(UserInfo userInfo, int pageNo,
 int pageSize) throws Exception {
 PreparedStatement pstmt = null;
 ResultSet rs = null;
 List<UserInfo> userList = null;
 try {
 String sql = "select * from(select rownum num,u.* from(select * from user_info where sex = ? and home like '"
 + userInfo.getHome()
 + "%"
 + "' and colleage like '"
 + userInfo.getColleage()
 + "%"
 + "' and comingyear like '"
 + userInfo.getCy()
 + "%"
 + "' order by id) u where rownum<=?) where num>=?";
 userList = new ArrayList<UserInfo>();
 Connection conn = DBUtility.getConnection();
 pstmt = conn.prepareStatement(sql);
 pstmt.setString(1, userInfo.getSex());
 pstmt.setInt(2, pageNo * pageSize);
 pstmt.setInt(3, (pageNo - 1) * pageSize + 1);
 rs = pstmt.executeQuery();
 while (rs.next()) {
 UserInfo user = new UserInfo();
 user.setId(rs.getInt("id"));
 user.setTruename(rs.getString("truename"));
 user.setSex(rs.getString("sex"));
 user.setHome(rs.getString("home"));
 userList.add(user);
 }
 } catch (SQLException e) {
 e.printStackTrace();
 throw new Exception(e);
 } finally {
 DBUtility.closeResultSet(rs);
 DBUtility.closePreparedStatement(pstmt);
 }
 return userList;
 }

 public int getTotalNum(UserInfo userInfo) throws Exception {
 PreparedStatement pstmt = null;
 ResultSet rs = null;
 int count = 0;
 try {
 String sql = "select count(*) from user_info where sex=? and home like '"
 + userInfo.getHome()
 + "%"
 + "' and colleage like '"
 + userInfo.getColleage()
 + "%"
 + "' and comingyear like '"
 + userInfo.getCy()+ "%" + "'";
 Connection conn = DBUtility.getConnection();
 pstmt = conn.prepareStatement(sql);
 pstmt.setString(1, userInfo.getSex());
 rs = pstmt.executeQuery();
 if (rs.next()) {
 count = rs.getInt(1);
 }
 } catch (SQLException e) {
 e.printStackTrace();
 throw new Exception(e);
 } finally {
 DBUtility.closeResultSet(rs);
 DBUtility.closePreparedStatement(pstmt);
 }
 return count;
 }
}
마지막으로 servlet은 얻은 결과를 jsp 페이지에 되돌려 줍니다.
참고: 여기서 DBUtility 코드는 다음과 같이 데이터베이스 연결 작업을 패키지화하는 코드입니다.

package kane;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DBUtility {
 private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();

 public static Connection getConnection() {
 Connection conn = null;
 conn = threadLocal.get();
 if (conn == null) {
 try {
 Class.forName("oracle.jdbc.driver.OracleDriver");
 conn = DriverManager.getConnection(
 "jdbc:oracle:thin:@localhost:1521:oracle", "admin",
 "admin");
 threadLocal.set(conn);
 } catch (ClassNotFoundException e) {
 e.printStackTrace();
 } catch (SQLException e) {
 e.printStackTrace();
 }
 }
 return conn;
 }

 //  Connection 
 public static void setAutoCommit(Connection conn, Boolean flag) {
 try {
 conn.setAutoCommit(flag);
 } catch (SQLException e) {
 e.printStackTrace();
 }
 }

 //  
 public static void commit(Connection conn) {
 try {
 conn.commit();
 } catch (SQLException e) {
 e.printStackTrace();
 }
 }

 //  Connection 
 public static void rollBack(Connection conn) {
 try {
 conn.rollback();
 } catch (SQLException e) {
 e.printStackTrace();
 }
 }

 //  Connection、PreparedStatement、ResultSet 
 public static void closeConnection() {
 Connection conn = threadLocal.get();
 try {
 if (conn != null) {
 conn.close();
 conn = null;
 threadLocal.remove();
 }
 } catch (SQLException e) {
 e.printStackTrace();
 }

 }

 public static void closePreparedStatement(PreparedStatement pstmt) {
 try {
 if (pstmt != null) {
 pstmt.close();
 pstmt = null;
 }
 } catch (SQLException e) {
 e.printStackTrace();
 }
 }

 public static void closeResultSet(ResultSet rs) {
 try {
 if (rs != null) {
 rs.close();
 rs = null;
 }
 } catch (SQLException e) {
 e.printStackTrace();
 }
 }
}

ThreadLocal을 사용하는 것은 업무의 일치를 확보하기 위해 같은 라인의 모든 데이터베이스 작업이 같은 연결을 사용하도록 합니다.
여기에 간단한 코드가 실현되면 완성된다.
이상은 본문의 전체 내용입니다. 여러분의 학습에 도움이 되고 저희를 많이 응원해 주십시오.

좋은 웹페이지 즐겨찾기