Programming/JDBC

CRUD 서비스 만들기 2(Select 문으로 레코드 리스트 형태로 가져오기). 2021-08-31

최동훈1 2021. 8. 31. 16:26

우선 이전 포스팅에서 완성하지 못했던, NoticeService 클래스와 서버에서 레코드를 저장하는 그릇역할을 할, Notice 클래스를 완성했다.

NoticeService 클래스

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.List;

import com.ulsanboy.app.entity.Notice;

//다른패키지에 만들어놓은 Notice 클래스를 참조.

public class NoticeService {
	public List<Notice> getList() throws ClassNotFoundException, SQLException{
    
    //List<Notice> 형 객체를 반환타입으로 가지는 메서드 생성.
    
		String url="jdbc:oracle:thin:@localhost:1521/xepdb1";
        String sql ="select * from notice";
		
		
		Class.forName("oracle.jdbc.driver.OracleDriver");
		Connection con = 
		DriverManager.getConnection(url,"newlec","vdongv1620");
	
	    Statement st=con.createStatement();
	    ResultSet rs=st.executeQuery(sql);
	    List<Notice> list=new ArrayList();
	    
	    
		while(rs.next()) {
			int id=rs.getInt("id");
			String title=rs.getString("title");
			String writer_id=rs.getString("writer_id");
			String content=rs.getString("content");
			String regdate=rs.getString("Regdate");
			int hit=rs.getInt("hit");
			Notice notice=new Notice(id,title,writer_id,content,regdate,hit);
            // Notice 클래스의 생성자로 서버에서 받아온 칼럼값을 
            //맴버로 가지는 클래스 생성
			
		list.add(notice);
        //생성한 클래스를 리스트에 삽입.
		
		}
		
		
		
		
		
		st.close();
		con.close();
        
		return list;
        //삽입이 완료된 리스트 타입을 반환

	}

}

말 그대로 주석에 적어놨지만, 서버에서 받은 레코드들을 리스트의 형태로 저장한 다음, 리스트의 형태로 반환하는 기능을 하는 클래스이다.

위의 getList() 메서드는 CRUD에서 Retrieve(select)를 담당하는 메서드 이다. 그럼 

남은 insert, update, delete를 차례로 메서드로 구현해보겠다.

insert

public int insert(Notice notice) throws ClassNotFoundException, SQLException {
        String url="jdbc:oracle:thin:@localhost:1521/xepdb1";
		
		String title =notice.getTitle();
		String writer_id =notice.getWriter_id();
		String content =notice.getContent();
		
		
		
		String sql ="insert into notice(title,writer_id,content)"
				+ "values(?,?,?)";
		
		
		Class.forName("oracle.jdbc.driver.OracleDriver");
		Connection con = 
		DriverManager.getConnection(url,"newlec","vdongv1620");
	
		PreparedStatement st= con.prepareStatement(sql);
		
		st.setString(1, title);
		st.setString(2, writer_id);
		st.setString(3, content);
		
		int count=st.executeUpdate();
	
		
		st.close();
		con.close();
		return count;
	}

사용자로 하여금, 직접 클래스를 입력받게 만들것이기에, 파라미터로 넘겨준 객체의 getter메서드를 사용해서 칼럼값들을 입력받는다. 코드는 전반적으로, 이전 포스팅에서 만들었던 insert 과정이랑 똑같다.

 

update

public int update(Notice notice) throws ClassNotFoundException, SQLException {
		String title =notice.getTitle();
		String content =notice.getContent();
		String writer_id =notice.getWriter_id();
		
		String url="jdbc:oracle:thin:@localhost:1521/xepdb1";
		String sql ="update notice set title=?, content=? where writer_id=?";
		
		
		Class.forName("oracle.jdbc.driver.OracleDriver");
		Connection con = 
		DriverManager.getConnection(url,"newlec","vdongv1620");
	
		PreparedStatement st= con.prepareStatement(sql);
		
		st.setString(1, title);
		st.setString(2, content);
		st.setString(3, writer_id);
		
		int count=st.executeUpdate();
	
		st.close();
		con.close();
		return count;
	}

update도 사용자로부터 입력받은 notice 객체로 칼럼값을 얻은다음, 레코드를 바꿔준다.

 

delete

public int delete(int id) throws SQLException, ClassNotFoundException {
        String url="jdbc:oracle:thin:@localhost:1521/xepdb1";
		String sql ="DELETE notice where id=?";
		
		
		Class.forName("oracle.jdbc.driver.OracleDriver");
		Connection con = 
		DriverManager.getConnection(url,"newlec","vdongv1620");
	
		PreparedStatement st= con.prepareStatement(sql);
		
		st.setInt(1, id);
		
		int count=st.executeUpdate();
		
		
		st.close();
		con.close();
		return count;

	}

delete는 사용자로부터 id 값을 입력받은 뒤, id값을 PreparedStatement를 활용해서 쿼리에 넣어 해당 레코드를 삭제한다.

 

이젠 사용자 UI를 만들어 보겠다. 웹으로는 아직 개발실력이 부족해 만들진 못하고, 콘솔 기반으로 게시판을 만들어 보겠다.

내가 만들려는 콘솔

 

우선 콘솔에 관련된 클래스들을 한곳에 모을 com.ulsanboy.Console 패키지를 만들었다.

또, 콘솔에서 실제적으로 콘솔을 만드는 NoticeConsole 클래스와, 사용자의 입력값으로 하여금 콘솔을 동작하게 하는 program5 클래스를 만들었다. program5 클래스는 NoticeConsole에 구현된 메소드를 사용해서 동작하게 할 것이다. 그럼 메인함수인 program5 클래스에 필요한 기능을 구현이 되있지 않더라도, 메서드를 만들어서 큰 틀을 잡은다음, 세부적인 메서드 내용은 NoticeConsole 클래스에서 마무리짓는 Top-Down 방식을 사용하였다.

 

이렇게 패키지별로 나누어서 기능에따라 클래스를 저장함.

이렇게 패키지를 나누어서 개발하니 훨씬 깔끔해졌다.

 

NoticeConsole 클래스

package com.ulsanboy.app.console;

import java.sql.SQLException;
import java.util.List;

import com.ulsanboy.app.entity.Notice;
import com.ulsanboy.app.service.NoticeService;

public class NoticeConsole {
	
	private NoticeService noticeservice;
	
    
	public NoticeConsole() {
		noticeservice=new NoticeService();
	}
    
    //생성자로 하여금 서비스 객체를 생성하도록 하였다.

	public void showList() throws ClassNotFoundException, SQLException {
		// TODO Auto-generated method stub
		List<Notice> list=noticeservice.getList();
		
		System.out.println("────────────────────────────────────");
		System.out.printf("<공지사항> 총 %d개 글.\n",12);
		System.out.println("────────────────────────────────────");
		for(Notice e:list) {
			System.out.printf("%d / %s / %s / %s \n",
					e.getId(),e.getContent(),e.getWriter_id(),e.getRegdate());
		}
        //생성된 서비스객체로 리스트를 뽑아내어서 현재 존재하는 모든 레코드들을
        //출력하도록 만들었다.
		System.out.println("────────────────────────────────────");
		
		
		
	}

	public int userInput() {//미완성.
		// TODO Auto-generated method stub
		return 0;
	}

}

실행결과.

아직까지 페이징 처리를 하지 않아서 중구난방으로 출력되는 모습이다.

위와같이 중구난방으로 출력도지 않고, 기존 계획대로 딱 12개 씩 짤라서 출력하려면 서버에서 12개의 레코드씩 가져오는 페이징기법이 필요하다.

 

오라클 공부할때 페이징을 공부했었는데, ROWNUM을 이용하면 된다.

select * from (select ROWNUM as num, n.* from notice n) 
where num between 1 and 12;

이렇게 서브쿼리를 이용하면 쉽게 페이징 할 수 있다. 이유: ROWNUM은 where 절에서 만들어지기 때문,

 

그런데 만약 12개를 출력하는데 글 적힌 날짜가 최신순으로 출력할려면 어떻게 해야 할까? 여기서도 SQL 지식이 필요한데, 컴퓨터에서 쿼리를 실행할때 from -> where-> group by -> having -> select -> order by 순으로 실행되기에 우선적으로, 서브쿼리 없이쓰면, ROWNUM이 붙인채로 정렬되버려서 뒤죽박죽이 된다. -> ROWNUBER() 함수 또는 서브쿼리를 써야한다. (이전에 페이징 포스팅에서 내가 자세히 설명함. 모르겠으면 참고하기 !!)

select * from (select ROWNUM as num, n.* from(select * from notice order by regdate disc) n )
between 1 and 12;

 이렇게 정렬부터 한 다음 ROWNUM을 붙여서 출력하면 된다.

 

이 페이징 쿼리를 NoticeService에 적용시키는 과정은 내일 보이겠다.

 

공부시간 3시간.

순공시간 1시간 .

 

오늘은 뭔가, 새롭게 알게된 내용이 없어서인지, 내 SQL 이랑 java 지식이 많이 쌓여서 공부한게 없다고 느껴서인지 공부를 조금한 기분이다. 오늘 어깨때문에 정형외과에 가서 정밀검사를 받아본다.