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>