[Spring] 스프링 정리9 - 게시판 만들기
[목차]
11. 게시판 만들기
① DB 연결
② List 출력
③ 게시물 등록
④ 검색
⑤ 상세 페이지 보기
⑥ 게시글 수정
⑦ 게시글 삭제
⑧ 댓글 기능 추가
[내용]
① DB 연결
= sprweb16_board
- db.properties
driver=org.mariadb.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/happydb
username=root
password=123
=> 계정 정보 설정파일.
- Configuration.xml
<configuration>
<typeAliases>
<typeAlias type="pack.model.BoardDto" alias="dto"/>
<typeAlias type="pack.controller.BoardBean" alias="formBean"/>
</typeAliases>
<mappers>
<mapper resource="pack/mybatis/DataMapper.xml" />
</mappers>
</configuration>
=> DataMapper.xml 연결.
- DataMapper.xml
<mapper namespace="dev">
<!-- 전체 검색 -->
<select id="selectList" resultType="dto">
select * from board order by gnum desc, onum asc
</select>
<!-- 카워드 검색 -->
<select id="searchList" parameterType="formBean" resultType="dto">
select * from board
where ${searchName} like concat('%',#{searchValue},'%')
order by gnum desc, onum asc
</select>
<!-- 번호로 검색 -->
<select id="selectOne" parameterType="string" resultType="dto">
select * from board where num=#{num}
</select>
<!-- 추가 -->
<insert id="insertData" parameterType="formBean">
insert into board
values(#{num},#{name},#{pass},#{mail},#{title},#{cont},
#{bip},#{bdate},0,#{gnum},0,0)
</insert>
<update id="updateData" parameterType="formBean">
update board
set name=#{name},mail=#{mail},title=#{title},cont=#{cont}
where num=#{num}
</update>
<delete id="deleteData" parameterType="string">
delete from board where num=#{num}
</delete>
<!-- maxnum -->
<select id="currentNum" resultType="integer">
select max(num) from board
</select>
<select id="totalCnt" resultType="integer">
select count(*) from board
</select>
<!-- readcnt -->
<update id="updateReadcnt" parameterType="string">
update board set readcnt=readcnt + 1
where num=#{num}
</update>
<!-- password -->
<select id="selectPass" parameterType="string" resultType="string">
select pass from shopboard
where num=#{num}
</select>
<!-- reply -->
<update id="updateOnum" parameterType="formBean">
update board set onum=onum + 1
where onum >= #{onum} and gnum=#{gnum}
</update>
<insert id="insertReData" parameterType="formBean">
insert into board
values(#{num},#{name},#{pass},#{mail},#{title},#{cont},
#{bip},#{bdate},0,#{gnum},#{onum},#{nested})
</insert>
</mapper>
=> SQL문 작성.
- servlet-context.xml
<context:component-scan base-package="pack.controller" />
<context:component-scan base-package="pack.model" />
=> 어노테이션 사용을 위한 패키지 스캔.
- root-context.xml
<!-- PropertyPlaceholderConfigurer 사용 : 외부 프로퍼티의 정보를 설정파일에서 사용가능.-->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<!-- locations 속성으로 db.properties를 read하도록 설정 -->
<!-- db.properties의 프로퍼티를 ${프로퍼티값}으로 사용할 수 있다. -->
<property name="locations">
<value>classpath:pack/mybatis/db.properties</value>
</property>
</bean>
<!-- SimpleDriverDataSource 사용 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<!-- -->
<property name="driverClass" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</bean>
<!-- SqlSessionFactoryBean 사용 -->
<!-- 복수개일 경우 id를 셋팅 -->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- SqlMapConfig의 SqlSession에 Configuration.xml 연결-->
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:pack/mybatis/Configuration.xml"></property>
</bean>
=> DB 연동을 위한 SqlSessionFactory 객체 생성.
② List 출력
- index.jsp
<body>
<h2>메인</h2>
<ul>
<li>쇼핑하기</li>
<li>회원관리</li>
<li>물류관리</li>
<li><a href="list?page=1">게시판</a></li>
</ul>
</body>
=> url (list), key=value(page=1) 전달(GET 방식).
- ListController
@Controller
public class ListController {
@Autowired
private BoardDaoInter boardInter;
private int tot; // 전체 레코드 수
private int plist=5; // 한 페이지 당 행의 수
private int pageCount; // 전체 페이지 수
public ArrayList<BoardDto> getListData(ArrayList<BoardDto> list, int page){
ArrayList<BoardDto> result = new ArrayList<BoardDto>();
int start = (page - 1)*plist; // 해당 페이지의 첫 게시물의 index
int size = plist <= list.size() - start ? plist : list.size() - start;
// 한 페이지에 표시할 데이터가 5개 이하일 경우엔 size가 그 수에 따르도록 조건처리.
for(int i=0; i<size;i++) { // list에 한 페이지당 표시할 데이터만 담아 리턴한다.
result.add(i, list.get(start + i));
}
return result;
}
public int getPageCount() { // get 페이지 수
pageCount = tot/plist;
if(tot%plist > 0 ) pageCount+=1;
return pageCount;
}
@RequestMapping("list")
public Model process(Model model, @RequestParam("page") int page) {
tot = boardInter.totalCnt();
ArrayList<BoardDto> list = boardInter.getList();
ArrayList<BoardDto> result = getListData(list, page);
model.addAttribute("data",result);
model.addAttribute("pageCount",getPageCount());
model.addAttribute("page",page);
//model.addAttribute("data",list); // 페이징 없이 작업할 경우
return model;
}
}
=> totalCnt() :
=> getList() : 전체 List 검색하여 list 리턴.
=> getListData() : 전체 리스트에서 한 페이지 당 표시할 데이터만 리턴값으로 가진다.
=> plist : 한 페이지 당 표시할 레코드 수를 설정.
=> getPageCount() : 페이지의 개수를 리턴.
- BoardBean
public class BoardBean {
private String name,pass,mail,title,cont,bip,bdate;
private int num,readcnt,gnum,onum,nested;
private String searchName, searchValue;
//getter/setter
}
=> FormBean 작성.
- BoardDto
public class BoardDto {
private String name,pass,mail,title,cont,bip,bdate;
private int num,readcnt,gnum,onum,nested;
//getter/setter
}
=> DTO 작성.
- BoardDaoInter
public interface BoardDaoInter {
ArrayList<BoardDto> getList();
ArrayList<BoardDto> getSearch(BoardBean bean);
boolean insert(BoardBean bean);
BoardDto getDetail(String num);
boolean update(BoardBean bean);
boolean delete(String num);
int currentNum();
int totalCnt();
boolean updateReadcnt(String num);
String selectPass(String num);
boolean updateOnum(BoardBean bean);
boolean insertReply(BoardBean bean);
}
=> interface 작성.
- BoardDaoImpl
@Repository
public class BoardDaoImpl extends SqlSessionDaoSupport implements BoardDaoInter {
@Autowired
public BoardDaoImpl(SqlSessionFactory factory) {
setSqlSessionFactory(factory);
}
@Override
public ArrayList<BoardDto> getList() {
return (ArrayList)getSqlSession().selectList("selectList");
}
@Override
public int totalCnt() {
return getSqlSession().selectOne("totalCnt");
}
...
}
=> getList() : board 테이블의 모든 정보 list 리턴.
=> totalCnt() : 레코드 수를 리턴.
<!-- 전체 검색 -->
<select id="selectList" resultType="dto">
select * from board order by gnum desc, onum asc
</select>
<select id="totalCnt" resultType="integer">
select count(*) from board
</select>
- list.jsp
<body>
<jsp:include page="./top.jsp"></jsp:include>
<table class="table">
<tr>
<td>
[<a href="list?page=1">최근목록</a>]
[<a href="insert">새글작성</a>]
</td>
</tr>
</table>
<table class="table table-striped">
<thead>
<tr style="">
<th>번호</th><th>제 목</th><th>작성자</th><th>작성일</th><th>조회</th>
</tr>
</thead>
<c:forEach var="b" items="${data}">
<!-- 댓글 들여쓰기 준비-->
<c:set var="tab" value=""/>
<c:forEach var="n" begin="1" end="${b.nested}">
<c:set var="tab" value="${tab} "/>
</c:forEach>
<tr>
<td>${b.num}</td>
<td>
${tab}<a href="detail?num=${b.num}&page=${page}">${b.title}</a>
</td>
<td>${b.name}</td>
<td>${b.bdate}</td>
<td>${b.readcnt}</td>
</tr>
</c:forEach>
<!-- paging -->
<tr style="text-align: center;">
<td colspan="5">
<c:forEach var="psu" begin="1" end="${pageCount}">
<c:if test="${psu==page}">
<b>${psu}</b>
</c:if>
<c:if test="${psu!=page}">
<a href="list?page=${psu}">${psu}</a>
</c:if>
</c:forEach>
</td>
</tr>
<!-- search -->
<tr style="text-align: center;">
<td colspan="5">
<br><br>
<form action="search" method="post">
<select name="searchName">
<option value="title" selected="selected">글제목</option>
<option value="name">작성자</option>
</select>
<input type="text" name="searchValue">
<input type="submit" value="검색">
</form>
</td>
</tr>
</table>
</body>
=> 페이지 처리된 list를 출력한다.
=> 제목을 누를 경우 요청명 detail로 num과 page 값을 전달한다.
=> 검색 버튼을 누를 경우 searchName(key)에 title or name(value), searchValue(key)에 값이 요청명 search로 전달.
(post방식)
=> 게시물 등록 하이퍼링크 클릭시 insert 요청명 전달.(GET방식)
③ 게시물 등록
- InsertController
@Controller
public class InsertController {
@Autowired
private BoardDaoInter boardInter;
@RequestMapping(value="insert", method = RequestMethod.GET)
public String insert() {
return "insform";
}
...
}
=> GET방식 요청명 insert 받을 경우 inform.jsp 실행.
- insform.jsp
<head>
<script type="text/javascript">
window.onload=function(){
let btnIns = document.getElementById("btnIns");
btnIns.addEventListener("click",checkData, false);
}
function checkData(){
if(frm.name.value === ""){
alert("작성자를 입력하세요");
frm.name.focus();
return;
}else if(frm.pass.value === ""){
alert("비밀번호를 입력하세요");
frm.name.focus();
return;
}
frm.submit();
}
</script>
</head>
<body>
<jsp:include page="./top.jsp"></jsp:include>
<h4 style="text-align: center;">* 게시물 등록</h4>
<form action="insert" method="post" name="frm">
<table class="table" style="width: 80%">
<tr>
<td>이름</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>암호</td>
<td><input type="text" name="pass"></td>
</tr>
<tr>
<td>메일</td>
<td><input type="text" name="mail"></td>
</tr>
<tr>
<td>제목</td>
<td><input type="text" name="title"></td>
</tr>
<tr>
<td>내용</td>
<td>
<textarea rows="5" cols="50" name="cont"></textarea>
</td>
</tr>
<tr>
<td colspan="2" style="text-align: center;">
<input type="hidden" name="bip" value="<%=request.getRemoteAddr()%>">
<input type="button" value="등록" id="btnIns">
<!-- <input type="button" value="등록" onclick="checkData()"> -->
<input type="button" value="목록" onclick="location.href='list?page=1'">
</td>
</tr>
</table>
</form>
</body>
=> 등록 버튼 누를 경우 name/pass칸이 비어있을 경우 pop-up 발생.
요청명 insert 전달.(post 방식)
=> location.href : 목록버튼 누를 경우 list 출력 창 1 page로 이동.
focus() : 커서가 해당 창으로 이동.
submit() : submit 동작 진행.
- InsertController
@Controller
public class InsertController {
@Autowired
private BoardDaoInter boardInter;
...
@RequestMapping(value="insert", method = RequestMethod.POST)
public String submit(BoardBean bean) {
bean.setBdate();
int newNum = boardInter.currentNum() + 1; // 새로 작성된 글의 번호
bean.setNum(newNum);
bean.setGnum(newNum);
boolean b= boardInter.insert(bean);
if(b) {
return "redirect:/list?page=1";
}else {
return "redirect:/error";
}
}
}
=> POST방식 요청명 insert 받을 경우 실행.
=> <form>태그 데이터 FormBean에 set.
=> setBdate() : Calendar객체를 이용하여 오늘 날짜를 set한다.
=> currentNum() : 현재 테이블의 num값중 가장 큰 값을 받아와 +1하여 현재 num가 group num 값을 set한다.
=> insert() : data 추가.
=> insert 성공 시 전체 list 페이지로 이동, 실패 error 페이지로 이동.
public void setBdate() {
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH) + 1;
int day = cal.get(Calendar.DATE);
this.bdate = year + "-" + month + "-" + day;
}
- BoardDaoImpl
@Repository
public class BoardDaoImpl extends SqlSessionDaoSupport implements BoardDaoInter {
@Autowired
public BoardDaoImpl(SqlSessionFactory factory) {
setSqlSessionFactory(factory);
}
...
@Override
public boolean insert(BoardBean bean) {
int result = getSqlSession().insert("insertData",bean);
if(result>0) {
return true;
}else {
return false;
}
}
...
@Override
public int currentNum() {
//insert시 번호 자동 증가를 위해 현재 레코드 중 가장 큰 번호 얻기.
if(getSqlSession().selectOne("currentNum") == null) {
return 0;
}else {
return getSqlSession().selectOne("currentNum");
}
}
...
}
=> insert() : insert에 성공 시 true, 실패 시 false 리턴.
=> currentNum() : 레코드가 없을 경우 현재 가장 큰 num값을 0으로 리턴.
...
<!-- 추가 -->
<insert id="insertData" parameterType="formBean">
insert into board
values(#{num},#{name},#{pass},#{mail},#{title},#{cont},
#{bip},#{bdate},0,#{gnum},0,0)
</insert>
...
<!-- maxnum -->
<select id="currentNum" resultType="integer">
select max(num) from board
</select>
...
=> Data insert
=> board테이블의 num중 가장 큰 값 리턴.
- ErrorController
@Controller
public class ErrorController {
@RequestMapping("error")
public String err() {
return "error";
}
}
=> error.jsp 실행
- error.jsp
<body>
<h2>에러 발생</h2>
<a href="list?page=1">목록보기</a>
</body>
=> error 페이지 출력.
④ 검색
- SearchController
@Controller
public class SearchController {
@Autowired
private BoardDaoInter inter;
@RequestMapping("search")
public ModelAndView searchProcess(BoardBean bean) {
ArrayList<BoardDto> list = inter.getSearch(bean);
ModelAndView view = new ModelAndView("list", "data", list);
view.addObject("page","1");
return view;
}
}
=> list.jsp에서 검색 버튼을 누를 경우 searchName(key), searchValue(key)가 전달된다.
=> getSearch() : searchName(key), searchValue(key)에 맞는 값을 검색하여 리스트로 출력한다.
=> 리턴 값을 list.jsp에 출력.
- BoardDaoImpl
@Repository
public class BoardDaoImpl extends SqlSessionDaoSupport implements BoardDaoInter {
@Autowired
public BoardDaoImpl(SqlSessionFactory factory) {
setSqlSessionFactory(factory);
}
...
@Override
public ArrayList<BoardDto> getSearch(BoardBean bean) {
return (ArrayList)getSqlSession().selectList("searchList", bean);
}
...
}
=> getSearch() : 검색 후 ArrayList 리턴.
- DataMapper.xml
...
<!-- 카워드 검색 -->
<select id="searchList" parameterType="formBean" resultType="dto">
select * from board
where ${searchName} like concat('%',#{searchValue},'%')
order by gnum desc, onum asc
</select>
...
=> searchName의 Column에서 searchValue의 키워드가 있을 경우 리스트를 리턴한다.
⑤ 상세 페이지 보기
- DetailController
@Controller
public class DetailController {
@Autowired
private BoardDaoInter inter;
@RequestMapping("detail")
public ModelAndView detailProcess(@RequestParam("num") String num,
@RequestParam("page") String page) {
// 조회수 증가 작업 선행
boolean b = inter.updateReadcnt(num);
// 상세보기 진행 후 jsp로 출력
ModelAndView view = new ModelAndView("detail");
view.addObject("data", inter.getDetail(num));
view.addObject("page", page);
return view;
}
}
=> list.jsp에서 제목을 누를 경우 요청명 detail로 num과 page 값을 전달받는다.
=> @RequestParam : request.getParameter()와 동일.
=> updateReadcnt() : 조회수를 +1한다.
=> getDetail() : 해당 num의 한 레코드 값을 리턴하여 detail.jsp 실행.
- BoardDaoImpl
@Repository
public class BoardDaoImpl extends SqlSessionDaoSupport implements BoardDaoInter {
@Autowired
public BoardDaoImpl(SqlSessionFactory factory) {
setSqlSessionFactory(factory);
}
...
@Override
public BoardDto getDetail(String num) {
// 글 내용보기, 글 수정 시 데이터 받아오기
return getSqlSession().selectOne("selectOne",num);
}
...
@Override
public boolean updateReadcnt(String num) {
//상세보기 전 조회수 증가
int result = getSqlSession().update("updateReadcnt",num);
if(result>0) {
return true;
}else {
return false;
}
}
...
}
=> getDetail() : 게시글의 내용을 받아온다.
=> updateReadcnt() : 업데이트 성공시 true, 실패 시 false 리턴
- DataMapper.xml
...
<!-- 번호로 검색 -->
<select id="selectOne" parameterType="string" resultType="dto">
select * from board where num=#{num}
</select>
...
<!-- readcnt -->
<update id="updateReadcnt" parameterType="string">
update board set readcnt=readcnt + 1
where num=#{num}
</update>
...
=> num값과 동일한 레코드 리턴.
=> num과 동일한 레코드의 조회수 +1.
- detail.jsp
<script type="text/javascript">
window.onload=function(){
document.getElementById("btnDel").onclick = chkDeleData;
}
function chkDeleData(){
let pass = prompt("비밀번호를 입력하세요");
location.href="delete?num=${data.num}&page=${page}&pass="+pass;
}
</script>
</head>
<body>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:if test="${msg != null}">
<script type="text/javascript">
(function msg(){
alert("${msg}");
})();
</script>
</c:if>
<jsp:include page="./top.jsp"></jsp:include>
<div class="container">
<h4 style="text-align: center;">* 상세보기</h4>
<table class="table" style="width: 80%">
<tr>
<td>비밀번호 : ${data.pass}</td>
<td style="text-align: right;">
<a href="reply?num=${data.num}&page=${page}">
<img src="./resources/images/reply.gif" />
</a>
<a href="update?num=${data.num}&page=${page}">
<img src="./resources/images/edit.gif" />
</a>
<button id="btnDel"><img src="./resources/images/del.gif" /></button>
<!--
<a href="delete?num=${data.num}&page=${page}">
<img src="./resources/images/del.gif" />
</a>
-->
<a href="list?page=${page}">
<img src="./resources/images/list.gif" />
</a>
</td>
</tr>
</table>
<table border="1" style="width: 80%">
<tr>
<td>
작성자 : <a href="mailto:${data.mail}">${data.name}</a>
(ip : ${data.bip})
</td>
<td>작성일 : ${data.bdate}</td>
<td>조회수 : ${data.readcnt}</td>
</tr>
<tr>
<td colspan="3">제목 : ${data.title}</td>
</tr>
<tr>
<td colspan="3">
<textarea rows="5" readonly="readonly" style="width:99%">${data.cont}</textarea>
</td>
</tr>
</table>
</div>
</body>
=> 댓글 기능 : 요청명 reply로 num과 page 값 전달.
=> 수정 기능 : 요청명 update로 num과 page 값 전달.(GET방식)
=> 삭제 기능 : 비밀번호 입력 prompt 출력 후 입력시 요청명 delete로 num, page, password 값 전달.
=> 목록 보기 기능 : 전체 list 출력 페이지로 이동.
=> msg가 있을 경우 pop-up창으로 발생.
⑥ 게시글 수정
- UpdateController
@Controller
public class UpdateController {
@Autowired
private BoardDaoInter inter;
@RequestMapping(value="update", method=RequestMethod.GET)
public ModelAndView edit(@RequestParam("num") String num,
@RequestParam("page") String page) {
// 모델에서 수정할 자료 읽기
BoardDto dto = inter.getDetail(num);
ModelAndView view = new ModelAndView("update");
view.addObject("data", dto);
view.addObject("page", page);
return view;
}
...
}
=> 상세 페이지에서 수정 버튼 클릭시 실행.
=> getDetail() : 해당 데이터값 리턴.
=> update.jsp 실행.
- update.jsp
<script type="text/javascript">
window.onload=function(){
document.getElementById("btnUp").onclick = chkUpData;
}
function chkUpData(){
if(upFrm.pass.value === ""){
upFrm.pass.focus();
alert("비밀번호를 입력하세요");
return;
}
if(confirm("정말 수정할까요?")){
upFrm.submit();
}
}
</script>
</head>
<body>
<jsp:include page="./top.jsp"></jsp:include>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:if test="${msg != null}">
<script type="text/javascript">
(function msg(){
alert("${msg}");
})();
location.href="list?page=${page}";
</script>
</c:if>
<div class="container">
<h4 style="text-align: center;">- 수정 -</h4>
<form action="update" method="post" name="upFrm">
<input type="hidden" name="num" value="${data.num}">
<input type="hidden" name="page" value="${page}">
<table class="table" style="width: 80%">
<tr>
<td>이름</td>
<td><input type="text" name="name" value="${data.name}"></td>
</tr>
<tr>
<td>암호</td>
<td><input type="text" name="pass"></td>
</tr>
<tr>
<td>메일</td>
<td><input type="text" name="mail" value="${data.mail}"></td>
</tr>
<tr>
<td>제목</td>
<td><input type="text" name="title" value="${data.title}"></td>
</tr>
<tr>
<td>내용</td>
<td>
<textarea rows="5" cols="50" name="cont">${data.cont}</textarea>
</td>
</tr>
<tr>
<td colspan="2" style="text-align: center;">
<input type="button" value="수정" id="btnUp">
<input type="button" value="목록" onclick="location.href='list?page=${page}'">
</td>
</tr>
</table>
</form>
</div>
</body>
=> 수정버튼을 누를 경우 비밀번호가 빈칸일 경우 팝업 발생. 있을 경우 요청명 update 전달.(post방식)
=> msg가 있을 경우 pop-up내용 출력 후 list 페이지로 이동.
- UpdateController
@Controller
public class UpdateController {
@Autowired
private BoardDaoInter inter;
...
@RequestMapping(value="update", method=RequestMethod.POST)
public ModelAndView editSubmit(BoardBean bean,
@RequestParam("page") String page) {
// 비밀번호 체크
String pass = inter.selectPass(Integer.toString(bean.getNum()));
ModelAndView view = new ModelAndView();
if(bean.getPass().equalsIgnoreCase(pass)) { // 사용자 비밀번호와 db의 비밀번호 비교
boolean b = inter.update(bean);
if(b) {
//view.setViewName("redirect:/list?page="+page);
view.setViewName("redirect:/detail?num="+bean.getNum()+"&page="+page);
}else {
view.setViewName("redirect:/error");
}
}else {
view.setViewName("update");
view.addObject("msg", "비밀번호 불일치");
view.addObject("page", page);
}
return view;
}
}
=> 수정 페이지에서 수정 버튼 누를 경우 실행.
=> selectPass() : 해당 num의 password 리턴.
=> 입력 패스트워드와 DB의 저장된 비밀 번호가 일치 할 경우 update()메소드 실행.
불일치 시 error msg를 전달하여 update 페이지 실행.
=> update 성공 시 수정 진행한 detail 페이지로 이동. 실패 시 error.jsp 실행.
- BoardDaoImpl
@Repository
public class BoardDaoImpl extends SqlSessionDaoSupport implements BoardDaoInter {
@Autowired
public BoardDaoImpl(SqlSessionFactory factory) {
setSqlSessionFactory(factory);
}
...
@Override
public boolean update(BoardBean bean) {
try {
int result = getSqlSession().update("updateData", bean);
if(result > 0) {
return true;
}else {
return false;
}
} catch (Exception e) {
System.out.println("update err"+e);
return false;
}
}
...
@Override
public String selectPass(String num) { // 수정용 : 비밀 번호 비교
return getSqlSession().selectOne("selectPass", num);
}
...
}
=> update() : 업데이트 성공 시 true, 실패시 false 리턴.
=> selectPass() : 해당 num의 password 리턴.
-DataMapper.xml
...
<update id="updateData" parameterType="formBean">
update board
set name=#{name},mail=#{mail},title=#{title},cont=#{cont}
where num=#{num}
</update>
...
<!-- password -->
<select id="selectPass" parameterType="string" resultType="string">
select pass from board
where num=#{num}
</select>
...
=> update() : 해당 데이터로 수정.
=> selectPass() : 해당 num의 password 리턴.
⑦ 게시글 삭제
- DeleteController
@Controller
public class DeleteController {
@Autowired
private BoardDaoInter inter;
@RequestMapping("delete")
public ModelAndView del(@RequestParam("num") String num,
@RequestParam("page") String page,
@RequestParam("pass") String pass) {
BoardDto dto = inter.getDetail(num);
ModelAndView view = new ModelAndView();
System.out.println(pass);
if(dto.getPass().equalsIgnoreCase(pass)) { // 사용자 비밀번호와 db의 비밀번호 비교
boolean b = inter.delete(num);
if(b) {
view.setViewName("redirect:/list?page="+page);
}else {
view.setViewName("redirect:/error");
}
}else {
view.setViewName("detail");
view.addObject("data", dto);
view.addObject("msg", "비밀번호 불일치");
view.addObject("page", page);
}
return view;
}
}
=> 상세 페이지에서 delete 버튼 클릭시 실행.
=> 해당 패스워드와 일치 시 delete()메소드 실행.
불일치 시 detail 페이지로 이동하여 error msg 팝업 발생.
=> 데이터 삭제 성공 시 전체 페이지 보기로 이동. 실패 시 error.jsp로 이동.
- BoardDaoImpl
@Repository
public class BoardDaoImpl extends SqlSessionDaoSupport implements BoardDaoInter {
@Autowired
public BoardDaoImpl(SqlSessionFactory factory) {
setSqlSessionFactory(factory);
}
...
@Override
public BoardDto getDetail(String num) {
// 글 내용보기, 글 수정 시 데이터 받아오기
return getSqlSession().selectOne("selectOne",num);
}
...
@Override
public boolean delete(String num) {
try {
int result = getSqlSession().delete("deleteData", num);
if(result > 0) {
return true;
}else {
return false;
}
} catch (Exception e) {
System.out.println("delete err"+e);
return false;
}
}
...
}
=> delete() : 삭제 성공시 true, 실패시 false 리턴.
- DataMapper.xml
<delete id="deleteData" parameterType="string">
delete from board where num=#{num}
</delete>
=> 데이터 삭제.
⑧ 댓글 기능 추가
- ReplyController
@Controller
public class ReplyController {
@Autowired
private BoardDaoInter inter;
@RequestMapping(value="reply", method=RequestMethod.GET)
public ModelAndView reply(@RequestParam("num") String num,
@RequestParam("page") String page) {
ModelAndView view = new ModelAndView("reply");
view.addObject("data", inter.getDetail(num)); // 원글의 데이터
return view;
}
...
}
=> 상세 페이지의 댓글 버튼 클릭시 실행.
=> 원본 글의 데이터를 저장 후 reply.jsp 실행.
- reply.jsp
<head>
<script type="text/javascript">
window.onload=function(){
document.getElementById("btnReply").onclick = chk;
}
function chk(){
if(reFrm.name.value === ""){
alert("작성자 이름을 입력하세요");
reFrm.name.focus();
}
// 입력자료 오류 검사
reFrm.submit();
}
</script>
</head>
<body>
<jsp:include page="./top.jsp"></jsp:include>
<h4 style="text-align: center;">* 댓글 쓰기</h4>
<form action="reply" method="post" name="reFrm">
<input type="hidden" name="num" value="${data.num}">
<input type="hidden" name="page" value="${page}">
<input type="hidden" name="gnum" value="${data.gnum}">
<input type="hidden" name="onum" value="${data.onum}">
<input type="hidden" name="nested" value="${data.nested}">
<input type="hidden" name="bip" value="<%=request.getRemoteAddr()%>">
<table class="table" style="width: 80%">
<tr>
<td>이름</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>암호</td>
<td><input type="text" name="pass"></td>
</tr>
<tr>
<td>메일</td>
<td><input type="text" name="mail"></td>
</tr>
<tr>
<td>제목</td>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="title" value="${data.title}"/>
<td><input type="text" name="title" value="[Re]:${fn:substring(title,0,8)}"></td>
</tr>
<tr>
<td>내용</td>
<td>
<textarea rows="5" style="width:99%" name="cont"></textarea>
</td>
</tr>
<tr>
<td colspan="2" style="text-align: center;">
<input type="button" value="작성" id="btnReply">
<input type="button" value="목록" onclick="location.href='list?page=${page}'">
</td>
</tr>
</table>
</form>
</body>
=> 댓글 제목이 8보다 클 경우 substring하여 출력.
=> 작성 버튼 클릭 시 작성자이 비어 있을 경우 팝업 발생. 성공 시 reply 요청명 전달(post방식)
- ReplyController
@Controller
public class ReplyController {
@Autowired
private BoardDaoInter inter;
...
@RequestMapping(value="reply", method=RequestMethod.POST)
public String replySubmit(BoardBean bean,
@RequestParam("page") String page) {
// onum 갱신
bean.setOnum(bean.getOnum() + 1);
inter.updateOnum(bean); // 반환값 처리 필요.
// 댓글 저장
bean.setBdate(); // 작성일 set
bean.setNum(inter.currentNum() + 1); // 새로운 글의 번호
bean.setNested(bean.getNested() + 1); // 들여쓰기
if(inter.insertReply(bean)) {
return "redirect:list?page="+page; // 추가 후 글 목록 보기
}else {
return "redirect:error";
}
}
}
=> updateOnum() : 원글 내 댓글 번호를 업데이트 한다.
=> insertReply() : 작성일, num+1, 들여쓰기+1하여 댓글을 추가 한다.
- BoardDaoImpl
@Repository
public class BoardDaoImpl extends SqlSessionDaoSupport implements BoardDaoInter {
@Autowired
public BoardDaoImpl(SqlSessionFactory factory) {
setSqlSessionFactory(factory);
}
...
@Override
public boolean updateOnum(BoardBean bean) {
//댓글에서 onum 갱신
int result = getSqlSession().update("updateOnum", bean);
if(result>0) {
return true;
}else {
return false;
}
}
@Override
public boolean insertReply(BoardBean bean) {
try {
int result = getSqlSession().insert("insertReData", bean);
if(result > 0) {
return true;
}else {
return false;
}
} catch (Exception e) {
System.out.println("insertReply err"+e);
return false;
}
}
}
=> updateOnum() : 업데이트 성공 시 true, 실패 시 false 리턴.
=> insertReply() : 추가 성공 시 true, 실패 시 false 리턴.
...
<!-- reply -->
<update id="updateOnum" parameterType="formBean">
update board set onum=onum + 1
where onum >= #{onum} and gnum=#{gnum}
</update>
<insert id="insertReData" parameterType="formBean">
insert into board
values(#{num},#{name},#{pass},#{mail},#{title},#{cont},
#{bip},#{bdate},0,#{gnum},#{onum},#{nested})
</insert>
</mapper>
=> 모든 데이터 중 onum이 group num이 같고 onum이 클 경우 onum을 +1한다.
=> 댓글 정보를 추가한다.