Language/JAVA

MVC 모델 2 게시판 만들기 - 1

자바걸 2022. 11. 1. 10:03

mvc란?

- mvc는 모델(model), 뷰(view), 컨트롤러(controller)의 약자로 소프트웨어를 개발하는 방법의 일종이다. 

- 모델2는 모델1과 달리 jsp에서 뷰와 컨트롤러를 모두 구현하지 않고 jsp는 오직 뷰만 담당한다. 처음엔 개발하기 조금 더 복잡하지만 이후에 유지보수가 더 용이하다는 장점이 있다. 

지금 하려는건 답변형 게시판 만들기이다.


0. 작업설정

먼저 데이터베이스 세팅을 해야한다. (오라클을 사용했다)

테이블

이런식으로 테이블을 생성했고,  NUM컬럼은 1씩 증가하는 시퀀스를 주었다.   

여기서 REF, RE_STEP, RE_LEVEL이 어떤 컬럼을 뜻하냐면,

REF > 글그룹(답변글을 포함해서 모두 같은 숫자이다)

RE_STEP > 글 스텝(몇번째 답변글인지. 예를들어 부모글이 1이라면 답변글은 2이다. 답변글의 답변글은 3이다),

RE_LEVEL > 글 순서(부모글을 제외한 나머지 글은 1씩 증가해야한다)

결국, REF는 숫자가 큰 순서대로 위로 온다. 내림차순이다.

반면, RE_STEP과 RE_LEVEL은 오름차순으로 정렬되어야 우리가 게시판에서 보는 그러한 정렬이 된다.

 


나는 Board라는 Dynamic Web project를 생성했다.(생성 후 build path로 servelt API 추가하는것 잊지말기)

servlet-api.jar
0.32MB

웹프로젝트 생성하면 데이터베이스와 연동될 수 있도록  server.xml에서 커넥션 풀을 설정해주어야한다.

(커넥션 풀 설정은 후에 따로 포스팅할것이다!) 

그리고 src의 lib폴더에 복사해서 넣어줘야할 파일들이 여럿이 있다.

(나는 톰캣10을 쓰므로 톰캣10 기준이다)

톰캣10 기준 lib폴더 필요한 파일

 


1. BoardDAO클래스 생성

-DAO클래스는 쿼리문을 사용하여 DB와 연결해서 필요한 데이터를 이용해 우리가 필요한 기능(메소드)를 생성하는 클래스다. 전체 DAO클래스 코드를 넣었다.

package model;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Vector;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

public class BoardDAO {
	Connection con;
	PreparedStatement pstmt;
	ResultSet rs;
	
	//데이터 베이스에 연결 메소드
	public void getCon() {
		
		try {
			Context initctx= new InitialContext();
			Context envctx = (Context)initctx.lookup("java:comp/env");
			DataSource ds = (DataSource)envctx.lookup("jdbc/oracle");
			con = ds.getConnection();//커넥션 연결 해주는 메소드
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	//전체 게시글의 갯수를 리턴하는 메소드 
		public int getAllCount(){
			int count = 0; //카운트 초기화
			getCon();//데이터베이스 연결
			
			try {
				//쿼리 준비 
				String sql ="select count(*) from board";
				pstmt =con.prepareStatement(sql);
				//쿼리 실행후 결과 리턴
				rs = pstmt.executeQuery();
				if(rs.next()){ //단일행 함수라서 while안써도 됨 //데이터가 있다면~
					count = rs.getInt(1);//첫번째 결과값을 int형으로 count변수에 집어넣으란 것.
				}
				con.close();
			}catch(Exception e) {
				e.printStackTrace();

			}
			return count;
		}
		//모든 화면에 보여질 데이터 10개씩 추출해서 리턴하는 매소드
		public Vector<BoardBean> getAllBoard(int startRow , int endRow){
			Vector<BoardBean> v = new Vector<>(); //가방의 이름은 보드빈
			getCon(); //디비연결
			try {
				//쿼리 준비 
				String SQL = "select * from (select A.* ,Rownum Rnum from (select *from board order by ref desc, re_step asc)A)"
						+ "where Rnum >= ? and Rnum <= ?";
				
				//쿼리실행 객체 선언
				pstmt = con.prepareStatement(SQL);
				//?에 값을 대입
				pstmt.setInt(1,startRow);
				pstmt.setInt(2,endRow);
				
				//쿼리를 실행후 결과를 저장
				rs = pstmt.executeQuery();	
				
				//데이터 개수가 몇개인지 모르기에 반복문을 이용하여 데이터를 추출 
				while(rs.next()){
					 //데이터를 패키징(가방 = Boardbean클래스를 이용)해줌
					 BoardBean bean = new BoardBean();
					 bean.setNum(rs.getInt(1));
					 bean.setWrite(rs.getString(2));
					 bean.setEmail(rs.getString(3));
					 bean.setSubject(rs.getString(4));
					 bean.setPassword(rs.getString(5));
					 bean.setReg_date(rs.getDate(6).toString());
					 bean.setRef(rs.getInt(7));
					 bean.setRe_step(rs.getInt(8));
					 bean.setRe_level(rs.getInt(9));
					 bean.setReadcount(rs.getInt(10));
					 bean.setContent(rs.getString(11));
					 //패키징한 데이터를 벡터에 저장 
					 v.add(bean);
				 }
				con.close();
				
				}catch(Exception e) {
					e.printStackTrace();	
				}	
				return v;
		}
		
		
		//하나의 게시글을 저장하는 메소드 호출
		public void insertBoard(BoardBean bean) {
			
			getCon();
			int ref=0;
			int re_step=1; //새글이기에
			int re_level=1; //새글
			try {
			String refsql = "select max(ref) from board";
			pstmt= con.prepareStatement(refsql);
			//쿼리 실행후 결과를 리턴
			rs = pstmt.executeQuery();
			if(rs.next()) {
				ref = rs.getInt(1)+1; //가장 큰 값에 1을 더해줌 그래야 다음번 ref값이 겹치지 않게 들어가니..
			}
			//데이터를 삽입하는 쿼리
			String sql = "insert into board values (board_seq.nextval, ?,?,?,?,sysdate,?,?,?,0,?)";
			pstmt=con.prepareStatement(sql);
			pstmt.setString(1, bean.getWrite());
			pstmt.setString(2, bean.getEmail());
			pstmt.setString(3, bean.getSubject());
			pstmt.setString(4, bean.getPassword());
			pstmt.setInt(5,ref);
			pstmt.setInt(6,re_step);
			pstmt.setInt(7,re_level);
			pstmt.setString(8,bean.getContent());
			//쿼리실행
			pstmt.executeUpdate();
			//자원반납
			con.close();
		}catch (Exception e) {
			e.printStackTrace();
		}
		}
		
		//BoardInfo 하나의 게시글 리턴하는 메소드 //BoardBean타입으로 리턴값
		public BoardBean getOneBoard(int num){	
			//리턴 타입 선언
			BoardBean bean = new BoardBean();
			getCon();
			try {
				//조회수 증가 쿼리 //하나의 게시글을 읽엇다는 조회수 증가
				String readsql = "update board set readcount = readcount+1 where num=?";
				pstmt = con.prepareStatement(readsql);
				pstmt.setInt(1,num);
				pstmt.executeUpdate();	
					
				//한 게시글에 대한 정보를 리턴해주는 쿼리준비
				String SQL = "select * from board where num=?";
				//쿼리실행객체 
				//쿼리실행 객체 
				pstmt = con.prepareStatement(SQL);
				pstmt.setInt(1,num);
				//쿼리 실행후 결과를 리턴
				rs= pstmt.executeQuery();
					
				if(rs.next()) { //하나의 게시글이 존재 한다면
					bean.setNum(rs.getInt(1));
					bean.setWrite(rs.getString(2));
					bean.setEmail(rs.getString(3));
					bean.setSubject(rs.getString(4));
					bean.setPassword(rs.getString(5));
					bean.setReg_date(rs.getDate(6).toString());
					bean.setRef(rs.getInt(7));
					bean.setRe_step(rs.getInt(8));
					bean.setRe_level(rs.getInt(9));
					bean.setReadcount(rs.getInt(10));
					bean.setContent(rs.getString(11));
					}
					
					con.close();
				}catch(Exception e) {
					e.printStackTrace();
					
				}
				return bean;
			}
		
		
		//답변글이 저장되는 메소드 
		public void reWriteBoard(BoardBean bean){
			//부모글 그룹과 글레벨 글 스템을 읽어드림 
			int ref =bean.getRef();
			int re_step = bean.getRe_step();
			int re_level = bean.getRe_level();
			
			getCon();
			
			try {
				/////////////////////핵심 코드 //////////////////////// 
					//부모글 보다 큰 re_level의 값을 전부 1씩 증가시켜줌 
					String  levelsql = "update board set re_level=re_level+1 where ref=? and re_level > ?";
					//쿼리 삽입 객체 선언 
					pstmt = con.prepareStatement(levelsql);
					pstmt.setInt(1 , ref);
					pstmt.setInt(2 , re_level);
					//쿼리 실행 
					pstmt.executeUpdate();
					//답변글 데이터를 저장
					String sql ="insert into board values(board_seq.NEXTVAL,?,?,?,?,sysdate,?,?,?,0,?)";
					pstmt = con.prepareStatement(sql);
					//?에 값을 대입
					pstmt.setString(1, bean.getWrite());
					pstmt.setString(2, bean.getEmail());
					pstmt.setString(3, bean.getSubject());
					pstmt.setString(4, bean.getPassword());
					pstmt.setInt(5, ref);//부모의 ref 값을 넣어줌 
					pstmt.setInt(6, re_step+1);//답글이기에 부모글 re_stop에 1을 넣어줌 
					pstmt.setInt(7, re_level + 1);
					pstmt.setString(8, bean.getContent());
					
					//쿼리를 실행하시오
					pstmt.executeUpdate();	
					con.close();
					
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		
		//Boardupdate용 Delete시 하나의 게시글을 리턴
		public BoardBean getOneUpdateBoard(int num){	
			//리턴 타입 선언
			BoardBean bean = new BoardBean();
			getCon();
			try {
				//쿼리준비
				String SQL = "select * from board where num=?";
				//쿼리실행객체 
				//쿼리실행 객체 
				pstmt = con.prepareStatement(SQL);
				pstmt.setInt(1,num);
				//쿼리 실행후 결과를 리턴
				rs= pstmt.executeQuery();
				
				if(rs.next()) {
					 bean.setNum(rs.getInt(1));
					 bean.setWrite(rs.getString(2));
					 bean.setEmail(rs.getString(3));
					 bean.setSubject(rs.getString(4));
					 bean.setPassword(rs.getString(5));
					 bean.setReg_date(rs.getDate(6).toString());
					 bean.setRef(rs.getInt(7));
					 bean.setRe_step(rs.getInt(8));
					 bean.setRe_level(rs.getInt(9));
					 bean.setReadcount(rs.getInt(10));
					 bean.setContent(rs.getString(11));
				}
				
				con.close();
			}catch(Exception e) {
				e.printStackTrace();
				
			}
			return bean;
		}
		
		
		//하나의 게시글을 수정하는 메소드
		public void updateBoard(int num ,String subject , String content){
			getCon();
				
			try {		
				//쿼리 준비 
				String sql = "update board set subject=? , content= ? where num = ?";
					
				//쿼리 실행할 객체 선언
				pstmt = con.prepareStatement(sql);
				
				//?에 값을 대입 하기
				pstmt.setString(1,subject);
				pstmt.setString(2,content);
				pstmt.setInt(3,num);
				
				//쿼리 실행후 결과를 리턴
				pstmt.executeUpdate();
					
				//자원 반납
				con.close();
						
			}catch(Exception e) {
				e.printStackTrace();
			}
		}  
		
		
		//하나의 게시글을 삭제하는 매소드
			public void deleteBoard(int num){
				getCon();
				
				try {		
					//쿼리 준비 
					String sql = "delete from board where num=?";
					
					//쿼리 실행할 객체 선언
					pstmt = con.prepareStatement(sql);
					//?
					pstmt.setInt(1,num);
					
					//쿼리 실행
					pstmt.executeUpdate();
					
					//자원 반납
					con.close();
						
				}catch(Exception e) {
					e.printStackTrace();
					
				}
			}
		
}