티스토리 뷰

반응형

목표: getNoticeList의 JDBC 코드를 구현한다.

기존의 NoticeListController.java에서 사용하던 쿼리문을 모두 NoticeService.java로 옮겨서 구현한다.
- NoticeListController.java : 사용자와의 입력과 출력(사용자와 상호작용)
- NoticeService.java :서비스 모듈을 따로 서비스만 전문으로 기능

코드:

- NoticeListController.java

package com.newlecture.web.controller;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.newlecture.web.entity.Notice;
import com.newlecture.web.service.NoticeService;

@WebServlet("/notice/list")
public class NoticeListController extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		/* NoticeService 객체를 만들고 함수를 사용 */
		NoticeService service = new NoticeService();
		List<Notice> list = service.getNoticeList(); 
		
		request.setAttribute("list", list);
		
		request.getRequestDispatcher("/WEB-INF/view/notice/list.jsp").forward(request, response);

	}
}

 

- NoticeListController.java 일부

		/* NoticeService 객체를 만들고 함수를 사용 */
		NoticeService service = new NoticeService();
		List<Notice> list = service.getNoticeList(); 

쿼리문은 모두 삭제하고 NoticeService 객체를 만들고 getNoticeList 함수를 사용한다.

 

- NoticeService.java

package com.newlecture.web.service;

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

import com.newlecture.web.entity.Notice;

public class NoticeService {
	public List<Notice> getNoticeList(){
		
		return getNoticeList("title", "", 1);
	}

	public List<Notice> getNoticeList(int page){
			
		return getNoticeList("title", "", page);
	}

	public List<Notice> getNoticeList(String field/*TITLE, WRITER_ID */, String query/*A*/, int page){
		
		List<Notice> list = new ArrayList<>();
		/* field는 문자열의 값으로 들어가지 않기 때문에 ?로 채울수 없다. */
		String sql = "SELECT * FROM( "
				+ "SELECT ROWNUM NUM, N.* "
				+ "FROM (SELECT * FROM NOTICE WHERE "+field+" LIKE ? ORDER BY REGDATE DESC) N "
				+ ") "
				+ "WHERE NUM BETWEEN ? AND ?";
		
		//1, 11, 21, 31, .. -> an = 1+(page-1)*10
		// 10, 20, 30, 40 -> page*10
			
		String url = "jdbc:oracle:thin:@localhost:1521/XE";

		try {
			Class.forName("oracle.jdbc.driver.OracleDriver");
			Connection con = DriverManager.getConnection(url, "programmers", "111111");
			/* ?가 포함된 쿼리문을 사용 할 겨웅에는 preparedStatement를 사용한다. */
			PreparedStatement st = con.prepareStatement(sql);
			st.setString(1, "%"+query+"%");
			st.setInt(2, 1+(page-1)*10);
			st.setInt(3, page*10);
			
			ResultSet rs = st.executeQuery();

			while(rs.next()){
				int id = rs.getInt("ID");
				String title = rs.getString("TITLE");
				String writerId = rs.getString("WRITER_ID");
				Date regdate = rs.getDate("REGDATE");
				String hit = rs.getString("HIT");
				String files = rs.getString("FILES");
				String content = rs.getString("CONTENT");
				
				/* Notice라는 개체를 이용해서 */
				Notice notice = new Notice(
						id,
						title,
						writerId,
						regdate,
						hit,
						files,
						content
					);
				list.add(notice);	
			}
			rs.close();
			st.close();
			con.close();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return list;
	}
	
	public int getNoticeCount() {
		
		return getNoticeCount("title", "");
	}
	
	public int getNoticeCount(String field, String query) {
		
		return 0;
	}
	
	public Notice getNotice(int id) {
		String sql = "SELECT * FROM NOTICE WHERE ID=?";
		
		return null;
	}
	
	public Notice getNextNotice(int id) {
		String sql = "SELECT * FROM NOTICE "
				+ "WHERE ID  = ( "
				+ "SELECT ID FROM NOTICE "
				+ "WHERE REGDATE > (SELECT REGDATE  FROM NOTICE WHERE ID=3) "
				+ "AND ROWNUM = 1)";
		return null;
	}

	public Notice getPrevNotice(int id) {
		String sql = "SELECT ID FROM (SELECT * FROM NOTICE ORDER BY REGDATE DESC) "
				+ "WHERE REGDATE < (SELECT REGDATE FROM NOTICE WHERE ID=5) AND ROWNUM = 1";
		return null;
	}
}

- NoticeService.java 일부

public List<Notice> getNoticeList(String field/*TITLE, WRITER_ID */, String query/*A*/, int page){
	List<Notice> list = new ArrayList<>();
/* field는 문자열의 값으로 들어가지 않기 때문에 ?로 채울수 없다. */
String sql = "SELECT * FROM( "
		+ "SELECT ROWNUM NUM, N.* "
		+ "FROM (SELECT * FROM NOTICE WHERE "+field+" LIKE ? ORDER BY REGDATE DESC) N "
		+ ") "
		+ "WHERE NUM BETWEEN ? AND ?";

//1, 11, 21, 31, .. -> an = 1+(page-1)*10
// 10, 20, 30, 40 -> page*10
	
String url = "jdbc:oracle:thin:@localhost:1521/XE";
	try {
	Class.forName("oracle.jdbc.driver.OracleDriver");
	Connection con = DriverManager.getConnection(url, "programmers", "111111");
	/* ?가 포함된 쿼리문을 사용 할 겨웅에는 preparedStatement를 사용한다. */
	PreparedStatement st = con.prepareStatement(sql);
	st.setString(1, "%"+query+"%");
	st.setInt(2, 1+(page-1)*10);
	st.setInt(3, page*10);
	ResultSet rs = st.executeQuery();

쿼리문에서 가장 안쪽의 서브 쿼리에서 먼저 필터링을 하는 것이 가장 효율적인 방법이다.
그래서 WHERE절을 이용해 field에서 query를 필터링한다.
WHERE절 이후의 "+field+"는 아래의 preparedStatement를 이용한? 물음표를 사용할 수가 없다. field는 문자열의 값으로 들어가지 않기 때문이다. 
    예) WHERE ? LIKE에서? 가 TITLE이라면 실제 쿼리문에는 WHERE 'TITLE' LIKE 가 된다. 그래서 어쩔 수 없이 위와    같이 코드를 사용해야 한다.
나머지 변수부분들은 preparedStatement를 이용해? 물음표로 값을 넣고, 수식을 넣어서 구현한다.

결과:

Controller와 DataService를 분리한 후에도 정상적으로 잘 작동 중이다.
이렇게 Controller에서는 사용자와의 상호작용을 하면서 코드가 더 간단하고 간결해졌다.
DataService에서는 서비스만 전문적으로 하면서 JDBC코드가 대부분을 차지하고 있고 사용자와의 입출력은 따로 되어있어 코드 가독성이 좋다.

반응형
댓글
공지사항