BoardRequestDto.java | 게시판 요청 데이터를 담당 |
BoardResponseDto.java | 게시판 응답 데이터를 담당 |
BaseTimeEntity.java | 반복되는 날짜 데이터의 공통 처리를 담당 |
Board.java | board 테이블의 @Entity |
BoardRepository.java | JpaRepository의 구현체 |
BoardService.java | 게시판 @Service |
@Entity | 실제 DB의 테이블과 매칭될 Class임을 명시한다 |
@MappedSuperclass | 이 클래스를 상속하는 엔티티에 매핑되는 테이블을 생성한다. |
@EntityListeners(AuditingEntityListener.class) | Jpa 내부에서 엔티티 객체가 생성/변경되는 것을 감지하는 역할을 한다. |
@CreateDate | Jpa 에서 엔티티의 생성 시간을 처리한다. |
@LastModifiedDate | 최종 수정 시간을 자동으로 처리한다. |
@GeneratedValue(strategy =GenerationType.IDENTITY) | PK의 생성 규칙을 나타낸다. |
@Builder | 어느 필드에 어떤 값을 채워야 할지 명확하게 정하여 생성 시점에 값을 채워준다. |
@Transactional | 선언적 트랜잭션을 사용한다. |
@Modifying | @Query Annotation으로 작성 된 변경, 삭제 쿼리를 사용할 때 사용한다. |
@Query | SQL을 JPQL로 작성할 수 있고, nativeQuery=true 옵션으로 네이티브 쿼리도 사용 가능하게 한다. |
entity.board
Entity를 정의한다.
테이블의 모든 필드와 Builder생성자를 구현한다.
package com.board.study.entity;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Entity
public class Board extends BaseTimeEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String content;
private int readCnt;
private String registerId;
@Builder
public Board(Long id, String title, String content, int readCnt, String registerId) {
this.id = id;
this.title = title;
this.content = content;
this.readCnt = readCnt;
this.registerId = registerId;
}
}
BaseTimeEntity
Entity에서 공통적으로 사용될 날짜 필드를 관리할 클래스를 정의한다.
꼭 날짜가 아니더라도 공통적으로 반복되는 필드를 정의하여 사용해도 된다.
package com.board.study.entity;
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.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseTimeEntity {
@CreatedDate
private LocalDateTime registerTime;
@LastModifiedDate
private LocalDateTime updateTime;
}
BoardRequestDto
dto.board
게시물 등록, 수정, 상세 조회에 필요한 필드를 정의한다.
toEntity() 메서드는 Board Entity를 builder 하여 사용한다.
package com.board.study.dto.board;
import com.board.study.entity.Board;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class BoardRequestDto {
private Long id;
private String title;
private String content;
private String registerId;
public Board toEntity() {
return Board.builder()
.title(title)
.content(content)
.registerId(registerId)
.build();
}
}
BoardResponseDto
게시물 목록, 상세 조회에 필요한 필드를 정의한다.
Board Entity를 BoardResponseDto에 맞게 변환하는 생성자를 생성한다.
package com.board.study.dto.board;
import com.board.study.entity.Board;
import lombok.Getter;
import java.time.LocalDateTime;
@Getter
public class BoardResponseDto {
private Long id;
private String title;
private String content;
private int readCnt;
private String registerId;
private LocalDateTime registerTime;
public BoardResponseDto(Board entity) {
this.id = entity.getId();
this.title = entity.getTitle();
this.content = entity.getContent();
this.readCnt = entity.getReadCnt();
this.registerId = entity.getRegisterId();
this.registerTime = entity.getRegisterTime();
}
@Override
public String toString() {
return "BoardListDto [id=" + id + ", title=" + title + ", content=" + content + ", readCnt" + readCnt +
", registerId=" + registerId + ", registerTime=" + registerTime + "]";
}
}
BoardRepository
JpaRepository를 상속받아 CRUD의 기능을 담당하는 인터페이스를 생성한다.
그리고 @Query을 사용한 JPQL 방식의 updateBoard() 메서드도 구현해 본다.
package com.board.study.repository;
import com.board.study.dto.board.BoardRequestDto;
import com.board.study.entity.Board;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
public interface BoardRepository extends JpaRepository<Board, Long> {
String UPDATE_BOARD = "UPDATE Board " +
"SET TITLE = :#{#boardRequestDto.title}, " +
"CONTENT = :#{#boardRequestDto.content}, " +
"UPDATE_TIME = NEW() " +
"WHERE ID = :#{#boardRequestDto.id}";
@Transactional
@Modifying
@Query(value = UPDATE_BOARD, nativeQuery = true)
public int updateBoard(@Param("boardRequestDto") BoardRequestDto boardRequestDto);
}
BoardService
게시판 기능을 담당할 Service 클래스로 나중에 파일 및 페이징 처리를 추가할 예정이다.
지금은 간단한 CRUD 메서드만 작성한다.
package com.board.study.service;
import com.board.study.dto.board.BoardRequestDto;
import com.board.study.dto.board.BoardResponseDto;
import com.board.study.repository.BoardRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.stream.Collectors;
@RequiredArgsConstructor
@Service
public class BoardService {
private final BoardRepository boardRepository;
@Transactional
public Long save(BoardRequestDto boardRequestDto) {
return boardRepository.save(boardRequestDto.toEntity()).getId();
}
@Transactional(readOnly = true)
public List<BoardResponseDto> findAll() {
return boardRepository.findAll().stream().map(BoardResponseDto::new).collect(Collectors.toList());
}
public BoardResponseDto findById(Long id) {
return new BoardResponseDto(boardRepository.findById(id).get());
}
public int updateBoard(BoardRequestDto boardRequestDto) {
return boardRepository.updateBoard(boardRequestDto);
}
public void deleteById(Long id) {
boardRepository.deleteById(id);
}
}
StudyApplication
Application 클래스에 @EnableJpaAuditing을 추가해 Auditing기능을 활성화 한다.
package com.board.study;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@EnableJpaAuditing
@SpringBootApplication
public class StudyApplication {
public static void main(String[] args) {
SpringApplication.run(StudyApplication.class, args);
}
}
테이블 생성
CREATE TABLE IF NOT EXISTS `board` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'PK',
`title` varchar(200) NOT NULL COMMENT '제목',
`content` text NOT NULL COMMENT '내용',
`read_cnt` int NOT NULL DEFAULT '0' COMMENT '조회수',
`register_id` varchar(100) NOT NULL COMMENT '작성자',
`register_time` datetime DEFAULT NULL COMMENT '작성일',
`update_time` datetime DEFAULT NULL COMMENT '수정일',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='게시판'
데이터베이스 설정(application.properties)
spring.profiles.active=local
# MySQL
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# DB Source URL
# ex) spring.datasource.url=jdbc:mysql://localhost:3306/test_db?useSSL=false&useUnicode=true&serverTimezone=Asia/Seoul
spring.datasource.url=jdbc:mysql://localhost:3303/Board?useSSL=false&useUnicode=true&serverTimezone=Asia/Seoul
# DB username
# ex) spring.datasource.username=root
spring.datasource.username=root
# DB password
# ex) spring.datasource.password=root
spring.datasource.password=0024
# 처리 시 발생하는 SQL 을 보여줄 것인지 결정
#spring.jpa.show-sql=true
# 프로젝트 실행 시 자동으로 DDL(create, alter, drop) 을 생성할 것인지 결정하는 설정
# create : 매번 테이블 생성을 새로 시도한다.
# update : 변경이 필요한 경우 alter 로 변경되고 테이블이 없는 경우 create 가 된다.
spring.jpa.hibernate.ddl-auto=update
# 실제 JPA 구현체인 Hibernate 가 동작하면서 발생하는 SQL 을 포맷팅해서 출력한다. 실행되는 SQL 의 가독성을 높여준다.
spring.jpa.properties.hibernate.format_sql=true
#JPA
loglogging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
'프로젝트 > 게시판' 카테고리의 다른 글
V2 - 게시판 만들기(초기 설정)#1 (0) | 2022.09.05 |
---|---|
V1 - 수정, 삭제 구현하기 (0) | 2022.09.05 |
V1 - 등록, 상세, 리스트 페이지 구현하기 (0) | 2022.09.03 |
V1 - 테스트 코드 작성 (0) | 2022.08.27 |
V1 - Spring Boot 게시판 만들기 설정 (0) | 2022.08.25 |