Spring Boot + JPA + Mysql 게시판 (1) 게시글 등록_수정본
나는 게시글 등록하는 부분을 하기로했다.
프로젝트 규모 초기 설정을 너무 크게잡아서 모두가 하기 어렵고
불편한 사항이 있을가봐 규모를 축소하고 소규모로 하기로 했다.
게시글등록에 관해 작성.
1.컨트롤러
package com.teamproject.checkin.board;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.List;
@Controller
@RequiredArgsConstructor
public class BoardController {
//@Autowired RequiredArgsConstructor
//final이 붙거나 @NotNull 이 붙은 필드의 생성자를 자동 생성해주는 롬복 어노테이션
final BoardService boardService;
//기본부트스트랩
@GetMapping("/freeBoard")
public String FRboardList(Model model){
return "/board/freeBoard";
}
@GetMapping("/FRWrite")
public String FRWrite(Model model){
return "/board/FRWrite";
}
@PostMapping("/boardReg")
public String boardReg(BoardDto boardDto){
boardService.boardReg(boardDto);
return "redirect:/freeBoard";
}
@GetMapping("/FRDetail")
public String FRDetail(Model model){
return "/board/FRDetail";
}
@GetMapping("/FREdit")
public String FREdit(Model model){
return "/board/FREdit";
}
}
FRboardList : 게시글리스트 (Get)
FRWrite : 게시글 작성화면 (Get)
boardReg : 게시글 입력기능(Post)
FRDetail : 상세조회
FREdit : 수정
2.Board (Entity)
package com.teamproject.checkin.board;
import com.teamproject.checkin.commEntity.TimeEntity;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
//@IdClass(BoarderPK.class)
public class Board extends TimeEntity {
/* @Id //@Pk
private String corpCode;
@Id
private String partCode;*/
// @Id
private String boardType;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)//자동으로 PK 값 입력이 됨 테스트 필요
private Long boardNo;
private String boardTitle;
private String boardContent;
// public Board() { }
public Board(Long boardNo, String boardType, String boardTitle, String boardContent){
this.boardNo = boardNo;
this.boardType = boardType;
this.boardTitle = boardTitle;
this.boardContent = boardContent;
}
public static Board of (Long boardNo, String boardType, String boardTitle, String boardContent)
{
return new Board(boardNo, boardType, boardTitle,boardContent);
}
}
!!Board of 중요!! JPA를 사용하기 위해 Entity를 리턴해주는 것으로 추측된다.
하단에 내용 설명하도록 하겠습니다.
그리고 등록, 수정에 관한 정보를 입력하기 위해
public class Board extends TimeEntity
상속처리를 해줬다.
2_2 TimeEntity 추가
공통으로 사용 할 수 있도록 따로 배두었다.
이름은 commEntity로 해두었는데 util이 나을지는 팀원과 상의를 해보려고한다.
package com.teamproject.checkin.commEntity;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;
//사용하기 위해 @EnableJpaAuditing 애노테이션 붙이기
@Getter
@MappedSuperclass // 테이블로 매핑하지 않고, 자식 Entity에게 매핑정보를 상속하기 위한 애노테이션
@EntityListeners(AuditingEntityListener.class) //JAP에게 해당 Entity는 Auditing 사용한다는 것을 알리는 애노테이션
public class TimeEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime insDate;
@LastModifiedDate
private LocalDateTime updDate;
}
Auditing 사용을 위해 메인 컨트롤러에도 추가를 해준다
@RestController
@SpringBootApplication
@EnableJpaAuditing
public class CheckInApplication {
@RequestMapping("/")
public String home(){
return "hello SpringBoot!";
}
public static void main(String[] args) {
SpringApplication.run(CheckInApplication.class, args);
}
}
@EnableJpaAuditing 추가
3.BoardRepository
public interface BoardRepository extends JpaRepository<Board, Long> {
}
Repository는 데이터 조작을 담당한다. interface로 생성하며, JpaRepository를 extends한다. JpaRepository의 값은 매핑할 entity와 id의 타입이다.(PK로 추측)
4.BoardService
package com.teamproject.checkin.board;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class BoardService {
private final BoardRepository boardRepository;
public Board boardReg(BoardDto dto){
return boardRepository.save(dto.toEntity());
}
}
Service는 위에서 말했듯 실제로 비즈니스 로직을 시행해주는 역할을 한다.
컨트롤러에서 받은 데이터를 저장히기 위해 BoardService의 boardReg를 실행, boardReg를 구현해줘야한다.
boardReg는 Repository를 통해 실제로 데이터를 저장하게 된다. (repository의 save는 JpaRepository -> PagingAndSortingRepository -> CrudRepository 의 인터페이스이다.)
CrudRepository 인터페이스 일부
<S extends T> S save(S entity);
매개변수로 entity를 받는것으로 볼 수 있다.
6.DTO
package com.teamproject.checkin.board;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.time.LocalDateTime;
@Getter
@Setter
@NoArgsConstructor
public class BoardDto {
private Long boardNo;
private String boardType;
private String boardTitle;
private String boardContent;
private LocalDateTime insDate;
private LocalDateTime updDate;
public BoardDto(Long boardNo, String boardType, String boardTitle, String boardContent,LocalDateTime insDate,LocalDateTime updDate) {
this.boardNo = boardNo;
this.boardType = boardType;
this.boardTitle = boardTitle;
this.boardContent = boardContent;
this.insDate = insDate;
this.updDate = updDate;
}
public Board toEntity(){
return Board.of(boardNo, boardType, boardTitle,boardContent);
}
// entity를 dto로 변환
public static BoardDto fromEntity(Board entity){
return new BoardDto(
entity.getBoardNo(),
entity.getBoardType(),
entity.getBoardTitle(),
entity.getBoardContent(),
entity.getInsDate(),
entity.getUpdDate()
);
}
}
마지막으로 DTO.
기본 생성자 생성 및 toEntity매서드를 만들어준다.
Board를 Entity로 변환해 주는 기능을 한다. save() 매서드를 사용하기 위함이다.
Hibernate:
insert
into
board
(ins_date, upd_date, board_content, board_title, board_type)
values
(?, ?, ?, ?, ?)
글 입력시 쿼리가 잘 날아가는것을 볼 수 있다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/layout002}">
<th:block layout:fragment="content002">
<style>
.tbx {
resize: none;
}
</style>
<div class="app-content content">
<div class="content-wrapper">
<div class="content-wrapper-before"></div>
<div class="content-header row">
<div class="content-header-left col-md-4 col-12 mb-2">
<h3 class="content-header-title">자유게시판</h3> <!-- Title 입력 -->
</div>
<div class="content-header-right col-md-8 col-12">
<div class="breadcrumbs-top float-md-right">
<div class="breadcrumb-wrapper mr-1">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/home">Home</a></li> <!-- Home LINK -->
<li class="breadcrumb-item active">자유게시판 > 글쓰기</li> <!-- Title 입력 -->
</ol>
</div>
</div>
</div>
</div>
<div class="content-body">
<section id="chartjs-bar-charts">
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h4 class="card-title">자유게시판 게시글작성</h4> <!-- 부제목 입력 -->
</div>
<div class="card-content collapse show">
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h1 class="card-title"><a href="javascript:history.back()"><span class="pink"><i class="la la-mail-reply"></i>뒤로</span></a></h1>
<a class="heading-elements-toggle"><i class="la la-ellipsis-v font-medium-3"></i></a>
<div class="heading-elements">
<ul class="list-inline mb-0">
<li><a data-action="collapse"><i class="ft-minus"></i></a></li>
</ul>
</div>
</div>
<div class="card-content collapse show">
<div class="card-body">
<form class="form" th:action="@{/boardReg}" method="post">
<div class="form-body">
<input type="hidden" name="boardType" value="B" readonly>
<!-- <input type="hidden" id="date" name="date">-->
<div class="form-group" style="text-align: right;">
<button type="button" class="btn btn-primary mr-1 btn-sm"><i class="la la-paperclip"></i></button>
<button type="button" class="btn btn-danger mr-1 btn-sm"><i class="la la-file-image-o"></i></button>
</div>
<div class="form-group">
<input type="text" id="writer" class="form-control" placeholder="작성자" name="writer" readonly="readonly" value="작성자">
</div>
<div class="form-group">
<input type="text" id="boardTitle" class="form-control" placeholder="제목을 입력하세요..." name="boardTitle">
</div>
<div class="form-group">
<textarea id="boardContent" name="boardContent" rows="20" class="form-control tbx" placeholder="내용을 입력하세요..." ></textarea>
</div>
</div>
<div class="form-actions center">
<button type="submit" class="btn btn-outline-primary">새글등록</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
</div>
</div>
</th:block>
<script>
</script>
</html>
현 게시판은 공부중에 작성하는 것으로 많이 미흡한 부분이 있을 수 있습니다.
추가내용에 대해서는 추후 추가로 작성하거나 수정하도록하겠습니다.
피드백을 주신다면 감사히 받겠습니다
(현재 시간이나 작성자 , 게시판타입 등등은 안받거나 하드코딩 입니다)
테이블에 등록자 컬럼도 없네요.. 추후 추가를..ㄷㄷ..ㅠㅠ