ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 게시판 만들기 📋 데이터베이스(MariaDB) 연동 및 JPA 입력, 조회, 수정, 삭제 구현
    Spring Boot/게시판 만들기 2022. 6. 18. 00:26

    이전 글) 스프링 부트 프로젝트 생성하기

     

    스프링 부트 프로젝트 생성하기

    이전 글) 인텔리제이 설치하기 인텔리제이 설치하기 인텔리제이 다운로드 인텔리제이 공식 홈페이지에서 운영체제에 맞는 Community 버전을 다운로드합니다. Ultimate와 Community 버전의 차이 제일

    hnev.tistory.com

    [개발환경] - 인텔리제이 설치하기

    [개발환경] - 윈도우 MariaDB 설치 및 접속하기

     


    🌈 데이터베이스(MariaDB) 연동 및 JPA 입력, 조회, 수정, 삭제 구현

    📌 개발환경

    IntelliJ Community, SpringBoot, Java 1.8, Gradle, Jar, Thymeleaf, JPA, MariaDB

     

    테이블 생성

    데이터베이스 연동 및 CRUD 구현하기에 앞서 테이블(board)을 먼저 생성합니다.

    📁 SQL Download

    toy.sql
    0.00MB

     

    Dependency 추가

    build.gradle

    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
    annotationProcessor 'org.projectlombok:lombok'

    Gradle 적용

    build.gradle에서 Load Gradle Chagnes (Ctrl  + Shift + O)

    또는 우측 Gradle 탭에서 Reload All Gradle Projects

     

    lombok Enabled

    Settings  →  Plugins에서 lombok을 검색한 뒤 Enabled 되어있는지 확인합니다.

     

    데이터베이스 설정

    application.properties

    spring.datasource.driverClassName=org.mariadb.jdbc.Driver
    spring.datasource.url=jdbc:mariadb://localhost:3306/toy
    spring.datasource.username=계정
    spring.datasource.password=비밀번호

    properties를 사용해도 되지만 개인적으로 중복되는 부분과 가독성을 위해서 yml를 사용하겠습니다. 변경하는 방법은 확장자를 yml로 바꿔주기만 하면 됩니다.

    application.yml

    spring:
      datasource:
        driverClassName: org.mariadb.jdbc.Driver
        url: jdbc:mariadb://localhost:3306/toy
        username: 계정
        password: 비밀번호

     

    서비스 구현

    BaseTimeEntity.java

    반복 사용되는 컬럼을 공통으로 정의합니다.

     📌 어노테이션 설명

    @Getter
    ↪  Getter 메서드를 생성
    @MappedSuperclass
    ↪  해당 클래스를 상속받는 자식 클래스에게 매핑 정보만 제공
    @EntityListeners(AuditingEntityListener.class)
    ↪  해당 클래스에 Auditing 기능을 포함
    @CreateDate
    ↪  Entity가 생성되어 저장될 때 시간이 자동 저장
    @LastModifedDate
    ↪  조회한 Entity의 값을 변경할 때 시간이 자동 저장

    @Getter
    @MappedSuperclass
    @EntityListeners(AuditingEntityListener.class)
    public class BaseTimeEntity {
        @CreatedDate
        private LocalDateTime registerTime;
        @LastModifiedDate
        private LocalDateTime modifyTime;
    }

     

    Board.java

    Entity 정의와 요청, 응답 멤버 클래스를 작성합니다.

    @NoargsConstructor
    ↪  파라미터가 없는 생성자 생성
    @Entity
    ↪  테이블과 매칭 될 Class 명시
    @GeneratedValue
    ↪  PK 생성 규칙 명시

    @Id
    ↪  PK 필드를 명시

    @Builder
    ↪  빌더 패턴을 생성
    @Getter
    ↪  Getter 메서드를 생성
    @Setter
    ↪  Setter 메서드를 생성

    @NoArgsConstructor
    @Getter
    @Entity(name = "board")
    public class Board extends BaseTimeEntity {
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Id
        private Long id;
        private String title;
        private String contents;
        private String useYn;
        private Long registerId;
        private Long modifyId;
    
        @Builder
        public Board(Long id, String title, String contents, String useYn, Long registerId, Long modifyId) {
            this.id = id;
            this.title = title;
            this.contents = contents;
            this.useYn = useYn;
            this.registerId = registerId;
            this.modifyId = modifyId;
        }
    
        @Getter
        @Setter
        public static class RequestDto {
            private Long id;
            private String title;
            private String contents;
            private String useYn;
            private Long registerId;
            private Long modifyId;
    
            public Board toEntity() {
                return Board.builder()
                        .title(title)
                        .contents(contents)
                        .useYn(useYn)
                        .registerId(registerId)
                        .modifyId(modifyId)
                        .build();
            }
        }
    
        @Getter
        public static class ResponseDto {
        	private Long id;
            private String title;
            private String contents;
            private String useYn;
            private Long registerId;
            private LocalDateTime registerTime;
            private Long modifyId;
            private LocalDateTime modifyTime;
    
            public ResponseDto(Board board) {
                this.id = board.id;
                this.title = board.title;
                this.contents = board.contents;
                this.useYn = board.useYn;
                this.registerId = board.getRegisterId();
                this.registerTime = board.getRegisterTime();
                this.modifyId = board.getModifyId();
                this.modifyTime = board.getRegisterTime();
            }
        }

     

    BoardRepository

    업데이트 쿼리는 @Query를 이용한 JPQL방식으로 정의

    @Transactional
    ↪  선언적 트랜잭션 사용
    @Modifying
    ↪  @Query로 작성된 변경 쿼리를 사용할 때 필요
    @Query
    ↪  SQL을 JPQL로 작성, 네이티브 쿼리 사용 유무 설정 가능

    public interface BoardRepository extends JpaRepository<Board, Long> {
        String updateBoardQuery = "update board " +
                "set title = :#{#requestDto.title}, " +
                "contents = :#{#requestDto.contents}, " +
                "use_yn = :#{#requestDto.useYn}, " +
                "modify_id = :#{#requestDto.modifyId}, " +
                "modify_time = NOW() " +
                "where id = :#{#requestDto.id}";
        @Transactional
        @Modifying
        @Query(value = updateBoardQuery, nativeQuery = true)
        public int updateBoard(@Param("requestDto") Board.RequestDto requestDto);
    }

     

    BoardService.java

    CRUD 메서드를 작성합니다.

    @RequiredArgsConstructor
    @Service
    public class BoardService {
    
        private final BoardRepository boardRepository;
    
        @Transactional
        public Long save(Board.RequestDto requestDto) {
            return boardRepository.save(requestDto.toEntity()).getId();
        }
    
        public List<Board.ResponseDto> findAll() {
            return boardRepository.findAll(Sort.by(Sort.Direction.DESC, "registerTime")).stream().map(Board.ResponseDto::new).collect(Collectors.toList());
        }
        
        public Board.ResponseDto findById(Long id) {
            return new Board.ResponseDto(boardRepository.findById(id).get());
        }
    
        public int updateBoard(Board.RequestDto requestDto) {
            return boardRepository.updateBoard(requestDto);
        }
    
        public void deleteBoard(Board.RequestDto requestDto) {
            boardRepository.deleteById(requestDto.getId());
        }
    }

     

    ToyApplicationTests.java

    test 구조에 있는 클래스로 Junit 테스트에 사용됩니다.

     

    CRUD 테스트

    @Test 어노테이션이 있는 메서드가 실행되는데 업데이트, 조회, 삭제 메서드의 경우 기존에 테스트하려는 데이터가 없기 때문에 주석으로 임시로 막아둔 상태에서 save() 메서드부터 실행합니다.

    인텔리제이 주석/주석해제하는 단축키는 해당 라인 선택 후 Ctrl + / 입니다.

    @SpringBootTest
    class ToyApplicationTests {
    
    	@Autowired
    	private BoardService boardService;
    
    	@Test
    	public void save() {
    		Board.RequestDto requestDto = new Board.RequestDto();
    		requestDto.setTitle("제목");
    		requestDto.setContents("내용");
    		requestDto.setUseYn("Y");
    		requestDto.setRegisterId(117L);
    		requestDto.setModifyId(117L);
            
    		// 2개의 데이터 입력
    		Assertions.assertNotEquals(0, boardService.save(requestDto));
    		Assertions.assertNotEquals(0, boardService.save(requestDto));
    	}
    
    //	@Test
    //	public void findAll() {
    //		Assertions.assertNotEquals(0, boardService.findAll().size());
    //	}
    
    //	@Test
    //	public void updateBoard() {
    //		Board.RequestDto requestDto = new Board.RequestDto();
    //		requestDto.setId(1L);
    //		requestDto.setTitle("제목 업데이트");
    //		requestDto.setContents("내용 업데이트");
    //		requestDto.setModifyId(322L);
    //
    //		Assertions.assertEquals(1, boardService.updateBoard(requestDto));
    //	}
    
    //	@Test
    //	public void deleteBoard() {
    //		Board.RequestDto requestDto = new Board.RequestDto();
    //		requestDto.setId(2L);
    //		boardService.deleteBoard(requestDto);
    //	}
    }

     

    테스트 실행

    ToyApplicationTest에 우 클릭  →  Run ToyApplicationTests

     

    save() 메서드만 실행한 결과 #1

    2개의 데이터가 입력되었는지 데이터베이스 GUI툴을 통해 확인해보겠습니다.
    MariaDB 설치 시 같이 생성되는 HeidiSQL 툴을 사용했습니다.

     

    나머지 수정, 조회, 삭제 메서드의 주석을 해제하고 실행한 결과 #2

    PK가 1인 데이터 수정되고 2인 데이터는 삭제 그리고 PK 3,4 데이터가 입력되어 정상 결과를 확인할 수 있습니다.

     


    Next Step

    📁 Project Download

    toy.zip
    0.22MB

     

    댓글

Designed by Tistory.