본문 바로가기

programming/Gukbi

국비 교육 47일차 - 댓글 달기, 댓글 많은순으로 출력

728x90
반응형

어제 시작한 영화 프로그램을 다시 이어서 진행했다. 예고해주신 대로 영화 상세목록 페이지를 먼저 짜줬고, 그 이후에는 로그인 한 사람들이 댓글을 달 수 있도록 하는 기능을 추가했다. 

 

아직 댓글을 삭제하거나 지우는 기능이 완성되지는 않았다. 그래도 일단 복습을 시작해보겠다. 

 

우선 메인 페이지에서 페이지를 이동할 수 있는 코드를 오늘 완성했다. 

 

out.println("<div class=row>");
	    out.println("<div style=\"text-align:center\">");
	    out.println("<a href=MovieListServlet?page="+(curpage>1?curpage-1:curpage)+" class=\"btn btn-sm btn-success\">이전</a>");
	    out.println(curpage+" page / "+totalpage+" pages");
	    out.println("<a href=MovieListServlet?page="+(curpage<totalpage?curpage+1:curpage)+" class=\"btn btn-sm btn-info\">다음</a>");
	    out.println("</div>");
	    out.println("");
	    out.println("");
	    out.println("");
	    out.println("");
	    out.println("</div>"); // row

 이제 페이지 나누는 코드도 익숙해졌다. 삼항연산자를 사용해서 curpage가 1보다 작으면 -1페이지를 해주고, 아니라면 1페이지 일테니까 현재 페이지를 보여주면 된다. 

 

 다음 페이지도 마찬가지로 curpage가 totalpage보다 작으면 +1페이지를 아니라면 맨 마지막 페이지이기 때문에 현재 페이지를 보여주면 된다. 여기까지만 완성하면 메인 페이지는 완성된다. 

 

 

그럼 DAO로 넘어가서 영화 상세목록을 보여주는 메소드를 만들어주면 된다. 

public MovieVO movieDetailData(int mno)
   {
	   MovieVO vo=new MovieVO();
	   
	   try 
	   {
		   getConnection();
		   String sql="SELECT mno, title, poster, genre, actor, regdate, grade, director FROM movie WHERE mno=?";
		   ps=conn.prepareStatement(sql);
		   ps.setInt(1, mno);
		   ResultSet rs=ps.executeQuery();
		   rs.next();
		   
			   vo.setMno(rs.getInt(1));
			   vo.setTitle(rs.getString(2));
			   vo.setPoster(rs.getString(3));
			   vo.setGenre(rs.getString(4));
			   vo.setActor(rs.getString(5));
			   vo.setRegdate(rs.getString(6));
			   vo.setGrade(rs.getString(7));
			   vo.setDirector(rs.getString(8));
		  
		   rs.close();
	   } 
	   catch (Exception ex)
	   {
		   System.out.println(ex.getMessage());
	   }
	   finally
	   {
		   disConnection();
	   }
	   return vo; // vo에 값을 채워서 넘겨준다
   }

 혼자 코드 써봤는데 값이 안떠서 매우 당황했으나 FROM 뒤에 테이블 이름을 안쓰는 바보같은 짓을 해서..

 

다시 해보니까 잘 된다. 이제 이정도 수준의 오라클 연결은 잘 이해하고 있는거 같다. 

 

 

그럼이제 MovieDetailServlet 파일로 넘어와서 데이터를 받아온것을 출력만 해주면 끝난다. 

		// MovieDetailServlet?mno=
		// 사용자로 부터 영화 번호를 받는다
		String mno=request.getParameter("mno");
		
		// 영화번호를 dao에 넘기면 dao가 상세내용을 리턴한다(VO)
		MovieDAO dao=new MovieDAO();
		// 목록을 출력 => DAO(ArrayList)
		MovieVO vo=dao.movieDetailData(Integer.parseInt(mno));
		ArrayList<MovieVO> list=dao.replyTop10();
		// 상세보기 => DAO(VO) VO : 영화관련 한개에 대한 모든 정보를 가지고 있다
		// 화면에 출력 => HTML

 

 메인 페이지로부터 mno를 받아왔기 때문에 parameter로 mno를 받는다. 그러면 이제 그걸 movieDetailData에 넘겨줘서 vo를 저장한다. 

 

저장한 vo는 html로 화면에 뿌려주기만 하면 된다. 

 

out.println("<html>");
		out.println("<head>");
		// script, css, title, meta => 설정 (화면 출력부분은 아니다)
		out.println("<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css\">");
		out.println("<style type=text/css>");
		 // container(960px) , container-fluid(Full 화면)
		out.println(".row { width:1200px;margin:0px auto;}");//<center>태그는 사용금지
		 // <center> => margin:0px auto;
		out.println("h3{text-align:center}");
		out.println("</style>");
		out.println("</head>");
		out.println("<body>");
		// 화면 출력 부분 ==> <html><head><body> => 생략할 수 있다
		out.println("<div style\"height:30px\"></div>");
		
		out.println("<div class=container>");
		
		// 상세보기, 인기순위
		out.println("<div class=row>");
		out.println("<div class=col-sm-9>");
		out.println("<h3> &lt; "+vo.getTitle()+"&gt; </h3>");
		out.println("<table class=\"table table-striped\">");
		
		out.println("<tr>");
		out.println("<td width=30% class=text-center rowspan=6>");
		out.println("<img src="+vo.getPoster()+" width=100%>");
		out.println("</td>");
		out.println("<td colspan=2 style=\"color:orange; font-size:11pt\">");
		out.println(vo.getTitle()+"</td>");
		out.println("</tr>");
		
		out.println("<tr>");
		out.println("<td width=10% class=text-right style=\" color:gray\">감독</td>");
		out.println("<td width=60%>"+vo.getDirector()+"</td>");
		out.println("</tr>");
		
		out.println("<tr>");
		out.println("<td width=10% class=text-right style=\" color:gray\">출연</td>");
		out.println("<td width=60%>"+vo.getActor()+"</td>");
		out.println("</tr>");
		
		out.println("<tr>");
		out.println("<td width=10% class=text-right style=\" color:gray\">장르</td>");
		out.println("<td width=60%>"+vo.getGenre()+"</td>");
		out.println("</tr>");
		
		out.println("<tr>");
		out.println("<td width=10% class=text-right style=\" color:gray\">등급</td>");
		out.println("<td width=60%>"+vo.getGrade()+"</td>");
		out.println("</tr>");
		
		out.println("<tr>");
		out.println("<td width=10% class=text-right style=\" color:gray\">개봉일</td>");
		out.println("<td width=60%>"+vo.getRegdate()+"</td>");
		out.println("</tr>");
		
		out.println("<tr>");
		out.println("<td colspan=3 class=text-right>");
		out.println("<a href=# class=\"btn btn-xs btn-danger\">예매하기</a>");
		out.println("<a href=# class=\"btn btn-xs btn-danger\">찜하기</a>");
		out.println("<a href=MovieListServlet class=\"btn btn-xs btn-danger\">목록</a>");
		out.println("</td>");
		out.println("</tr>");
		
		out.println("</table>");
		out.println("</div>");
		

뿌리기 끝...

html은 재미없고 지루하다...

 

 

이제 다음으로 중요한 기능이 댓글이 많이 달린 영화 목록을 출력해주는 것이다. 

이 기능을 만들기 위해 다시 DAO에서 메소드를 만들어준다. 

 

 public ArrayList<MovieVO> replyTop10()
   {
	   ArrayList<MovieVO> list = new ArrayList<MovieVO>();
	   try
	   {
		   getConnection();
		   // 2. SQL문장 => 공지사항, 이벤트, 인기순위 ... rownum
		   String sql="SELECT title, poster, hit, rownum "
				   +"FROM (SELECT title, poster, hit "
				   +"FROM movie ORDER BY hit DESC) "
				   +"WHERE rownum<=10";
		   ps=conn.prepareStatement(sql);
		   
		   // 실행요청
		   ResultSet rs=ps.executeQuery();
		   while(rs.next())
		   {
			   MovieVO vo=new MovieVO();
			   vo.setTitle(rs.getString(1));
			   vo.setPoster(rs.getString(2));
			   vo.setHit(rs.getInt(3));
			   list.add(vo);
		   }
		   rs.close();
	   }
	   catch (Exception ex) {
		System.out.println(ex.getMessage());
	   }
	   finally
	   {
		   disConnection();
	   }
	   return list;
   }

 rownum을 이용해서 댓글이 많은 순으로 10개만 가져와주는 코드이다. 

DESC로 정렬해야 내림차순으로 가져와서 가장 댓글이 많은 영화 게시글들을 출력해준다. 

 

물론 아직 댓글을 작성하지는 않아서 그냥 mno순서대로 출력이 되고 있다. 

아래는 html로 가져온 내용들을 출력해주는 코드이다. 

	
		out.println("<div class=col-sm-3>");
		out.println("<h3>댓글이 많은 영화</h3>"); // 댓글을 올릴때마다 자동으로 히트를 증가 (Trigger)
		out.println("<table class=\"table table-hover\">");
		for(MovieVO tvo:list)
		{
			out.println("<tr>");
			
			out.println("<td class=text-center>");
			out.println("<img src="+tvo.getPoster()+" width=30%>");
			out.println("</td>");
			
			out.println("<td class=text-center>");
			out.println(tvo.getTitle());
			out.println("</td>");
			
			out.println("<td class=text-center>");
			out.println(tvo.getHit());
			out.println("</td>");
			
			out.println("</tr>");
		}
		out.println("</table>");
		out.println("</div>");
		out.println("</div>");

 포스터와 제목, 댓글수(hit)정도만 가져와 주면 된다. 

 

 

그러면 준비가 되었으니 댓글을 입력받을 준비를 해준다

 

// 7) 댓글 읽기
   public ArrayList<ReplyVO> replyListData(int mno)
   {
	   ArrayList<ReplyVO> list=new ArrayList<ReplyVO>();
	   try
	   {
		   getConnection();
		   String sql="SELECT no, id, name, msg, TO_CHAR(regdate, 'YYYY-MM-DD HH24:MI:SS') "
				   +"FROM webReply "
				   +"WHERE mno=?"
				   +"ORDER BY no DESC";
		   ps=conn.prepareStatement(sql);
		   ps.setInt(1, mno);
		   
		   ResultSet rs=ps.executeQuery();
		   while(rs.next())
		   {
			   ReplyVO vo=new ReplyVO();
			   vo.setNo(rs.getInt(1));
			   vo.setId(rs.getString(2));
			   vo.setName(rs.getString(3));
			   vo.setMsg(rs.getString(4));
			   vo.setDbday(rs.getString(5));
			   list.add(vo);
		   }
		   rs.close();
	   }
	   catch (Exception ex) {
		System.out.println(ex.getMessage());
	   }
	   finally
	   {
		   disConnection();
	   }
	   return list;
   }

 

 일단 댓글 읽어오는 메소드. 매개변수로는 영화 번호를 가져온다. 

 

out.println("<div class=row>");
		HttpSession session=request.getSession();
		String id=(String)session.getAttribute("id");
		ArrayList<ReplyVO> rlist=dao.replyListData(Integer.parseInt(mno));

 로그인을 하지 않아도 댓글이 보이긴 하니까 우선 이렇게 댓글을 화면에 출력해 준다.

 

그리고 나서 로그인에 성공한 사람들에 한해서 댓글 입력창을 띄워준다. 

 

 이미 입력한 댓글은 잘 보인다. 근데 입력창은 보이지 않는다. 로그인을 하지 않았기 때문이다. 

if(id!=null) // 로그인에 성공했을때만 출력 
		{
			out.println("<table class=\"table\">");
			out.println("<tr>");
			out.println("<td>");
			out.println("<form method=post action=ReplyInsertServlet>");
			out.println("<input type=hidden name=mno value="+vo.getMno()+">");
			out.println("<textarea rows=3 cols=80 style=\"float:left\" name=msg></textarea>");
			out.println("<input type=submit value=입력 class=\"btn btn-sm btn-primary\" style=\"height:50px; float:left\">");
			out.println("</form>");
			out.println("</td>");
			out.println("</tr>");
			out.println("</table>");
		}
		

 로그인 정보는 세션에 저장해두었기 때문에, 세션에 저장되어 있는 id의 값을 가져온다. 세션에 저장된 id값이 있다는 얘기는 로그인에 성공했다는 뜻이기 때문에 댓글 입력창을 띄워주면 된다. 

 

form 태그를 통해 ReplyInsertServlet으로 mno와 msg값을 넘겨주었다. 

// 1. 사용자가 보낸값을 받는다
		
		try {
			request.setCharacterEncoding("UTF-8");
		}
		catch(Exception ex) {}
		String mno=request.getParameter("mno");
		String msg=request.getParameter("msg");
		HttpSession session = request.getSession();
		String id=(String)session.getAttribute("id");
		String name=(String)session.getAttribute("name");
		// 매개변수가 3개이상이면 => VO를 이용한다
		ReplyVO vo=new ReplyVO();
		vo.setMno(Integer.parseInt(mno));
		vo.setMsg(msg);
		vo.setId(id);
		vo.setName(name);
		// => DAO로 전송 => 데이터를 오라클에 저장
		MovieDAO dao=new MovieDAO();
		dao.replyInsert(vo);
		// => 이동 => 상세보기로 이동 
		response.sendRedirect("MovieDetailServlet?mno="+mno);

일단 ReplyInsertServlet을 따로 만들어 주고 난 뒤 처리를 한다.

일단 mno가 정해진 detailServlet에서 출력을 하는거기 때문에 사용자로부터 mno를 받아와야 한다. 또 사용자가 작성한 댓글의 내용을 받아와야 하기 때문에 역시 매개변수로 msg를 받아온다. 

 

ReplyVO에 받아온 값들을 저장해준다. mno, msg, id, name을 받으면 replyInsert 메소드를 통해 새로 작성된 댓글의 정보를 오라클로 넘겨줄 수 있다. 

그리고 나서는 다시 상세보기 페이지로 돌아간다. 

 

 

 

DAO에서 댓글을 업데이트 해주는 메소드를 작성한다. 

public void replyInsert(ReplyVO vo)
   {
	   try
	   {
		   // 1. 연결
		   getConnection();
		   // 2. SQL문장
		   String sql="UPDATE movie SET "
				     +"hit=hit+1 "
				     +"WHERE mno=?";
		   ps=conn.prepareStatement(sql);
		   ps.setInt(1, vo.getMno());
		   ps.executeUpdate();
		   
		   sql="INSERT INTO webReply VALUES("
				     +"wr_no_seq.nextval,?,?,?,?,SYSDATE)";
		   ps=conn.prepareStatement(sql);
		   // 2-2.?에 값을 채운다 
		   ps.setInt(1, vo.getMno());
		   ps.setString(2, vo.getId());
		   ps.setString(3, vo.getName());
		   ps.setString(4, vo.getMsg());
		   // 3. 실행 
		   ps.executeUpdate();
	   }catch(Exception ex)
	   {
		   ex.printStackTrace();
	   }
	   finally
	   {
		   disConnection();
	   }
   }

 일단 댓글을 써주면 댓글 hit수를 +1해줘야 하기 때문에 update문을 사용해서 댓글 hit수에 +1을 해준다. 

그리고 나서 댓글의 내용을 채워준다. 

 

이미 vo값으로 필요한 값들을 넘겨받았기 때문에, ?에 값들을 잘 채워넣어주기만 하면 오라클에 저장이 되어 들어간다. 

이때 사용하는 sql문장은 당연히 INSERT INTO이다. 

 

 

 

이제 더 구현해야할 기능은 댓글 수정, 삭제 두개다. 금방하지 않을까 싶기도 한데.. 일단 봐야겠다. 

 

 

728x90
반응형