entity/Board.java
package com.example.entity;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.hibernate.annotations.CreationTimestamp;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
@NoArgsConstructor
@Entity
// 생략하면 클래스명이 테이블명 ex) BOARD
@Table(name = "BOARDTBL1")
// 시퀀스 생성
@SequenceGenerator(name = "SEQ1",
sequenceName = "SEQ_BOARDTBL1_NO",
initialValue = 1, allocationSize = 1)
public class Board {
@Id // 기본키
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "SEQ1" )
private Long no = 0L;
// 컬럼명을 생략하면 변수명 ex) TITLE
@Column(name="TITLE", length = 300)
private String title = null;
private String content = null;
@Column(name = "HIT")
private Long hit = 1L;
private String writer = null;
@CreationTimestamp
@Column(name = "REGDATE", updatable = false)
private Date regdate = null;
// mappedBy는 변수명
// @JsonManagedReference(value = "board1")
@OneToMany(mappedBy = "board", cascade = CascadeType.REMOVE)
@OrderBy(value = "no desc") // 정렬하기 no를 기준으로 내림차순
private List<BoardReply> reply;
// mappedBy는 변수명
// @JsonManagedReference(value = "board2")
@OneToMany(mappedBy = "board", cascade = CascadeType.REMOVE)
@OrderBy(value = "no desc") // 정렬하기 no를 기준으로 내림차순
private List<BoardImage> image;
}
controller/BoardController.java
package com.example.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import com.example.entity.Board;
import com.example.entity.BoardReply;
import com.example.repository.BoardReplyRepository;
import com.example.repository.BoardRepository;
@Controller
@RequestMapping(value = "/board")
public class BoardController {
@Autowired BoardRepository bRepository;
@Autowired BoardReplyRepository brRepository;
@PostMapping(value = "/deletebatch.do")
public String deletebatch(
@RequestParam(name="chk") List<Long> chk){
System.out.println(chk.toString());
bRepository.deleteAllById(chk);
return "redirect:/board/select.do";
}
@GetMapping(value="/selectone.do")
public ModelAndView selectOne(@RequestParam(name="no") long no){
//게시글 정보
Board board = bRepository.findById(no).orElse(null);
// 답글목록 확인용
// System.out.println(board.getReply().toString());
// 이미지 확인용
// System.out.println(board.getImage().toString());
List<BoardReply> reply
= brRepository.findByBoard_noOrderByNoAsc(no);
ModelAndView mav= new ModelAndView();
mav.setViewName("board_selectone");
mav.addObject("brd", board);
mav.addObject("reply", reply);
return mav;
}
@PostMapping(value="/update.do")
public String updatePOST(@ModelAttribute Board board){
System.out.println(board.toString());
Board board1 = bRepository.findById(board.getNo()).orElse(null);
board1.setTitle(board.getTitle());
board1.setContent(board.getContent());
board1.setWriter(board.getWriter());
bRepository.save(board1);
return "redirect:/board/select.do";
}
@GetMapping(value="/update.do")
public ModelAndView updateGET(@RequestParam(name="no") Long no){
Board board = bRepository.findById(no).orElse(null);
return new ModelAndView("board_update", "board", board);
}
@PostMapping(value="/delete.do")
public String deletePOST(@RequestParam(name="no") Long no){
try {
bRepository.deleteById(no);
return "redirect:/board/select.do";
}
catch(Exception e) {
return "redirect:/board/select.do";
}
}
@GetMapping(value="/select.do")
public ModelAndView selectGET(){
List<Board> list = bRepository.findAll();
// model.addAttribute("list", list);
// return "board_select";
return new ModelAndView("board_select", "list", list);
}
// 127.0.0.1:8080/ROOT/board/insert.do
@GetMapping(value = "/insert.do")
public String insertGET(){
// view로 전송할 값이 없음
return "board_insert";
}
@PostMapping(value = "/insert.do")
public String insertPOST(@ModelAttribute Board board){
System.out.println(board.toString());
Board ret = bRepository.save(board);
if(ret == null){
return "redirect:/board/insert.do";
}
return "redirect:/board/select.do";
}
}
repository/Repository.java
package com.example.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.example.entity.Board;
// 기존에 생성되어있는 저장소 상속(엔티티, 기본키타입)
@Repository
public interface BoardRepository extends JpaRepository<Board, Long> {
}
templates/board_select.html 로 확인 script로 삭제하기
이유는 form을 쓰면 form안에 form이 적용이 안됌.
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<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">
<title>게시판글쓰기</title>
</head>
<body>
<a th:href="@{/board/insert.do}">글쓰기</a>
<input type="button" value="일괄삭제" th:onclick="|javascript:handleDeleteBatch()|" />
<table border="1">
<tr th:each="obj, idx : ${list}">
<td><input type="checkbox" class="chk" th:value="${obj.no}" /></td>
<td th:text="${obj.no}"></td>
<td>
<a th:href="@{/board/selectone.do(no=${obj.no})}"
th:text="${obj.title}"></a>
</td>
<td th:text="${obj.writer}"></td>
<td th:text="${obj.hit}"></td>
<td th:text="${obj.regdate}"></td>
<td>
<form th:action="@{/board/delete.do}" method="post">
<input type="hidden" name="no" th:value="${obj.no}" />
<input type="submit" value="삭제" />
</form>
<form th:action="@{/board/update.do}" method="get">
<input type="hidden" name="no" th:value="${obj.no}" />
<input type="submit" value="수정" />
</form>
<form th:action="@{/boardimage/insert.do}" method="get">
<input type="hidden" name="no" th:value="${obj.no}" />
<input type="submit" value="이미지등록" />
</form>
</td>
</tr>
</table>
<script>
const handleDeleteBatch = () => {
// form 태그 생성
const form = document.createElement("form");
form.action="[[@{/board/deletebatch.do}]]";
form.method="post";
form.style.display="none";
// 위의 체크박스 전체 가져오기
const chk = document.getElementsByClassName("chk");
for(let i=0;i<chk.length;i++){
if(chk[i].checked){ //체크된 항목만 찾기
const check = document.createElement("input");
check.type="checkbox";
check.name="chk";
check.value = chk[i].value;
check.checked=true;
form.appendChild(check); // 체크된 항목만 form에 추가
}
}
// form을 body에 추가
document.body.appendChild(form);
// form 전송
form.submit();
}
</script>
</body>
</html>
templates/board_insert.html 로 확인
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<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">
<title>게시판글쓰기</title>
</head>
<body>
<form th:action="@{/board/insert.do}" method="post">
<input type="text" placeholder="제목" name="title" />
<input type="text" placeholder="내용" name="content" />
<input type="text" placeholder="작성자" name="writer" />
<input type="submit" value="글쓰기" />
</form>
</body>
</html>