10일차 특이사항
1. 10일차다. 출근길 mvc란 무엇인지 영상 시청.
2. 오늘 게시판 수정기능을 추가해보려고 한다.
3. 뭐가 오류인지 데이터가 넘어가지 않는다. 머리가 복잡하다.
4. 저녁 11시까지 붙잡고 결국 체크박스 삭제까지 완료했다. 뿌듯하다.
게시판 수정하기 기능 추가 , 게시판 MVC 구조의 흐름
1. 목표 : '게시판 리스트(boardList.jsp)'에서 글의 '제목' 을 클릭 했을 때 '상세 페이지(detail.jsp)'로 이동이 되고, 상세페이지에서 '수정하기' 버튼을 눌렀을때 'updateView.jsp'로 이동하고 수정할 수 있는 페이지가 나온다. '수정완료' 버튼을 누르면 DB에 저장된 기존의 데이터가 새로운 데이터로 업데이트 된다. 수정이 완료된 후 '목록 페이지(boardList.jsp)'로 이동한다.
2. update 쿼리문에 where 조건절을 주지 않아서 모든 게시글들의 제목이 하나로 통일됐다... 사고침. 오라클이 아니었다면 db복구 못했을 것이다.
3. 게시판 MVC 구조의 흐름
● 사용자의 URL 요청 수신 : 사용자가 웹 브라우저 등을 통해 애플리케이션에 요청을 보냅니다. 예를 들어, 게시판 목록을 보고 싶다는 요청을 한다고 가정합니다.
요청 URL : /board/list
● Spring 프론트 컨트롤러의 역할
Spring MVC 프레임워크의 프론트 컨트롤러는 들어오는 요청을 받아 처리할 컨트롤러 메소드를 판별합니다.
@RequestMapping("/board/list")에 대한 처리
● 해당 URL에 매핑된 list() 메소드가 실행됩니다. 이 메소드는 게시글 목록을 조회하여 모델에 담고, "boardList" 뷰로 이동하는 로직을 수행합니다.
● 서비스 계층 호출
service.list(paramMap) 메소드를 호출하여 게시글 목록 데이터를 가져옵니다. paramMap은 필요한 조회 조건 등을 담을 수 있는 맵입니다. 서비스 계층은 DAO를 통해 데이터베이스에서 실제 데이터를 조회하거나 조작합니다.
● 뷰로 데이터 전달
조회된 게시글 목록 데이터를 모델에 추가합니다.
이렇게 모델에 데이터를 추가하면, 해당 데이터는 뷰에서 사용할 수 있게 됩니다.
● 뷰로 이동
return "boardList"를 통해 "boardList"라는 뷰를 반환합니다.
이것은 웹 페이지에서 실제로 보여지는 화면을 지칭합니다.
스프링은 이 뷰 이름을 기준으로 실제 뷰를 렌더링합니다.
이와 같은 흐름으로 사용자의 요청이 들어와 컨트롤러에서 서비스 계층을 통해 데이터를 가져오고, 그 결과를 뷰로 전달하여 최종적으로 사용자에게 웹 페이지가 보여지게 됩니다.
새로운 과제 : 체크박스 누르고 삭제버튼 누르면 해당 게시글이 삭제되는 기능을 추가해라.
1. controller
// 글 삭제하기
@RequestMapping("/board/delete")
public String delete(@RequestParam(name = "chk") Integer[] chk) throws Exception {
try {
for (Integer seq : chk) {
// 데이터베이스에서 해당 seq에 해당하는 항목 삭제
service.delete(seq);
}
return "redirect:/board/list";
} catch (Exception e) {
// 에러 처리
e.printStackTrace();
return "Error occurred during deletion";
}
}
2. Dao, DaoImpl
public interface BoardDao {
List<Map<String, Object>> list(Map<String, Object> paramMap);
// int insert(Map<String, Object> map);
int insert(BoardDto dto);
BoardDto detail(int seq);
int update(BoardDto dto);
int delete(int seq);
}
package com.earth.downtown.dao;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.stereotype.Repository;
import com.earth.downtown.dto.BoardDto;
@Repository("dao")
public class BoardDaoImpl implements BoardDao {
@Inject
public SqlSessionTemplate sqlSession;
@Override
public List<Map<String, Object>> list(Map<String, Object> paramMap) {
// TODO Auto-generated method stub
return sqlSession.selectList("mapper.list");
}
@Override
public int insert(BoardDto dto) {
// TODO Auto-generated method stub
return sqlSession.insert("mapper.insert", dto);
}
@Override
public BoardDto detail(int seq) {
// TODO Auto-generated method stub
System.out.println("seq :" + seq);
System.out.println("selectOne : " + sqlSession.selectOne("mapper.detail", seq));
return sqlSession.selectOne("mapper.detail", seq);
}
@Override
public int update(BoardDto dto) {
// TODO Auto-generated method stub
return sqlSession.update("mapper.update", dto);
}
@Override
public int delete(int seq) {
// TODO Auto-generated method stub
return sqlSession.delete("mapper.delete", seq);
}
}
3. dto
package com.earth.downtown.dto;
import java.sql.Date;
public class BoardDto {
private int seq;
private String name;
private String id;
private String subject;
private String content;
private Date regDate;
private Date uptDate;
private int viewCnt;
public int getSeq() {
return seq;
}
public void setSeq(int seq) {
this.seq = seq;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getRegDate() {
return regDate;
}
public void setRegDate(Date regDate) {
this.regDate = regDate;
}
public Date getUptDate() {
return uptDate;
}
public void setUptDate(Date uptDate) {
this.uptDate = uptDate;
}
public int getViewCnt() {
return viewCnt;
}
public void setViewCnt(int viewCnt) {
this.viewCnt = viewCnt;
}
@Override
public String toString() {
return "BoardDto [seq=" + seq + ", name=" + name + ", id=" + id + ", subject=" + subject + ", content="
+ content + ", regDate=" + regDate + ", uptDate=" + uptDate + ", viewCnt=" + viewCnt + "]";
}
}
4. service, serviceImpl
package com.earth.downtown.service;
import java.util.List;
import java.util.Map;
import com.earth.downtown.dto.BoardDto;
public interface BoardService {
List<Map<String, Object>> list(Map<String, Object> paramMap);
//int insert(Map<String, Object> map);
int insert(BoardDto dto); // dto 사용
BoardDto detail(int seq);
int update(BoardDto dto);
int delete(int seq);
}
package com.earth.downtown.service;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.earth.downtown.dao.BoardDao;
import com.earth.downtown.dto.BoardDto;
@Service("service")
public class BoardServiceImpl implements BoardService{
@Inject
public BoardDao dao;
@Override
public List<Map<String, Object>> list(Map<String, Object> paramMap) {
// TODO Auto-generated method stub
return dao.list(paramMap);
}
@Override
public int insert(BoardDto dto) {
// TODO Auto-generated method stub
return dao.insert(dto);
}
@Override
public BoardDto detail(int seq) {
// TODO Auto-generated method stub
System.out.println("service.seq" + seq);
return dao.detail(seq);
}
@Override
public int update(BoardDto dto) {
// TODO Auto-generated method stub
return dao.update(dto);
}
// @Override
// public int insert(Map<String, Object> map) {
// // TODO Auto-generated method stub
// return dao.insert(map);
// }
@Override
public int delete(int seq) {
// TODO Auto-generated method stub
return dao.delete(seq);
}
}
5. mapper
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper">
<resultMap type="map" id="rsMap">
<result column="seq" property="seq"/>
<result column="mem_name" property="memName"/>
<result column="mem_id" property="memId"/>
<result column="board_subject" property="Subject"/>
<result column="board_content" property="Content"/>
<result column="reg_date" property="regDate"/>
<result column="upt_date" property="uptDate"/>
<result column="view_cnt" property="viewCnt"/>
</resultMap>
<!-- 게시글 조회 -->
<select id="list" resultMap="rsMap">
select
seq
, mem_name
, mem_id
, board_subject
, board_content
, reg_date
, upt_date
, view_cnt
, useyn
from board_study
order by REG_DATE DESC
</select>
<!-- 글쓰기 -->
<insert id = "insert" parameterType="map">
insert into board_study(
SEQ
,MEM_NAME
,MEM_ID
,BOARD_SUBJECT
,BOARD_CONTENT
,REG_DATE
,VIEW_CNT
,USEYN
)values(
(select nvl(max(seq), 0) + 1 from board_study)
,#{name}
,#{id}
,#{subject}
,#{content}
,sysdate
,0
,'Y'
)
</insert>
<!-- 상세 페이지 -->
<select id="detail" parameterType="int" resultType="com.earth.downtown.dto.BoardDto">
select
SEQ AS seq
,BOARD_SUBJECT AS subject
,BOARD_CONTENT AS content
from board_study
where SEQ = #{seq}
</select>
<!-- 글 수정하기 -->
<update id="update" parameterType="com.earth.downtown.dto.BoardDto">
UPDATE board_study
SET
BOARD_SUBJECT = #{subject},
BOARD_CONTENT = #{content},
UPT_DATE = sysdate
WHERE SEQ = #{seq}
</update>
<!-- 글 삭제하기 -->
<delete id="delete" parameterType="int">
DELETE
FROM board_study
WHERE SEQ = #{seq}
</delete>
</mapper>
6. boardList.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri = "http://java.sun.com/jsp/jstl/fmt" %>
<c:set var="loginout" value="${sessionScope.id == null ? 'Login' : 'Logout' }" />
<c:set var="loginoutlink" value="${sessionScope.id == null ? '/login/login' : '/login/logout' }" />
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://code.jquery.com/jquery-3.6.3.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css">
<link rel="stylesheet" href="<c:url value='/resources/css/board.css' />" />
<link rel="stylesheet" href="<c:url value='/resources/css/menu.css' />" />
<title>게시판 리스트</title>
</head>
<script>
$(document).ready(function() {
// 삭제 버튼 누를 시
$(function(){
$("#delBtn").click(function(){
$("#listFrm").attr("action","delete").attr("method","post").submit();
})
})
//전체 체크시 모든 체크박스 체크됨
var chkList = $("input[name=chk]"); //같은 name은 배열로 인식한다. 한번에 통제할 수 있음.
$("#all").click(function(){
if($(this).is(":checked")){
chkList.prop("checked", true); //prop을 사용하면 속성값을 가져오고 직접 설정할 수 있다. true로 설정하면 체크됨.
} else {
chkList.prop("checked", false);
}
});
//나머지 버튼 중 하나가 체크해제되면 전체 체크 해제됨.
chkList.not("#all").click(function(){
if(!$(this).is(":checked")){
$("#all").prop("checked", false);
}
});
//체크박스가 모두 클릭되면 전체 체크됨
$("input[name=chk]").not("#all").click(function() {
var allChecked = true;
$("input[name=chk]").not("#all").each(function() { // chk1을 제외한 나머지 배열들을 각각 확인한다.
if (!$(this).is(":checked")) { // 하나라도 체크가 되어 있지 않다면 false를 반환한다.
allChecked = false;
}
});
$("#all").prop("checked", allChecked); // false를 받으면 전체 체크x, true를 받으면 전체 체크됨
});
});
</script>
<body>
<div id="menu">
<ul>
<li id="logo">Web</li>
<li><a href="<c:url value='/' />">Home</a></li>
<li><a href="<c:url value='/board/list' />">Board</a></li>
<li><a href="<c:url value='${loginoutlink}' />">${loginout}</a></li>
<li><a href="<c:url value='/signup/list' />">SignUp</a></li>
<li><a href="<c:url value='/file/list' />">File</a></li>
<li><a href="<c:url value='/chkbox/list' />">chkbox</a></li>
<li><a href=""><i class="fas fa-search small"></i></a></li>
</ul>
</div>
<div id="btnContainer">
<input type = "button" name = "delBtn" id = "delBtn" value = "삭제">
<input type = "button" name = "writeBtn" id= "writeBtn" value="글쓰기" onclick="location.href='../board/write'">
</div>
<form name="listFrm" id="listFrm">
<table border="1">
<thead>
<tr>
<th><input id="all" type="checkbox" name="all"></th>
<th>글번호</th>
<th>작성자(ID)</th>
<th>제목</th>
<th>작성일</th>
<th>수정일</th>
<th>조회수</th>
</tr>
</thead>
<tbody id="tableBody">
<c:forEach var="b" items="${list}" varStatus="loop" begin="0" end="9">
<tr id="trList">
<td><input type="checkbox" name="chk" value="${b.seq}"></td>
<td>${b.seq}</td>
<td>${b.memName}(${b.memId})</td>
<td><a href="<c:url value='/board/detail'/>?seq=${b.seq}">${b.Subject}</a></td>
<td><fmt:formatDate value="${b.regDate}" pattern="yyyy-MM-dd"/></td>
<td><fmt:formatDate value="${b.uptDate}" pattern="yyyy-MM-dd"/></td>
<td>${b.viewCnt}</td>
</tr>
</c:forEach>
</tbody>
</table>
</form>
</body>
</html>
무조건 해결한다
어떻게 해서든지 무조건 해결한다. 오늘은 정말 하루종일 앉아서 문제를 해결했다. 내가 이긴다. 결국 내가 이길 것이다. 나는 결국 승리할 것이다.
'일경험' 카테고리의 다른 글
[국민취업지원제도 일경험프로그램 12일차] SQL 문제 풀이(JOIN) (0) | 2023.08.17 |
---|---|
[국민취업지원제도 일경험프로그램 11일차] SQL문제, 게시판 상세조회 페이지 (0) | 2023.08.16 |
[국민취업지원제도 일경험프로그램 9일차] 게시판 상세페이지 만들기 (1) | 2023.08.11 |
[국민취업지원제도 일경험프로그램 8일차] 게시판 글쓰기 기능 : jsp에서 db로 데이터 보내기 (0) | 2023.08.11 |
[국민취업지원제도 일경험프로그램 7일차] 게시판 만들기 (map사용) (1) | 2023.08.09 |