본문 바로가기

programming/Gukbi

국비 교육 87일차 - 동적쿼리연습, 대댓글 게시판

728x90
반응형
/*
 *   => 단일 조건문 
 *   <if test="조건">실행 SQL</if>
 *   <if test="조건">name=#{name}</if>
 *   
 *   => 다중 조건문 
 *   <choose>
 *     <when test="">SQL</when>
 *     <when test="">SQL</when>
 *     <otherwise></otherwise> ==> else
 *   </choose>
 *   
 *   => <foreach> => IN(값,값,값...)
 *      <foreach collection="배열,List.." item="name"
 *          open="(" close=")" separator=",">
 *          #{name}
 *      </foreach>
 *   => <trim> => 추가 , 제거 
 *      <trim prefix="" suffix="" prefixOverrrides="OR">
 *      prefix="" : 앞에 추가 
 *      suffix="" : 맨뒤에 추가 
 *      prefixOverrrides="OR" : 제거 
 *      
 */

 마이마티스에서 동적쿼리를 쓰는 연습을 해봤다. 단일조건문인 if, 다중조건문 choose~when, foreach, trim 등을 배우고 적용해보는 연습을 했다. 

 

그리고 나서 대댓글 게시판을 완성하는데 주력했다. 

 

일단 저번에 배우긴 배웠으니 쓰는 방법만 간단하게 정리하려고 한다. 

 

 private int no,bno,group_id,group_step,group_tab,root,depth;
    private String id,name,msg;
    private Date redate;
    private String dbday;

group_id - 몇번째 그룹인지

group_step - 그룹내에서 몇번째인지

group_tab - 탭을 몇번 띄고 출력할 것인지

root - 가장 상위 댓글의 번호

depth - 댓글 아래 달린 대댓글의 갯수

 

그리고 reply-mapper

<select id="replyListData" resultType="ReplyVO" parameterType="int">
    SELECT no,bno,id,name,msg,TO_CHAR(regdate,'YYYY-MM-DD HH24:MI:SS') as dbday,group_tab
    FROM spring_reply
    WHERE bno=#{bno}
    ORDER BY group_id DESC,group_step ASC
  </select>

 이거는 댓글의 모든 정보를 불러오는 코드. 같은 글에 있는 댓글들을 불러와야하기 때문에 where bno=? 구문을 써줬다. 또, 가장 최신의 댓글이 먼저 올라와야 하기 때문에 group_id는 desc로, group_step은 asc로 가져온다. 

 

<insert id="replyInsert" parameterType="ReplyVO">
   <!-- mybatis 자동 증가 번호 -->
   <selectKey keyProperty="no" resultType="int" order="BEFORE">
     SELECT NVL(MAX(no)+1,1) as no FROM spring_reply
   </selectKey>
   INSERT INTO spring_reply(no,bno,id,name,msg,group_id) VALUES(
     #{no},
     #{bno},
     #{id},
     #{name},
     #{msg},
     (SELECT NVL(MAX(group_id)+1,1) FROM spring_reply)
   )
  </insert>

 댓글을 쓰는 코드 자동증가번호는 select key로 대체했다.

 

<update id="replyUpdate" parameterType="ReplyVO">
    UPDATE spring_reply SET
    msg=#{msg}
    WHERE no=#{no}
  </update>

 댓글 수정 역시 간단하다

 

 

 

여기부터는 대댓글이 달릴때 처리

<select id="replyParentInfoData" resultType="ReplyVO" parameterType="int">
   SELECT group_id,group_step,group_tab 
   FROM spring_reply
   WHERE no=#{no}
  </select>

 대댓글이 달리는 상위 댓글의 정보

 

<update id="replyGroupStepIncrement" parameterType="ReplyVO">
   UPDATE spring_reply SET
   group_step=group_step+1
   WHERE group_id=#{group_id} AND group_step>#{group_step}
  </update>

 대댓글이 달리면 group_step을 +1해준다. 

 

<insert id="replyToReplyInsert" parameterType="ReplyVO">
    <selectKey keyProperty="no" resultType="int" order="BEFORE">
      SELECT NVL(MAX(no)+1,1) as no FROM spring_reply
    </selectKey>
    INSERT INTO spring_reply VALUES(
      #{no},
      #{bno},
      #{id},
      #{name},
      #{msg},
      SYSDATE,
      #{group_id},
      #{group_step},
      #{group_tab},
      #{root},
      0
    )
  </insert>

 그냥 댓글이 아닌 대댓글을 올릴때 쓰는 코드

 

<update id="replyDepthIncrement" parameterType="int">
    UPDATE spring_reply SET
    depth=depth+1
    WHERE no=#{no}
  </update>

 대댓글이 써지면 depth를 +1 해준다

 

위의 select, update, insert, update를 전부 처리해야 대댓글이 올라가게 된다. 

 

 

 

그러면 이렇게 댓글이 올라간다. 맨위의 댓글이 최초의 댓글이고, 두번째, 세번째가 첫번째 댓글에 대한 대댓글이다. 

group_tab과 depth가 +1씩 증가한걸 알 수 있다

 

 

DAO에서는 이렇게 처리를 해주고 있다. 

 @Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
    // 일괄 처리 (동시에 처리 : 성공 , 한개 실패=> 전부 취소)
    public void replyToReplyInsert(int root,ReplyVO vo)
    {
	   	 // 1. 상위 정보 
	   	 ReplyVO pvo=getSqlSession().selectOne("replyParentInfoData",root);
	   	 // parent => group_id , group_step , group_tab
	   	 getSqlSession().update("replyGroupStepIncrement",pvo);
	   	 // 실제 추가 
	   	 vo.setGroup_id(pvo.getGroup_id());
	   	 vo.setGroup_step(pvo.getGroup_step()+1);
	   	 vo.setGroup_tab(pvo.getGroup_tab()+1);
	   	 vo.setRoot(root);
	   	 getSqlSession().insert("replyToReplyInsert",vo);
	   	 // depth증가
	   	 getSqlSession().update("replyDepthIncrement",root);
    }

 

INSERT에서는 상위정보를 가져오고, 실제 추가, DEPTH증가를 전부 한번에 처리를 해줘야 댓글이 올라가도록 만들어주고 있다. 

이런걸 transaction 프로그램이라고 부른다. 일괄 처리를 해준다는 뜻으로, 이벤트 전부를 성공해야 댓글이 올라가게 된다. 

 

상위 댓글의 정보를 가져왔으면 group_step을 하나 올려준다.  

 

 // 실제 추가 
	   	 vo.setGroup_id(pvo.getGroup_id());
	   	 vo.setGroup_step(pvo.getGroup_step()+1);
	   	 vo.setGroup_tab(pvo.getGroup_tab()+1);
	   	 vo.setRoot(root);

 새로 올라올 댓글의 정보는 이렇게 업데이트 해준다. 

상위 댓글의 group_id가져와서 셋팅, group_step +1, group_tab+1, root는 당연히 상위 댓글의 정보로 

 

getSqlSession().insert("replyToReplyInsert",vo);
	   	 // depth증가
	   	 getSqlSession().update("replyDepthIncrement",root);

insert를 해주면 root의 depth를 +1까지 해준다. 이런 단계를 전부 거쳐야 완성이 된다. 

 

<!-- 댓글 삭제 -->
  <select id="replyInfoData" resultType="ReplyVO" parameterType="int">
    SELECT root,depth FROM spring_reply
    WHERE no=#{no}
  </select>
  <update id="replyMsgUpdate" parameterType="int">
    UPDATE spring_reply SET
    msg='관리자가 삭제한 댓글입니다'
    WHERE no=#{no}
  </update>
  <delete id="replyDelete" parameterType="int">
    DELETE FROM spring_reply
    WHERE no=#{no}
  </delete>
  <update id="depthDecrement" parameterType="int">
    UPDATE spring_reply SET
    depth=depth-1
    WHERE no=#{no}
  </update>

 댓글을 삭제하기 위해서는 root가 되는 댓글의 번호와 depth를 알아야한다. 

그리고 우선 관리자가 삭제한 댓글이라고 내용을 update 해야한다. 

 

그리고 테이블에서 완전히 삭제를 해준다. 그리고 난 뒤 상위 댓글의 depth를 -1해준다. 

 

 @Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
    public void replyDelete(int no)
    {
    	ReplyVO vo=getSqlSession().selectOne("replyInfoData", no);
    	if(vo.getDepth()==0) // 댓글이 없는 경우
    	{
    		getSqlSession().delete("replyDelete",no);
    	}
    	else // 댓글이 있는 경우 
    	{
    		getSqlSession().update("replyMsgUpdate",no);
    	}
    	getSqlSession().update("depthDecrement",vo.getRoot());
    }

 

댓글 삭제는 대댓글 달기보다는 좀더 간단하다. 댓글이 있으면 메세지 업데이트를 해주고, 아니라면 그냥 지워준다. 그리고 지워지든 아니든 상위 댓글의 depth는 꼭 -1을 해줘야 한다. 

 

 

그리고 이걸 view에서 띄워주는 연습을 해야하는데, 이건 내일 ajax를 이용해서 띄워주기로 했다. 맞춰서 포스팅하도록 하겠다. 

728x90
반응형