java/com/example에 dto 폴더를 생성하여 Board.java를 생성한다.
package com.example.dto;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(exclude = {"regdate"})
@NoArgsConstructor
@AllArgsConstructor
public class Board {
private long no;
private String title;
private String content;
private String writer;
private long hit;
private Date regdate;
}
Board.java
<!DOCTYPE html>
<html lang="en">
<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>
<div>
<h3>게시판 글쓰기</h3>
<hr />
</div>
</body>
</html>
insert.html을 생성한다.
<body>
홈화면
<p th:text="${title}"></p>
<div th:text="${abc}"></div>
<a th:href="@{/board/insert.do}">게시판 글쓰기</a>
</body>
home.html에 위 코드를 추가하면
게시판 글쓰기로 이동하는 링크가 추가된다.
<body>
<div>
<h3>게시판 글쓰기</h3>
<hr />
<form th:action="@{/board/insert.do}" method="post">
제목 : <input type ="text" name="title" /><br />
내용 : <input type ="text" name="content" /><br />
작성자 : <input type ="text" name="writer" /><br />
<input type ="submit" value="글쓰기" />
</form>
</div>
</body>
insert.html을 수정한다.
게시판 글쓰기를 누르면
이렇게 작성한대로 추가된다.
주소가 사진처럼 바뀌는 모습을 볼 수 있다.
<form th:action="@{/board/insert.do}" method="post">
제목 : <input type ="text" name="title" value="1" /><br />
내용 : <input type ="text" name="content" value="2" /><br />
작성자 : <input type ="text" name="writer" value="3" /><br />
<input type ="submit" value="글쓰기" />
</form>
insert.html을 위처럼 수정한다.
이렇게 값이 추가된다.
글쓰기 버튼을 누르면
이런 오류가 뜬다.
POST로 받는 곳이 없기 때문이다.
POST를 만들어보자
public class BoardController {
// 게시판 글쓰기
@PostMapping(value ="/insert.do")
public String insertPost(
@RequestParam(name = "title") String title,
@RequestParam(name = "content") String content,
@RequestParam(name = "writer") String writer ) {
// 넘어온 값 확인
System.out.println(title);
System.out.println(content);
System.out.println(writer);
// DB에 추가
// 적절한 페이지로 이동(게시판 목록으로)
return "redirect:select.do";
}
BoardController를 위처럼 수정한다.
글쓰기 버튼을 누르면
return에 입력한 주소값인 select.do로 이동하게 된다.
// 게시판 글쓰기
@PostMapping(value ="/insert.do")
public String insertPost(
@RequestParam(name = "title") String title,
@RequestParam(name = "content") String content,
@RequestParam(name = "writer") String writer ) {
Board obj = new Board();
obj.setTitle(title);
java를 사용할 땐 이렇게 객체를 만들어서 obj.setTitle(title); 이런 식으로 정보를 받아왔지만
// 게시판 글쓰기
@PostMapping(value ="/insert.do")
public String insertPost( @ModelAttribute Board board){
System.out.println(board.toString());
// DB에 추가
// 적절한 페이지로 이동(게시판 목록으로)
return "redirect:select.do";
}
Spring은 이렇게 @ModelAttribute 를 이용하여 dto파일로 바로 정보를 받아올 수 있다.
맨 아래쪽에 Board의 정보를 받아온 모습을 볼 수 있다.
dto에 작성한 이름과 html의 name값이 같아야만 불러올 수 있다.
<!-- h2, oracle, mysql-->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
pom.xml에 dependency를 추가한다.
# db 연동
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:tcp://1.234.5.158:31521/ds201;Mode=Oracle
spring.datasource.username=sa
spring.datasource.password=
application.properties에 위 코드를 추가한다.
늘 사용하던 h2 주소이다.
application.properties 코드 뒤에 공백(스페이스바)가 있으면 안되니 꼭 주의하자.
service 폴더에 BoardService.java를 생성한다.
package com.example.service;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Service;
import com.example.dto.Board;
// shift + alt + o : 자동 임포트
@Service
public interface BoardService {
// 게시글 등록
public int insertBoardOne(@Param("obj") Board obj);
}
BoardService.java
이어서 BoardServiceImpl도 생성한다.
빨간줄이 생기는 BoardServiceImpl을 누르면 왼쪽에 노란색 전구 아이콘을 눌러
Add unimplemented methods를 선택한다.
@Service
public class BoardServiceImpl implements BoardService {
@Override
public int insertBoardOne(Board obj) {
try{
}
catch(Exception e){
throw new UnsupportedOperationException("Unimplemented method 'insertBoardOne'");
}
}
}
BoardServiceImpl이다.
이제 Mapper를 생성하자.
src - main - java - com - example에 mapper 폴더를 생성하여 그 안에 BoardMapper.java를 만든다.
@Mapper
public interface BoardMapper {
// 글쓰기
@Insert({
" INSERT INTO board(title, content, writer) VALUES(#{obj.title}, #{obj.content}, #{obj.writer}) "
})
public int insertBoardOne(@Param("obj") Board obj);
}
BoardMapper.java
@Service
public class BoardServiceImpl implements BoardService {
@Autowired
BoardMapper bMapper;
@Override
public int insertBoardOne(Board obj) {
try{
return bMapper.insertBoardOne(obj);
}
catch(Exception e){
throw new UnsupportedOperationException("Unimplemented method 'insertBoardOne'");
}
}
}
BoardServiceImpl을 위처럼 수정한다.
@Autowired는 자동으로 객체를 생성해주는 기능이다.
뒤에 객체명인 BoardMapper bMapper;까지 꼭 작성해야 한다.
@RequestMapping(value="/board")
public class BoardController {
@Autowired BoardService bService;
// 게시판 글쓰기
@PostMapping(value ="/insert.do")
public String insertPost( @ModelAttribute Board board){
System.out.println(board.toString());
int ret = bService.insertBoardOne(board);
if(ret == 1){ // 성공시
// 적절한 페이지로 이동(게시판 목록으로)
// return "redirect://member/select.do";
return "redirect:select.do";
}
// 실패시
return "redirect:insert.do";
}
BoardController.java를 위처럼 수정한다.
@Autowired 또한 추가한다.
// 새로운 패키지를 생성하고 역할을 부여하면 반드시 실행파일에 등록해야 함.
@SpringBootApplication
@MapperScan(basePackages = {"com.example.mapper"}) // mapper 위치
@ComponentScan(basePackages = {"com.example.controller", "com.example.service"}) // 컨트롤러, 서비스 위치 설정
Boot20230427Application.java에 위 코드를 추가한다.
@Controller
@RequestMapping(value="/board")
@RequiredArgsConstructor // 클래스에서만 가능함, 인터페이스에서는 안됨.
public class BoardController {
final BoardService bService;
// @Autowired BoardService bService;
BoardController를 위처럼 수정한다.
// 전체조회
@Select({
" SELECT b.* FROM board b ORDER BY no DESC "
})
public List<Board> selectBoardList();
mapper를 추가한다.
// 전체조회
public List<Board> selectBoardList();
BoardService에도 추가하고
@Service
@RequiredArgsConstructor
public class BoardServiceImpl implements BoardService {
final BoardMapper bMapper; // @Autowired BoardMapper bMapper;와 같음
...
@Override
public List<Board> selectBoardList() {
try{
return bMapper.selectBoardList();
}
catch(Exception e){
e.printStackTrace();
return null;
}
}
BoardServiceImpl에도 추가한다.
// 127.0.0.1:9090/ROOT/board/select.do
@GetMapping(value="/select.do")
public String selectGET(Model model){
List<Board> list = bService.selectBoardList();
model.addAttribute("list", list);
// templates에서 board폴더를 생성하고 select.html생성
return "/board/select";
}
BoardController.java에 추가로 작성한다.
<body>
<h3>게시글목록</h3>
<a th:href="@{/board/insert.do}">글쓰기</a>
<table>
<thead>
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
<th>조회수</th>
<th>날짜</th>
</tr>
</thead>
<tbody>
<tr th:each="one : ${list}">
<td th:text="${one.no}"></td>
<td th:text="${one.title}"></td>
<td th:text="${one.writer}"></td>
<td th:text="${one.hit}"></td>
<td th:text="${one.regdate}"></td>
</tr>
</tbody>
</table>
</body>
</html>
select.html도 추가하여 서버에 연결해보자.
글쓰기를 누르면
1 2 3이 추가로 등록되고 DB에 저장되어있는 정보들이 나온다.
@GetMapping(value = {"/selectone.do"})
public String selectoneGET(
Model model,
@RequestParam(name = "no", defaultValue = "0", required = false) long no){
System.out.println(no);
if(no == 0){
return "redirect:select.do";
}
Board obj = bService.selectBoardOne(no);
model.addAttribute(obj); // key를 생략했으면 변수명 obj가 키값임.
return "board/selectone"; // board 폴더에 selectone.html 생성하기
}
BoardController에 위 코드를 추가한다.
// 하나 조회
@Select({
" SELECT b.* FROM board b WHERE no = #{no} "
})
public Board selectBoardOne(@Param("no") long no);
mapper를 생성하고
// 하나 조회
public Board selectBoardOne(@Param("no") long no);
BoardService
@Override
public Board selectBoardOne(long no){
try{
return bMapper.selectBoardOne(no);
}
catch (Exception e){
e.printStackTrace();
return null;
}
}
BoardServiceImpl에 추가한다.
<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>
<p th:text="${obj.no}"></p>
<p th:text="${obj.title}"></p>
<p th:text="${obj.content}"></p>
<p th:text="${obj.writer}"></p>
<p th:text="${obj.hit}"></p>
<p th:text="${obj.regdate}"></p>
<a th:href="@{/board/update.do(no=${obj.no})}">수정</a>
<form th:action="@{/board/delete.do}" method="post">
<input type="hidden" name="no" th:value="${obj.no}" />
<input type="submit" value="삭제" />
</form>
</body>
마지막으로 board 폴더에 selectone.html을 생성하여 위와 같이 작성하면
이렇게 선택한 게시글에 해당하는 정보들이 나오게 된다.
@GetMapping(value="/update.do")
public String updateGET(
Model model,
@RequestParam(name = "no", defaultValue = "0", required = false) long no){
if(no == 0){
return "redirect:select.do";
}
Board obj = bService.selectBoardOne(no);
model.addAttribute("obj", obj);
return "/board/update";
}
BoardController에 위 코드를 추가하고
<body>
<form th:action="@{/board/update.do(no=${obj.no})}" method="post">
<input type="text" name="no" th:value="${obj.no}" readonly/><br />
<input type="text" name="title" th:value="${obj.title}" /><br />
<input type="text" name="content" th:value="${obj.content}" /><br />
<input type="text" name="writer" th:value="${obj.writer}" /><br />
<input type="text" th:value="${obj.hit}" readonly/><br />
<input type="text", th:value="${obj.regdate}" readonly/><br />
<input type="submit" value="수정"><br />
</form>
</body>
update.html을 생성한다.
이런 화면이 나오면 성공이다.
// sql문이 없음 => resources/mappers/파일명Mapper.xml
public int updateBoardOne(@Param("obj") Board obj);
Mapper를 추가한다. 하지만 sql문이 존재하지 않는다.
resources 아래 mapper폴더를 생성하고 boardMapper.xml을 생성한다.
# sql문이 있는 위치 설정(mybatis)
mybatis.mapper-locations=classpath:/mapeprs/*Mapper.xml
application.properties에 위 코드를 작성한다.
deleteBoardOne도 추가하였다
위 사진에서 기존에 사용하던 BoardMapper와 resources폴더에서 만든 boardMapper를 비교해보자.
같은 색의 밑줄친 곳은 꼭 동일해야 한다. 그렇게 해야 서로 연동이 되며 정상적으로 구동이 된다.
// 수정
public int updateBoardOne(Board obj);
// 삭제
public int deleteBoardOne(long no);
BoardService.java에 추가하고
@Override
public int updateBoardOne(Board obj) {
try{
return bMapper.updateBoardOne(obj);
}
catch (Exception e){
e.printStackTrace();
return 0;
}
}
@Override
public int deleteBoardOne(long no) {
try{
return bMapper.deleteBoardOne(no);
}
catch (Exception e){
e.printStackTrace();
return 0;
}
}
BoardServiceImpl에도 추가한다.
@PostMapping(value = "/update.do")
public String updatePOST(@ModelAttribute Board board) {
int ret = bService.updateBoardOne(board);
if (ret == 1) {
return "redirect:selectone.do?no=" + board.getNo(); // 성공시 상세 화면
}
return "redirect:update.do?no=" + board.getNo(); // 실패시 수정 화면
}
@PostMapping(value = "/delete.do")
public String deletePOST(
@RequestParam(name = "no", defaultValue = "0", required = false) long no) {
System.out.println(no);
if (no == 0) {
return "redirect:select.do";
}
int ret = bService.deleteBoardOne(no);
if (ret == 1) {
return "redirect:select.do";
}
return "redirect:boardone.do?no=" + no;
}
마지막으로 BoardController에 update, delete에 대한 POST를 추가한다.
resources 안의 폴더명을 mapper=> mapeprs
application.properties 내의 mapeprs => mappers로 오타 수정
정상적으로 수정됨.
삭제도 정상적으로 수행됨.