Spring Boot์์ ๊ฒ์๊ธ ๊ด๋ฆฌ ํด๋ณด๊ธฐ! ใฝ(โฟ๏พโฝ๏พ)ใ
- ์ฌ์ฉ IDE : IntelliJ IDEA Ultimate
- ์ฌ์ฉ DB : MySQL
- ์ฌ์ฉ ์ธ์ด & SDK : Java & Amazon correto 11
- ์ ๋ฆฌ๋ณธ์ ๋๋ค ์ฐธ๊ณ ์ฉ์ผ๋ก๋ง ๋ด์ฃผ์ธ์ :D
- ํ์๊ด๋ฆฌ ์์ ์ฒ๋ผ ์ฒ์ฒํ ์งํ ํ ์์ ์ ๋๋ค! ๊ทธ๋ผ ํ๋ก์ ํธ๋ถํฐ ๋ง๋ค๋ฌ ๊ฐ์์ฃ !
ํ๋ก์ ํธ ์ด๋ฆ : BoardProject
๊ธฐ๋ณธ ํจํค์ง : com.icia.board
Type : Gradle
dependency : Spring web, lombok, Thyleaf, Validation, Spring Data Jpa, Mysql Driver
์ค์ ํ ์์ฑ
# ํฌํธ๋ฒํธ๋ ์ ์๋ ์๊ฒน์น๊ฒ ์์ ๋กญ๊ฒ ์ฐ์ธ์!
server:
port: 8096
# DB์ ์ ์ ๋ณด
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springbootclass?serverTimezone=Asia/Seoul&characterEncoding=UTF-8
username: bootuser
password: 1234
# cache๊ฐ์ ์ฌ์ฉํ์ง ์๊ฒ ๋ค๋ ์๋ฏธ
thymeleaf:
cache: false
# JPA ๊ด๋ จ ์ค์ , datasource: ์์น์ ๊ฐ์ ์์น์ ์์ฑํด์ค์ผํจ.
jpa:
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
show-sql: true
hibernate:
ddl-auto: update
# create : ์คํํ ๋ ๋ง๋ค ์ ์ฒด ์ฌ์์
# update : ์คํํ ๋ table drop ์์ด ์คํ.
๊ธฐ๋ณธ๊ธฐ๋ฅ
index.html
BoardController
save.html
BoardSaveDTO
BoardEntity
BoardRepository
์ ํญ๋ชฉ ์ค ๊ฐ๋จํ MainController, index ๋ฑ์ ๊ฑด๋๋ฐ๊ฒ ์ต๋๋ค.
์ด๋ฒ ์๊ฐ์ Thymeleaf๋ฅผ ์์ฃผ ์ฌ์ฉํ ์์ ์ด๋ ์ด ์ ์ฐธ๊ณ ํด์ฃผ์ธ์ :D
๊ทธ๋ผ Entity์์ ์ปฌ๋ผ ์ค์ ์ ์ด๋ป๊ฒ ํ๋์ง๋ง ๋ณด๊ณ , ์ปจํธ๋กค๋ฌ๋ก ๋์ด๊ฐ๊ฒ ์ต๋๋ค.
๊ธด๊ธ์์ ! (22.01.13.๋ชฉ 19:00 ~ 20:00)
BaseEntity ์ถ๊ฐ
๊ธฐ์กด Entity๋ฅผ ์์๋ฐ๋ ์์ํด๋์ค๋ก ์ค์
boardDate ์ญ์ , createTime, updateTime ์ถ๊ฐ
๊ธํ๊ฒ ๋ณ๊ฒฝํ ์ ์ฌ๊ณผ๋๋ฆฝ๋๋ค ( ; ฯ ; )
@Entity
@Getter
@Setter
@Table(name = "board_table")
// BaseEntity๋ฅผ ์์๋ฐ๋ ์์ ํด๋์ค๋ก ์ค์
public class BoardEntity extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "board_id")
private Long id;
@Column
private String boardWriter;
@Column
private String boardPassword;
@Column
private String boardTitle;
@Column
private String boardContents;
// ๊ธฐ์กด boardDate ์ญ์
// @Column
// private LocalDateTime boardDate;
// createTime, updateTime ์ถ๊ฐ๋ BaseEntity์์ ์ถ๊ฐ
}
์ ๋ ์์ ๊ฐ์ด ์ค์ ํ์ต๋๋ค.
Column ์ง์ ํ ์๋ฌด๊ฒ๋ ์ง์ ์ ์ํด์ค๋ค๋ฉด String์ varchar(255)๋ก ์์ฑ์ด ๋ฉ๋๋ค.
์ด๋ ํ์๊ด๋ฆฌ ์์ ์์ ์ค๋ช ํด๋จ์ผ๋ ์ฐธ๊ณ ํด์ฃผ์ธ์.
๊ทธ๋ผ Entity๋ฅผ ๋ง๋ค์์ผ๋ Controller๋ก ๋์ด๊ฐ๋ ค๊ณ ํ์ง๋ง ๊ธด๊ธ ๋ด์ฉ ์์ ์ด ์๊ฒ ์ต๋๋ค...
Entity๋ฅผ ๋ณด์กฐํด์ฃผ๋ ํด๋์ค๋ฅผ ํ๋ ๋ ์์ฑํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.ใฝ(โฟ๏พโฝ๏พ)ใ
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
// ์์ Entity ์ฆ ์์๋ฐ์ Entity ํด๋์ค๊ฐ ๋ฌด์จ ๊ธฐ๋ฅ์ ์ํํ๋์ง ๊ฐ์งํ๋ ์ด๋
ธํ
์ด์
@Getter
public abstract class BaseEntity {
// abstract : ์ถ์ ํด๋์ค
@CreationTimestamp // create ์ฆ insert๊ฐ ์ํ๋ ์๊ฐ
@Column(updatable = false) // update ํ ๋ ๊ฐ์ด ๋ค์ด๊ฐ์ง ์๊ฒ
private LocalDateTime createTime; // insert ์ํํ ์๊ฐ.
@UpdateTimestamp // update ์ฆ update๊ฐ ์ํ๋ ์๊ฐ
@Column(insertable = false) // insert ํ ๋ ๊ฐ์ด ๋ค์ด๊ฐ์ง ์๊ฒ
private LocalDateTime updateTime; // update ์ํํ ์๊ฐ.
}
- ๊ธด๊ธ ์์ ์ฌ์
๊ธฐ์กด boardDate๋ก๋ง ์ฌ์ฉ ์ ์ฐจํ์ ์์ ์๊ฐ ์ฌ์ฉ ๋ถ๊ฐ ๋ฐ ์ค๋ฅ ๋ฐ์์ผ๋ก ์ธํ ์์
๋ถํธ์ ๋ผ์ณ๋๋ ค ์ฃ์กํฉ๋๋ค ลฬฅฬฅฬฅฬฅืลฬฅฬฅฬฅฬฅ
๊ทธ๋ผ Controller์์ ๋ต๊ฒ ์ต๋๋ค...
thymeleaf๋ฅผ ์ด์ฉํ๊ธฐ ์ํด Controller ํ์ด์ง ์์ฒญ๋ฉ์๋์ ๋ด์ฉ์ด ๋ช๊ฐ์ง ์ถ๊ฐ๋๋๊ฒ ์์ต๋๋ค.
์๋ ์ฝ๋๋ฅผ ๋ณด๋ฉฐ ๊ฐ์ด ์ดํดํ์์ฃ !
@Controller
@RequiredArgsConstructor
@Slf4j // ๋ก๊ทธ๋ฅผ ๊ธฐ๋กํ ์ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(์ด๋
ธํ
์ด์
)
// ๋ชฉ๋ก ์ถ๋ ฅ & ์์ธ์กฐํ ๋ ์ฌ์ฉํด๋ณด๊ฒ ์ต๋๋ค.
@RequestMapping("/board")
// /board/* ๋์ ์ /board ๋ ์ฌ์ฉ ๊ฐ๋ฅ, ์ด๋ฒ์ ํ์๋ฅผ ์ฌ์ฉํด๋ณด๊ฒ ์ต๋๋ค!
public class BoardController {
// ๊ธ์์ฑ ํ์ด์ง ์์ฒญ
@GetMapping("/save")
public String saveForm(Model model) {
model.addAttribute("board", new BoardSaveDTO());
return "board/save";
}
}
๊ธฐ์กด์ ๊ทธ์ ์ฃผ์ ์์ฒญ์ ๋ฐ์ผ๋ฉด return์ผ๋ก ํ์ด์ง๋ง ๋์์ฃผ๊ณ ๋์ด์์ง๋ง
thymeleaf์ ์ ์ ๊ณตํ๋ ์ฝ๋๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ์ด์ ๋ง์ถฐ ์ฝ๋๊ฐ ๋ช๊ฐ์ง ์ถ๊ฐ๊ฐ ๋ ๋ชจ์ต์ ๋๋ค.
๋งค๊ฐ๋ณ์์ Model์ด ์ถ๊ฐ๋์๊ณ , return์ ํ๊ธฐ ์ BoardSaveDTO()๋ฅผ model์ ๋ด์๊ฐ๋๋ค.
์ด ์ฝ๋๊ฐ ๋ฌด์จ ์ญํ ์ ํ๋์ง save.html์ ๋ง๋ค๋ฌ ๊ฐ์์ฃ :D
<!DOCTYPE html>
<!-- ์๋ thymeleaf ์ฌ์ฉ๋ฌธ์ ๊ผญ ์ฐ์
์ผํฉ๋๋ค!!!!!! -->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>save.html</h2>
<form action="/board/save" method="post" th:object="${board}">
<!-- th:object="${}" : model์์ ์ค์ ํ ํค๋ฅผ ์ฌ์ฉ -->
<!-- Controller์์ ์ค์ ํ model ํค๊ฐ๊ณผ ๊ฐ๊ฒ ์์ฑํด์ผ ์ค๋ฅ๊ฐ ์๋ฉ๋๋ค!! -->
<input type="text" th:field="*{boardWriter}" placeholder="์์ฑ์">
<!-- th:field="*{}" : DTO์ ํ๋๊ฐ์ inputํ๊ทธ์ id์ name๊ฐ์ผ๋ก ์ฌ์ฉํ๊ฒ ๋ค๋ ์๋ฏธ -->
<!-- ๋ฐ๋์ DTO์ ํ๋ ๋ค์๊ณผ ๊ฐ๊ฒ ์์ฑํด์ผ ์ค๋ฅ๊ฐ ์๋ฉ๋๋ค!! -->
<input type="text" th:field="*{boardPassword}" placeholder="๋น๋ฐ๋ฒํธ">
<input type="text" th:field="*{boardTitle}" placeholder="์ ๋ชฉ">
<input type="text" th:field="*{boardContents}" placeholder="๋ด์ฉ">
<input type="submit" th:value="๊ธ์์ฑ">
</form>
</body>
</html>
์๋๋ ๊ณต๋ฐฑ ์ฒดํฌ ๋ฐ ์ค๋ฅ์ก๋ @Variable๋ ์ฌ์ฉํ๋ ค ํ์ผ๋ ํ๋ฒ์ ๋๋ฌด ๋ง์๊ฑธ ์ฌ์ฉํ๋ฉด
๋ค๋ค ์ด๋ ค์ํ ๊ฑฐ ๊ฐ์์ ์ง๊ธ์ ์ ์ธํ์ต๋๋ค. ๋์ค์ ์์ธํ ๋ค๋ค๋ณผ๊ป์!!์์ ์ฃผ์๊ณผ ๊ฐ์ด th:object="${modelํค๊ฐ}" & th:field="*{DTO ํ๋ ์ด๋ฆ}" ๋ฅผ ์ํด
์ปจํธ๋กค๋ฌ์์ ํ์ด์ง ์์ฒญ ๋ฉ์๋์ model์ ์ฌ์ฉํ๋๊ฒ๋๋ค!!
์์์ฒ๋ผ ์ฝ๋๋ฅผ ์์ฑํ๋ค๋ฉด id์ name๊ฐ์ ์๋ชป ์ง์ ํด ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ ํ๋ฅ ์ ์์จ ์ ์์ต๋๋ค.
์ฒ์์๋ ์ฌ์ฉํ๊ธฐ ๋ถํธํ ์ ์์ง๋ง ๊ณ์ ์ฌ์ฉํด๋ณด๋ฉด์ ์๋ฌํ๋ฉด ์ข๊ฒ ์ฃ ??
๊ทธ๋ผ save.html์ ์์ฑํ์ผ๋ ์ด๋ฅผ ์ ์ฅํ๋ ๋ฉ์๋๋ฅผ ๋ง๋ค๋ฌ Controller๋ก ๊ฐ๋ด ์๋ค :D
// ๊ธ์์ฑ ์ ์ฅ
// thymeleaf๋ฅผ ์ฐ์ง ์๋๋ค๋ฉด @ModelAttribute ์๋ต ๊ฐ๋ฅ
// ์ ๋ ์ผ์ผ๋ฏ๋ก ์์ฑ
@PostMapping("/save")
public String save(@ModelAttribute("board") BoardSaveDTO boardSaveDTO) {
bs.save(boardSaveDTO);
return "index";
}
์ ์ฃผ์์์ ์ค๋ช ํ๊ฒ์ฒ๋ผ ๋ง์ฝ thymeleaf๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ์ผ๋ก form์ ์์ฑํ๋ค๋ฉด @ModelAttribute๋ฅผ ์๋ตํ ์ ์์ต๋๋ค. Spring Boot๊ฐ ์์์ ์ก์์ฃผ๊ธฐ ๋๋ฌธ์ด์ฃ !!
๊ฒ์๊ธ ์ ์ฅ ๋ฉ์๋์ ๋ณ ๋ด์ฉ์ด ์์ผ๋ฏ๋ก ๋ฐ๋ก Service๋ก ๋์ด๊ฐ๊ฒ ์ต๋๋ค.
@Service
@RequiredArgsConstructor
public class BoardServiceImpl implements BoardService {
private final BoardRepository br;
@Override
public Long save(BoardSaveDTO boardSaveDTO) {
BoardEntity boardEntity = BoardEntity.saveBoard(boardSaveDTO);
// DTOํ์
์ Entityํ์
์ผ๋ก ๋ณํ
return br.save(boardEntity).getId();
// ๋ฆฌํด์ผ๋ก ๊ฒ์๊ธ ๋ฒํธ๋ฅผ ๋๊ฒจ์ค.
}
}
Jpa๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ DTOํ์ ์ Entityํ์ ์ผ๋ก ๋ณํ์์ผ์ฃผ๋ ์์ ์ด ํ์ํฉ๋๋ค.
Jpa๋ฅผ ์ฌ์ฉํ ๋ ์ด๋ฅผ ํญ์ ์ฃผ์ํด์ฃผ์ธ์!
public static BoardEntity saveBoard(BoardSaveDTO boardSaveDTO) {
BoardEntity boardEntity = new BoardEntity();
boardEntity.setBoardWriter(boardSaveDTO.getBoardWriter());
boardEntity.setBoardPassword(boardSaveDTO.getBoardPassword());
boardEntity.setBoardTitle(boardSaveDTO.getBoardTitle());
boardEntity.setBoardContents(boardSaveDTO.getBoardContents());
// boardEntity.setBoardDate(LocalDateTime.now());
// ๊ธด๊ธ์์ ์ผ๋ก ์ธํ ์ญ์
return boardEntity;
}
์ฌ๊ธฐ๊น์ง ์ ๋ฐ๋ผ์ค์ จ๋ค๋ฉด ๊ฒ์๊ธ ์ ์ฅ์ ๋ฌธ์ ์์ด ์ ์๋ํ ๊ฒ๋๋ค.
๊ฒ์๊ธ ์์ฑ ์๊ฐ์ BaseEntity์์ ๋ง๋ ๋ด์ฉ์ผ๋ก ์ธํด ์๋์ผ๋ก ๋ค์ด๊ฐ์ง๋๋ค.
๊ทธ๋ผ ๊ฒ์๊ธ ๋ชฉ๋ก ์ถ๋ ฅ์ผ๋ก ๋์ด๊ฐ๋ด ์๋ค!! :D
์ง๊ธ๋ถํฐ ๊ฒ์๊ธ ๋ชฉ๋ก์ถ๋ ฅ์ ๋ํด ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค!
์ด์ ์ ํ์๊ด๋ฆฌ ์์ ๋ฅผ ํ์ ๋ถ์ด๋ผ๋ฉด ๊ฑฐ์ ๋๊ฐ์ด ํ๋ฌ๊ฐ๊ธฐ ๋๋ฌธ์ ๋ฌธ์ ์์ด ์ ํ์ค ์ ์์๊ฒ๋๋ค :D
๊ทธ๋ผ ๋ฐ๋ก ๊ฐ์์ฃ ~!ูฉ(เนโขฬoโขฬเน)ู
๊ฒ์๊ธ ๋ชฉ๋ก ์ถ๋ ฅ์ฉ & ์์ธ์กฐํ๋ฅผ ๊ฐ์ด ์ํํ๋ DTO๋ฅผ ๋ง๋ค์ด์ผํฉ๋๋ค.
DTO๋ฅผ ๋ง๋ค๋ฉด์ Entityํ์ ์ DTOํ์ ์ผ๋ก ๋ณํ์์ผ์ฃผ๋ ๋ฉ์๋๋ฅผ ๋ฏธ๋ฆฌ ์์ฑํด์ค๋๋ค.
์์๋๋ฉด ์ข์ ํ์ผ๋ก ๋ณํ์ด ํ์ํ ํ์ ์ด ์ํ ๋ฉ์๋์ ๋ณํ ๋ฉ์๋๋ฅผ ์์ฑํ๋๊ฒ์ด ์ข์ต๋๋ค!!
toBoardDetailDTO : Entityํ์ ์ DTOํ์ ์ผ๋ก ๋ณํ์์ผ์ฃผ๋ ๋ฉ์๋
toBoardDetailDTOList :List<Entity>
ํ์ ์List<BoardDetailDTO>
ํ์ ์ผ๋ก ๋ณํ
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BoardDetailDTO {
private Long boardId;
private String boardWriter;
private String boardPassword;
private String boardTitle;
private String boardContents;
// boardDate ์ญ์
// private LocalDateTime boardDate;
// ์๋ ๋ ์ค ์ถ๊ฐ
private LocalDateTime createTime;
private LocalDateTime updateTime;
public static BoardDetailDTO toBoardDetailDTO(BoardEntity boardEntity) {
BoardDetailDTO boardDetailDTO = new BoardDetailDTO();
boardDetailDTO.setBoardId(boardEntity.getId());
boardDetailDTO.setBoardWriter(boardEntity.getBoardWriter());
boardDetailDTO.setBoardPassword(boardEntity.getBoardPassword());
boardDetailDTO.setBoardTitle(boardEntity.getBoardTitle());
boardDetailDTO.setBoardContents(boardEntity.getBoardContents());
// boardDetailDTO.setBoardDate(boardEntity.getBoardDate());
boardDetailDTO.setCreateTime(boardEntity.getCreateTime());
boardDetailDTO.setUpdateTime(boardEntity.getUpdateTime());
return boardDetailDTO;
}
public static List<BoardDetailDTO> toBoardDetailDTOList(List<BoardEntity> boardEntityList) {
List<BoardDetailDTO> boardDetailDTOList = new ArrayList<>();
for(BoardEntity b: boardEntityList) {
boardDetailDTOList.add(toBoardDetailDTO(b));
}
return boardDetailDTOList;
}
}
// ๊ธ๋ชฉ๋ก ์ถ๋ ฅ
@GetMapping("/")
public String findAll(Model model) {
log.info("๊ธ๋ณด๊ธฐ ๋ฉ์๋ ํธ์ถ. ์์ฒญ๊ธ๋ฒํธ {}", boardId);
List<BoardDetailDTO> boardDetailDTOList = bs.findAll();
model.addAttribute("boardList", boardDetailDTOList);
return "board/findAll";
}
@GetMapping("/{boardId}")
// {}์์ / ๊ฐ ๋ถ์ด๋ @PathVariable๋ค ("boardId") ์๋ต๊ฐ๋ฅ
public String findById(@PathVariable Long boardId, Model model) {
// ๋ณ์๋ฅผ ์ฐ๊ณ ์ถ๋ค๋ฉด {} ๊ฐ ๋ฐ๋์ ํ์. {}์์ ๋ณ์๊ฐ ๋ค์ด๊ฐ
// ๋ก๊ทธ ์ข
๋ฅ
// info : ํ๋ํ๋ ๋์์ ์ ๋ถ ๊ธฐ๋ก
// warn : ๊ฒฝ๊ณ , ์๋ฌ๋ ์๋์ง๋ง ๋ฌธ์ ์ ์์ง๊ฐ ์๋ค.
// error : ๋ฌธ์ ๋ฐ์
log.info("๊ธ๋ณด๊ธฐ ๋ฉ์๋ ํธ์ถ. ์์ฒญ๊ธ๋ฒํธ {}", boardId);
BoardDetailDTO boardDetailDTO = bs.findById(boardId);
model.addAttribute("boardDetailDTO",boardDetailDTO);
return "board/findById";
}
// ajax๋ ์ ์ธํ๊ฒ ์ต๋๋ค. ์ฌ์ฉํ์ค๋ถ๋ค์ ์๋ ์ฃผ์์ ํด์ ํ์๊ณ ์ฌ์ฉํ์๋ฉด ๋ฉ๋๋ค!
// ResponseEntity๋ก ๋ฐ์ดํฐ์ ์ํ์ฝ๋๋ฅผ ๊ฐ์ด ๋ณด๋ด๋ ๋ฐฉ๋ฒ.
// @PostMapping("/{boardId}")
// public ResponseEntity findById2(@PathVariable Long boardId) {
// BoardDetailDTO boardDetailDTO = bs.findById(boardId);
// return new ResponseEntity<BoardDetailDTO>(boardDetailDTO, HttpStatus.OK);
// ๋ณด๋ด๊ณ ์ ํ๋ ๋ฐ์ดํฐ์ ํ์
์ <> ์์ ์จ์ผํ๋ค. (์๋ต๊ฐ๋ฅํ๊ธดํ์ง๋ง ์ฐ๋๊ฒ ์ข์)
// ์์ : new ResponseEntity<๋ณด๋ด๊ณ ์ํ๋ ๋ฐ์ดํฐ ํ์
>(๋ฐ์ดํฐ ๋ณ์์ด๋ฆ, ์ํ์ฝ๋)
// HttpStatus.BAD_REQUEST๋ฅผ ํตํด ์๋ชป ๋ค์ด์จ ์์ฒญ์ ๋ํด ๋ถ๊ธฐ์ฒ๋ฆฌ๋ฅผ ํ ์ ์๋ค.
}
๊ธฐ์กด ํ์๊ด๋ฆฌ์ ๋๊ฐ์ด ๊ฐ๋๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
๋ค๋ฅธ์ ์ด ์๋ค๋ฉด log๋ฅผ ์ฌ์ฉํ๋ ๋ถ๋ถ์ด ๋ณด์ผํ ๋ฐ์, ๊ผญ ํ์ํ๊ฑด ์๋์ง๋ง ์ด๋ฌํ ์ฝ์ ๋ก๊ทธ๊ธฐ๋ก์ ํตํด
์ด๋ค ๋ฉ์๋๊ฐ ์ธ์ ํธ์ถ์ด ๋ฌ๋์ง ๋ ํธํ๊ฒ ๋ณผ ์ ์์ต๋๋ค. ํ๋ฒ์ฉ ์ฌ์ฉํด๋ณด์๋๊ฒ๋ ๋์์ง ์์๊ฒ๋๋ค :D
๊ทธ๋ผ ๋ฐ๋ก html์ ๋ง๋ค๋ฌ ๊ฐ๋ณด์์ฃ !!
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script>
// ajax๋ฅผ ์ฌ์ฉํด๋ณด๊ณ ์ถ์ผ์ ๋ถ๋ค์ ์๋ ์ฃผ์์ฒ๋ฆฌ๋ฅผ ํด์ ํ์๊ณ ์ฐ์๋ฉด ๋ฉ๋๋ค.
// ์์ธํ ์ค๋ช
์ ์๋ตํ๋ ์ง์ ์๋ ์ฝ๋๋ค์ด ๋ฌด์จ ์ญํ ์ ํ๋ ๊ฑด์ง ์์๋ณด์๋๊ฒ๋ ์ข์๊ฑฐ ๊ฐ์ต๋๋ค:D
// const detail = (boardId) => {
// console.log(boardId)
// const reqUrl = "/board/"+boardId
// $.ajax({
// type: "post",
// url: reqUrl,
// dataType: "json",
// success: function (result) {
// console.log(result)
// let output=""
// output += "<table>\n" +
// " <thead>\n" +
// " <tr>\n" +
// " <th>๋ฒํธ</th>\n" +
// " <th>์์ฑ์</th>\n" +
// " <th>์ ๋ชฉ</th>\n" +
// " <th>๋ด์ฉ</th>\n" +
// " <th>์์ฑ์ผ์</th>\n" +
// " </tr>\n" +
// " </thead>\n" +
// " <tbody>\n" +
// " <tr>\n" +
// " <td>" + result.boardId + "</td>\n" +
// " <td>" + result.boardWriter + "</td>\n" +
// " <td>" + result.boardTitle + "</td>\n" +
// " <td>" + result.boardContents + "</td>\n" +
// " <td>" + result.createTime + "</td>\n" +
// " </tr>\n" +
// " </tbody>\n" +
// "</table>"
// document.getElementById("board-detail").innerHTML = output;
// },
// error: function () {
// alert('ajax ์คํจ')
// }
// })
// }
</script>
</head>
<body>
<h2>findAll.html</h2>
<table>
<thead>
<tr>
<th>๋ฒํธ</th>
<th>์์ฑ์</th>
<th>์ ๋ชฉ</th>
<th>์์ฑ์ผ์</th>
<th>์์ ์ผ์</th>
<!-- th>ajax ์์ธ์กฐํ</th> ajax์ฌ์ฉํ์ค ๋ถ์ ์ฃผ์ํด์ ํ์
์ฉ -->
</tr>
</thead>
<tbody>
<tr th:each="board:${boardList}">
<td th:text="${board.boardId}"></td>
<td th:text="${board.boardWriter}"></td>
<!-- ์ด ์ฝ๋๋ก๋ ์ฌ์ฉ ๊ฐ๋ฅ <td><a th:text="${board.boardTitle}" th:href="@{|/board/${board.boardId}|}"></a></td> -->
<td>
<a th:href="@{|/board/${board.boardId}|}">
<span th:text="${board.boardTitle}"></span>
</a>
</td>
<td th:text="${board.createTime}"></td>
<td th:text="${board.updateTime}"></td>
<!-- ์ ๋ชฉ ํด๋ฆญํ๋ฉด ์์ธ์กฐํํ๋ฉด(findById.html) ์ถ๋ ฅ -->
<!-- ajax๋ฅผ ์ด์ฉํ ์์ธ์กฐํ, ์กฐํ ๋ฒํผ์ ๋๋ฅด๋ฉด ๋ชฉ๋ก ์๋์ ํด๋น ๊ธ์ ์์ธ ๋ด์ฉ ์ถ๋ ฅ -->
<!-- <td><button th:onclick="detail([[${board.boardId}]])">์์ธ์กฐํ(ajax)</button></td> -->
<!-- ์ฌ์ฉํ์ค ๋ถ๋ค์ ์ฃผ์์ ํด์ ํด์ฃผ์ธ์:D -->
</tr>
</tbody>
</table>
<!-- ajax๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ผ๋ฉด ์ฃผ์์ ํด์ ํด์ฃผ์ธ์! -->
<!-- <div id="board-detail"></div> -->
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>findById.html</h2>
<table>
<thead>
<tr>
<th>๋ฒํธ</th>
<th>์์ฑ์</th>
<th>์ ๋ชฉ</th>
<th>๋ด์ฉ</th>
<th>์์ฑ์๊ฐ</th>
<th>์์ ์๊ฐ</th>
<th>์์ </th>
</tr>
</thead>
<tbody>
<tr>
<th th:text="${boardDetailDTO.boardId}"></th>
<th th:text="${boardDetailDTO.boardWriter}"></th>
<th th:text="${boardDetailDTO.boardTitle}"></th>
<th th:text="${boardDetailDTO.boardContents}"></th>
<th th:text="${boardDetailDTO.createTime}"></th>
<th th:text="${boardDetailDTO.updateTime}"></th>
<th><a th:href="@{|/board/update/${boardDetailDTO.boardId}|}">์์ ํ์ด์ง</a></th>
</tr>
</tbody>
</table>
</body>
</html>
์ด๋ ๊ฒ ๊ฒ์๊ธ ๋ชฉ๋ก์ถ๋ ฅ์ฉ๊ณผ ์์ธ์กฐํ์ฉ html์ ์ ์ํ์ผ๋ Service์ ์ฝ๋๋ฅผ ๋ง๋ค๋ฌ ๊ฐ๋ด ์๋ค!!
๋ง์ฝ ajax๋ก ํด๋ณด๊ณ ์ถ์ผ์ ๋ถ๋ค์ ์ฃผ์์ฒ๋ฆฌํ ๋ถ๋ถ์ ์ฌ์ฉํ์๋ฉด ๋ฉ๋๋ค.
ajax์ ๋ํด ์๋ก์ด ๋ด์ฉ์ ์ฃผ์์ผ๋ก ์ค๋ช ์ ๋ถ์ฌ๋จ์ผ๋ ๊ฑฑ์ ์์ผ์ ๋ ๋ฉ๋๋ค!!
@Override
public List<BoardDetailDTO> findAll() {
List<BoardEntity> boardEntityList = br.findAll();
List<BoardDetailDTO> boardDetailDTOList = BoardDetailDTO.toBoardDetailDTOList(boardEntityList);
return boardDetailDTOList;
}
@Override
public BoardDetailDTO findById(Long boardId) {
/*
Optional ์ฌ์ฉ
๋จผ์ null ์ฒดํฌ๋ฅผ ํด์ผ ํจ.
Optional ๊ฐ์ฒด ๋ฉ์๋
.isPresent() : ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด true, ์์ผ๋ฉด false ๋ฐํ
.isEmpty() : ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด false, ์์ผ๋ฉด true ๋ฐํ
.get() : Optional ๊ฐ์ฒด์ ๋ค์ด์๋ ์ค์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ๋
*/
Optional<BoardEntity> optionalBoardEntity = br.findById(boardId);
BoardDetailDTO boardDetailDTO = null;
if (optionalBoardEntity.isPresent()) {
BoardEntity boardEntity = optionalBoardEntity.get();
boardDetailDTO = BoardDetailDTO.toBoardDetailDTO(boardEntity);
}
return boardDetailDTO;
}
์ด๋ฒ์๋ Optional๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ดค์ต๋๋ค.
Boot์์๋ DB์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ๋ null์ด๋ null์ด ์๋๋ ๋ฌด์กฐ๊ฑด Optional๊ฐ์ฒด์ ๋ด์์ ๋ณด๋ด๊ฒ ๋ฉ๋๋ค.
(findAll๊ฐ์ด ๋ฐ์ดํฐ ์ ์ฒด๋ฅผ ๊ฐ์ ธ์ค๋๊ฒ ์๋, findById๊ฐ์ ์ฟผ๋ฆฌ์์)
์ ๋ฒ์๋ ๋ฐ๋ก .get()์ผ๋ก ์์ ๊ฐ์ ๊บผ๋ด ์ฌ์ฉํ์ง๋ง ์ด๋ฒ์๋ ๋จผ์ null์ฒดํฌ ํ ๊ฐ์ ๊ฐ์ ธ๊ฐ๊ฒ๋ ๋ง๋ค์์ต๋๋ค.
๋ง์ฝ ๋ ์ถ๊ฐ๋๋ ๋ด์ฉ์ด ์๋ค๋ฉด ๋์ค์ ์์ธํ ๋ค๋ค๋ณด๋๋ก ํ์ฃ !! :D
์ด๋ ๊ฒ ๊ฒ์๊ธ ์ ์ฅ๋ถํฐ ๊ฒ์๊ธ ๋ชฉ๋ก ์ถ๋ ฅ, ์์ธ ์กฐํ๊น์ง ์์๋ณด์์ต๋๋ค.
์์ง๊น์ง๋ ํ์๊ด๋ฆฌ ์์ ์ ๊ฒน์น๋ ๋ถ๋ถ์ด ๋ง์ ์ด์ ๊ฒ์๊ธ๋ค์ ๋ฐ๋ผํด๋ณด์ ๋ถ๋ค์ด๋ผ๋ฉด
๋ณ ๋ฌด๋ฆฌ์์ด ์ ํ์ จ์๊ฒ๋๋ค :D
๋ค์์๊ฐ์๋ ์์ ๊ณผ ๊ทธ ์ธ ๋ค๋ฅธ๊ฑฐ์ ๋ํด ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
๊ทธ๋ผ ๋ค๋ค ๋ค์์ ๊ฑด๊ฐํ ๋ชจ์ต์ผ๋ก ๋ง๋์~!! :D