Board.java

package com.example.projectquestion.board;
import java.time.LocalDateTime;
import java.util.List;
import com.example.projectquestion.customer.Customer;
import com.example.projectquestion.reply.Reply;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import lombok.Data;

@Data
@Entity
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer bid;
@Column(length = 200)
private String btitle;
@Column(columnDefinition = "TEXT")
private String bcontent;
@ManyToOne//앞 Many 가 나 즉 질문들 뒤가 작성자, 하나의 작성자가 여러 질문을 작성할수 있다.
private Customer bauthor; // User's Object
@OneToMany(mappedBy = "rboard", cascade = CascadeType.REMOVE)
private List<Reply> replyList;
private LocalDateTime bdate;
}


      BoardRepository.java

package com.example.projectquestion.board;
import org.springframework.data.jpa.repository.JpaRepository;
public interface BoardRepository extends JpaRepository<Board, Integer> {
}


      BoardService / BoardServiceImpl.java

package com.example.projectquestion.board;
import java.security.Principal;
import java.util.List;
public interface BoardService {
void create(Board board, Principal principal);

List<Board> readlist();

Board readdetail (Integer bid);

void update(Board board);

void delete(Integer bid);


}






package com.example.projectquestion.board;
import java.security.Principal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.projectquestion.customer.Customer;
import com.example.projectquestion.customer.CustomerRepository;
@Service
public class BoardServiceImpl implements BoardService {

@Autowired
private BoardRepository boardRepository;
@Autowired
private CustomerRepository customerRepository;

@Override
public void create(Board board, Principal principal) {
board.setBdate(LocalDateTime.now());
Optional<Customer> tc = customerRepository.findByusername(principal.getName());
board.setBauthor(tc.get());
boardRepository.save(board);
}
@Override
public List<Board> readlist() {
return boardRepository.findAll();
}
@Override
public Board readdetail(Integer bid) {
Optional<Board> tb = boardRepository.findById(bid);
return tb.get();
}
@Override
public void update(Board board) {
boardRepository.save(board);
}
@Override
public void delete(Integer bid) {
Optional<Board> tb = boardRepository.findById(bid);
boardRepository.delete(tb.get());
}
}



      BoardController

package com.example.projectquestion.board;
import java.security.Principal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@RequestMapping("/board")
@Controller
public class BoardController {

@Autowired
private BoardService boardService;

@GetMapping("/create")
public String create() {
return "board/create";
}

@PostMapping("/create")
public String create(Board board, Principal principal) {
boardService.create(board, principal);
return "redirect:/board/readlist";
}

@GetMapping("/readlist")
public String readlist(Model model) {
model.addAttribute("boards", boardService.readlist());
return "board/readlist";
}

@GetMapping("/readdetail/{bid}")
public String readdetail(@PathVariable("bid") Integer bid,
Model model) {
model.addAttribute("board", boardService.readdetail(bid));
return "board/readdetail";
}

@GetMapping("/update/{bid}")
public String update(@PathVariable("bid") Integer bid, Model model) {
model.addAttribute("board", boardService.readdetail(bid));
return "board/update";
}

@PostMapping("/update")
public String update(Board board) {
boardService.update(board);
return "redirect:/board/readlist";
}
}


      create.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<span sec:authorize="isAnonymous()">Signin First...<a href="/signin">Sign in</a></span>
<span sec:authorize="isAuthenticated()">Welcome...<span th:text="${#authentication.name}"></span>
<span th:text="${#authentication.authorities}"></span>
<a href="/signout">Sign out</a>
</span>
<h1> Board Create </h1>
<form action="/board/create" method="post">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<p>Title : <input type="text" name="btitle">
<p>Content : <input type="text" name="bcontent">
<p><input type="submit" value="submit">
</form>
<p><a href="/board/readlist">Board List</a>
</body>
</html>







      readlist.html


<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>
<h1> Read List </h1>
<a href="/board/create">CREATE</a><br><br>
<th:block th:each="board: ${boards}">
[[${board.bid}]] /
<a th:href="@{|/board/readdetail/${board.bid}|}" th:text="${board.btitle}"></a>
/ [[${board.bauthor.username}]] / [[${board.bdate}]]<br>
</th:block>
</body>
</html>





<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2> Read Detail </h2>
<a href="/board/readlist">List</a><br><br>
Id : [[${board.bid}]] <br>
Title : [[${board.btitle}]]<br>
Content : [[${board.bcontent}]]<br>
Username : [[${board.bauthor.username}]] <br>
Date : [[${board.bdate}]]<br>
<br><br>
<p><a th:href="@{|/board/update/${board.bid}|}"> update</a>
<p><a th:href="@{|/board/delete/${board.bid}|}"> delete</a>
<br>
<h4>Create Reply</h4>
<form action="/reply/create" method="post">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<input type="hidden" name="bid" th:value="${board.bid}"/>
<p>Content : <input type="text" name="rcontent">
<input type="submit" value="create">
</form>








      Reply.java


package com.example.projectquestion.reply;
import java.time.LocalDateTime;
import com.example.projectquestion.board.Board;
import com.example.projectquestion.customer.Customer;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import lombok.Data;
@Data
@Entity
public class Reply {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer rid;

@Column(columnDefinition = "TEXT")
private String rcontent;

@ManyToOne
private Customer rauthor; // User's Object

@ManyToOne
private Board rboard;

private LocalDateTime rdate;
}





ReplyRepository.java

package com.example.projectquestion.reply;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ReplyRepository extends JpaRepository<Reply, Integer> {
}




ReplyService / ReplyServiceImpl.java

package com.example.projectquestion.reply;
import java.security.Principal;
public interface ReplyService {
void create(String rcontent, Integer bid, Principal principal);
}









package com.example.projectquestion.reply;
import java.security.Principal;
import java.time.LocalDateTime;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.projectquestion.board.Board;
import com.example.projectquestion.board.BoardRepository;
import com.example.projectquestion.customer.Customer;
import com.example.projectquestion.customer.CustomerRepository;
@Service
public class ReplyServiceImpl implements ReplyService {
@Autowired
private ReplyRepository replyRepository;

@Autowired
private CustomerRepository customerRepository;

@Autowired
private BoardRepository boardRepository;

@Override
public void create(String rcontent, Integer bid, Principal principal) {
Reply reply = new Reply(); // 새로운 answer 객체 생성

reply.setRcontent(rcontent); // 객체에 답변 내용 넣기

reply.setRdate(LocalDateTime.now()); //객체에 현재 날짜 시간 넣기

Optional<Board> tr = boardRepository.findById(bid);
reply.setRboard(tr.get());

Optional<Customer> tc = customerRepository.findByusername(principal.getName());
reply.setRauthor(tc.get()); //객체에 답변 작성자 정보 객체로 객체에 넣기

replyRepository.save(reply);// 최종 객체 저장
}
}


      ReplyController.java


package com.example.projectquestion.reply;
import java.security.Principal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@RequestMapping("/reply")
@Controller
public class ReplyController {
@Autowired
private ReplyService replyService;

@PostMapping("/create")
public String create(@RequestParam ("rcontent") String rcontent,
@RequestParam ("bid") Integer bid,
Principal principal) {

replyService.create(rcontent, bid, principal);

return "redirect:/board/readdetail/" + bid;
}
}






<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2> Read Detail </h2>
<a href="/board/readlist">List</a><br><br>
Id : [[${board.bid}]] <br>
Title : [[${board.btitle}]]<br>
Content : [[${board.bcontent}]]<br>
Username : [[${board.bauthor.username}]] <br>
Date : [[${board.bdate}]]<br>
<br><br>
<p><a th:href="@{|/board/update/${board.bid}|}"> update</a>
<p><a th:href="@{|/board/delete/${board.bid}|}"> delete</a>
<br>
<h4>Create Reply</h4>
<form action="/reply/create" method="post">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<input type="hidden" name="bid" th:value="${board.bid}"/>
<p>Content : <input type="text" name="rcontent">
<input type="submit" value="create">
</form>
<h4>Replies List</h4>
There are [[${#lists.size(board.replyList)}]] Replies<br>
<div th:each="reply : ${board.replyList}">
[[${reply.rcontent}]] /
[[${#temporals.format(reply.rdate, 'yyyy-MM-dd HH:mm')}]] /
[[${reply.rauthor.username}]]
<br>
</div>

</body>
</html>









한국정보시스템개발원 |
Hankook Information System Institute

austiny@snu.ac.kr / austiny@gatech.edu