From 45211c75d93d6a5648a6638c81fa77e6b66b0b07 Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Mon, 3 Jun 2024 15:31:23 +0900 Subject: [PATCH 01/22] =?UTF-8?q?chore:=20yml=20=EB=82=B4=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=EB=B2=A0=EC=9D=B4=EC=8A=A4=EC=97=90=20?= =?UTF-8?q?=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index ff69a9e..2ae6a82 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,6 +1,6 @@ spring: datasource: - url: jdbc:mysql://localhost:3306/bcsd # 본인의 환경에 맞게 수정한다. + url: jdbc:mysql://localhost:3306/bcsd?serverTimezone=Asia/Seoul # 본인의 환경에 맞게 수정한다. username: root # 본인의 환경에 맞게 수정한다. - password: qwer1234 # 본인의 환경에 맞게 수정한다. + password: jabell0310 # 본인의 환경에 맞게 수정한다. driver-class-name: com.mysql.cj.jdbc.Driver From e1921969f15c68d197aebf24798b4a81dbc21c3b Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Mon, 3 Jun 2024 15:35:54 +0900 Subject: [PATCH 02/22] =?UTF-8?q?chore:=20build.gradle=EC=97=90=20AOP,=20L?= =?UTF-8?q?ombok=20dependencies=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.gradle b/build.gradle index 728ec9c..a4e1ef9 100644 --- a/build.gradle +++ b/build.gradle @@ -16,11 +16,15 @@ repositories { } dependencies { + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-jdbc' runtimeOnly 'com.mysql:mysql-connector-j' testImplementation 'org.springframework.boot:spring-boot-starter-test' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-aop' } tasks.named('test') { From a7c8dc90d9c71b012012b8283565e325a332117f Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Mon, 3 Jun 2024 15:37:56 +0900 Subject: [PATCH 03/22] =?UTF-8?q?refactor:=20Entity=20=EA=B0=9D=EC=B2=B4?= =?UTF-8?q?=EC=97=90=20Lombok=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/demo/domain/Article.java | 41 ++++--------------- .../java/com/example/demo/domain/Board.java | 18 +++----- .../java/com/example/demo/domain/Member.java | 27 ++++-------- 3 files changed, 21 insertions(+), 65 deletions(-) diff --git a/src/main/java/com/example/demo/domain/Article.java b/src/main/java/com/example/demo/domain/Article.java index e0183db..355480d 100644 --- a/src/main/java/com/example/demo/domain/Article.java +++ b/src/main/java/com/example/demo/domain/Article.java @@ -1,7 +1,14 @@ package com.example.demo.domain; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + import java.time.LocalDateTime; +@NoArgsConstructor +@Getter +@Setter public class Article { private Long id; @@ -47,39 +54,5 @@ public void update(Long boardId, String title, String description) { this.modifiedAt = LocalDateTime.now(); } - public void setId(Long id) { - this.id = id; - } - - public void setModifiedAt(LocalDateTime modifiedAt) { - this.modifiedAt = modifiedAt; - } - - public Long getId() { - return id; - } - - public Long getAuthorId() { - return authorId; - } - public Long getBoardId() { - return boardId; - } - - public String getTitle() { - return title; - } - - public String getContent() { - return content; - } - - public LocalDateTime getCreatedAt() { - return createdAt; - } - - public LocalDateTime getModifiedAt() { - return modifiedAt; - } } diff --git a/src/main/java/com/example/demo/domain/Board.java b/src/main/java/com/example/demo/domain/Board.java index 992e2c6..2db0216 100644 --- a/src/main/java/com/example/demo/domain/Board.java +++ b/src/main/java/com/example/demo/domain/Board.java @@ -1,5 +1,11 @@ package com.example.demo.domain; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@NoArgsConstructor +@Getter @Setter public class Board { private Long id; @@ -14,18 +20,6 @@ public Board(String name) { this.name = name; } - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - public void update(String name) { this.name = name; } diff --git a/src/main/java/com/example/demo/domain/Member.java b/src/main/java/com/example/demo/domain/Member.java index fe80d6b..c5ecbdf 100644 --- a/src/main/java/com/example/demo/domain/Member.java +++ b/src/main/java/com/example/demo/domain/Member.java @@ -1,5 +1,13 @@ package com.example.demo.domain; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + + +@NoArgsConstructor +@Getter +@Setter public class Member { private Long id; @@ -25,23 +33,4 @@ public void update(String name, String email) { this.email = email; } - public void setId(Long id) { - this.id = id; - } - - public Long getId() { - return id; - } - - public String getName() { - return name; - } - - public String getEmail() { - return email; - } - - public String getPassword() { - return password; - } } From 33326afc5d783d5d0f216ab4cfd08eadc9918760 Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Mon, 3 Jun 2024 15:40:41 +0900 Subject: [PATCH 04/22] =?UTF-8?q?feat:=20=EC=97=90=EB=9F=AC=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/demo/exception/ErrorResponse.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/main/java/com/example/demo/exception/ErrorResponse.java diff --git a/src/main/java/com/example/demo/exception/ErrorResponse.java b/src/main/java/com/example/demo/exception/ErrorResponse.java new file mode 100644 index 0000000..ded0cf7 --- /dev/null +++ b/src/main/java/com/example/demo/exception/ErrorResponse.java @@ -0,0 +1,19 @@ +package com.example.demo.exception; + +import lombok.Getter; + +import java.time.LocalDateTime; + +@Getter +public class ErrorResponse { + private final LocalDateTime timeStamp = LocalDateTime.now(); + private final int status; + private final String code; + private final String message; + + public ErrorResponse(ErrorCode errorCode) { + this.status = errorCode.getStatus(); + this.code = errorCode.getCode(); + this.message = errorCode.getMessage(); + } +} From 3ce3fc353120eba51f47ad31e3f83ee45979bb6d Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Mon, 3 Jun 2024 15:41:32 +0900 Subject: [PATCH 05/22] =?UTF-8?q?feat:=20=EC=97=90=EB=9F=AC=20=EC=97=B4?= =?UTF-8?q?=EA=B1=B0=ED=98=95=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/demo/exception/ErrorCode.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/main/java/com/example/demo/exception/ErrorCode.java diff --git a/src/main/java/com/example/demo/exception/ErrorCode.java b/src/main/java/com/example/demo/exception/ErrorCode.java new file mode 100644 index 0000000..5ad680b --- /dev/null +++ b/src/main/java/com/example/demo/exception/ErrorCode.java @@ -0,0 +1,30 @@ +package com.example.demo.exception; + +import lombok.Getter; + +@Getter +public enum ErrorCode { + REQUEST_NULL_VALUE(400,"BAD REQUEST", "요청 메시지에 null 값이 존재합니다."), + BOARD_NOT_EXIST(400, "BAD REQUEST", "해당 게시판을 찾을 수 없습니다."), + MEMBER_NOT_EXIST(400, "BAD REQUEST", "해당 사용자를 찾을 수 없습니다."), + + ARTICLE_NOT_EXIST(404,"NOT FOUND", "해당 게시물을 찾을 수 없습니다."), + BOARD_NOT_FOUND(404, "NOT FOUND", "해당 게시판을 찾을 수 없습니다."), + MEMBER_NOT_FOUND(404, "NOT FOUND", "해당 사용자를 찾을 수 없습니다."), + + EMAIL_EXIST(409,"CONFLICT", "해당 이메일이 존재합니다."), + INVALID_MEMBER_OR_BOARD(400, "BAD REQUEST", "존재하지 않는 사용자, 게시판을 참조하고 있습니다."), + + BOARD_ARTICLE_EXIST(400, "BAD REQUEST", "게시판에 작성된 게시물이 존재합니다."), + MEMBER_ARTICLE_EXIST(400, "BAD REQUEST", "사용자가 작성한 게시물이 존재합니다."); + + private final int status; + private final String code; + private final String message; + + ErrorCode(int status, String code, String message) { + this.status = status; + this.code = code; + this.message = message; + } +} From f3a2bfc652c8994cef0d024adc374e757512727d Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Mon, 3 Jun 2024 15:42:31 +0900 Subject: [PATCH 06/22] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98=20=EC=98=88=EC=99=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/demo/exception/AlreadyHasEmailException.java | 8 ++++++++ .../example/demo/exception/ArticleNotFoundException.java | 8 ++++++++ .../example/demo/exception/BoardHasArticleException.java | 8 ++++++++ .../example/demo/exception/BoardNotExistException.java | 8 ++++++++ .../example/demo/exception/BoardNotFoundException.java | 8 ++++++++ .../example/demo/exception/MemberHasArticleException.java | 8 ++++++++ .../example/demo/exception/MemberNotExistException.java | 8 ++++++++ .../example/demo/exception/MemberNotFoundException.java | 8 ++++++++ .../example/demo/exception/RequestNullExistException.java | 8 ++++++++ 9 files changed, 72 insertions(+) create mode 100644 src/main/java/com/example/demo/exception/AlreadyHasEmailException.java create mode 100644 src/main/java/com/example/demo/exception/ArticleNotFoundException.java create mode 100644 src/main/java/com/example/demo/exception/BoardHasArticleException.java create mode 100644 src/main/java/com/example/demo/exception/BoardNotExistException.java create mode 100644 src/main/java/com/example/demo/exception/BoardNotFoundException.java create mode 100644 src/main/java/com/example/demo/exception/MemberHasArticleException.java create mode 100644 src/main/java/com/example/demo/exception/MemberNotExistException.java create mode 100644 src/main/java/com/example/demo/exception/MemberNotFoundException.java create mode 100644 src/main/java/com/example/demo/exception/RequestNullExistException.java diff --git a/src/main/java/com/example/demo/exception/AlreadyHasEmailException.java b/src/main/java/com/example/demo/exception/AlreadyHasEmailException.java new file mode 100644 index 0000000..6b01e5c --- /dev/null +++ b/src/main/java/com/example/demo/exception/AlreadyHasEmailException.java @@ -0,0 +1,8 @@ +package com.example.demo.exception; + +import lombok.NoArgsConstructor; + +@NoArgsConstructor +public class AlreadyHasEmailException extends RuntimeException { + +} diff --git a/src/main/java/com/example/demo/exception/ArticleNotFoundException.java b/src/main/java/com/example/demo/exception/ArticleNotFoundException.java new file mode 100644 index 0000000..2303f33 --- /dev/null +++ b/src/main/java/com/example/demo/exception/ArticleNotFoundException.java @@ -0,0 +1,8 @@ +package com.example.demo.exception; + +import lombok.NoArgsConstructor; + +@NoArgsConstructor +public class ArticleNotFoundException extends RuntimeException { + +} diff --git a/src/main/java/com/example/demo/exception/BoardHasArticleException.java b/src/main/java/com/example/demo/exception/BoardHasArticleException.java new file mode 100644 index 0000000..da50657 --- /dev/null +++ b/src/main/java/com/example/demo/exception/BoardHasArticleException.java @@ -0,0 +1,8 @@ +package com.example.demo.exception; + +import lombok.NoArgsConstructor; + +@NoArgsConstructor +public class BoardHasArticleException extends RuntimeException { + +} diff --git a/src/main/java/com/example/demo/exception/BoardNotExistException.java b/src/main/java/com/example/demo/exception/BoardNotExistException.java new file mode 100644 index 0000000..c5e3119 --- /dev/null +++ b/src/main/java/com/example/demo/exception/BoardNotExistException.java @@ -0,0 +1,8 @@ +package com.example.demo.exception; + +import lombok.NoArgsConstructor; + +@NoArgsConstructor +public class BoardNotExistException extends RuntimeException { + +} diff --git a/src/main/java/com/example/demo/exception/BoardNotFoundException.java b/src/main/java/com/example/demo/exception/BoardNotFoundException.java new file mode 100644 index 0000000..07e0380 --- /dev/null +++ b/src/main/java/com/example/demo/exception/BoardNotFoundException.java @@ -0,0 +1,8 @@ +package com.example.demo.exception; + +import lombok.NoArgsConstructor; + +@NoArgsConstructor +public class BoardNotFoundException extends RuntimeException { + +} diff --git a/src/main/java/com/example/demo/exception/MemberHasArticleException.java b/src/main/java/com/example/demo/exception/MemberHasArticleException.java new file mode 100644 index 0000000..5e51fcd --- /dev/null +++ b/src/main/java/com/example/demo/exception/MemberHasArticleException.java @@ -0,0 +1,8 @@ +package com.example.demo.exception; + +import lombok.NoArgsConstructor; + +@NoArgsConstructor +public class MemberHasArticleException extends RuntimeException { + +} diff --git a/src/main/java/com/example/demo/exception/MemberNotExistException.java b/src/main/java/com/example/demo/exception/MemberNotExistException.java new file mode 100644 index 0000000..f7a4bdc --- /dev/null +++ b/src/main/java/com/example/demo/exception/MemberNotExistException.java @@ -0,0 +1,8 @@ +package com.example.demo.exception; + +import lombok.NoArgsConstructor; + +@NoArgsConstructor +public class MemberNotExistException extends RuntimeException { + +} diff --git a/src/main/java/com/example/demo/exception/MemberNotFoundException.java b/src/main/java/com/example/demo/exception/MemberNotFoundException.java new file mode 100644 index 0000000..daa2843 --- /dev/null +++ b/src/main/java/com/example/demo/exception/MemberNotFoundException.java @@ -0,0 +1,8 @@ +package com.example.demo.exception; + +import lombok.NoArgsConstructor; + +@NoArgsConstructor +public class MemberNotFoundException extends RuntimeException { + +} diff --git a/src/main/java/com/example/demo/exception/RequestNullExistException.java b/src/main/java/com/example/demo/exception/RequestNullExistException.java new file mode 100644 index 0000000..9566e54 --- /dev/null +++ b/src/main/java/com/example/demo/exception/RequestNullExistException.java @@ -0,0 +1,8 @@ +package com.example.demo.exception; + +import lombok.NoArgsConstructor; + +@NoArgsConstructor +public class RequestNullExistException extends RuntimeException{ + +} From 58fb4db34000f5aa685f116dff52419ccd56439e Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Mon, 3 Jun 2024 15:46:51 +0900 Subject: [PATCH 07/22] =?UTF-8?q?feat:=20AOP=EB=A5=BC=20=ED=99=9C=EC=9A=A9?= =?UTF-8?q?=ED=95=9C=20=EC=A0=84=EC=97=AD=20=EC=98=88=EC=99=B8=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/GlobalExceptionHandler.java | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/main/java/com/example/demo/exception/GlobalExceptionHandler.java diff --git a/src/main/java/com/example/demo/exception/GlobalExceptionHandler.java b/src/main/java/com/example/demo/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..a15616b --- /dev/null +++ b/src/main/java/com/example/demo/exception/GlobalExceptionHandler.java @@ -0,0 +1,64 @@ +package com.example.demo.exception; + +import org.springframework.http.HttpStatusCode; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(RequestNullExistException.class) + public ResponseEntity RequestNullExistException() { + ErrorResponse response = new ErrorResponse(ErrorCode.REQUEST_NULL_VALUE); + return new ResponseEntity<>(response, HttpStatusCode.valueOf(400)); + } + + @ExceptionHandler(MemberNotExistException.class) + public ResponseEntity MemberNotExistException() { + ErrorResponse response = new ErrorResponse(ErrorCode.MEMBER_NOT_EXIST); + return new ResponseEntity<>(response, HttpStatusCode.valueOf(400)); + } + + @ExceptionHandler(BoardNotExistException.class) + public ResponseEntity BoardNotExistException() { + ErrorResponse response = new ErrorResponse(ErrorCode.BOARD_NOT_EXIST); + return new ResponseEntity<>(response, HttpStatusCode.valueOf(400)); + } + + @ExceptionHandler(ArticleNotFoundException.class) + public ResponseEntity ArticleNotFoundException() { + ErrorResponse response = new ErrorResponse(ErrorCode.ARTICLE_NOT_EXIST); + return new ResponseEntity<>(response, HttpStatusCode.valueOf(404)); + } + + @ExceptionHandler(MemberNotFoundException.class) + public ResponseEntity MemberNotFoundException() { + ErrorResponse response = new ErrorResponse(ErrorCode.MEMBER_NOT_FOUND); + return new ResponseEntity<>(response, HttpStatusCode.valueOf(404)); + } + + @ExceptionHandler(BoardNotFoundException.class) + public ResponseEntity BoardNotFoundException() { + ErrorResponse response = new ErrorResponse(ErrorCode.BOARD_NOT_FOUND); + return new ResponseEntity<>(response, HttpStatusCode.valueOf(404)); + } + + @ExceptionHandler(AlreadyHasEmailException.class) + public ResponseEntity AlreadyHasEmailException() { + ErrorResponse response = new ErrorResponse(ErrorCode.EMAIL_EXIST); + return new ResponseEntity<>(response, HttpStatusCode.valueOf(409)); + } + + @ExceptionHandler(MemberHasArticleException.class) + public ResponseEntity MemberHasArticleException() { + ErrorResponse response = new ErrorResponse(ErrorCode.MEMBER_ARTICLE_EXIST); + return new ResponseEntity<>(response, HttpStatusCode.valueOf(400)); + } + + @ExceptionHandler(BoardHasArticleException.class) + public ResponseEntity BoardHasArticleException() { + ErrorResponse response = new ErrorResponse(ErrorCode.BOARD_ARTICLE_EXIST); + return new ResponseEntity<>(response, HttpStatusCode.valueOf(400)); + } +} From d7e977c1bb781ec442ba723536a019a5fa48cc6e Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Mon, 3 Jun 2024 15:47:50 +0900 Subject: [PATCH 08/22] =?UTF-8?q?feat:=20authorId=20=ED=95=84=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../demo/controller/dto/request/ArticleUpdateRequest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/example/demo/controller/dto/request/ArticleUpdateRequest.java b/src/main/java/com/example/demo/controller/dto/request/ArticleUpdateRequest.java index aced461..1177957 100644 --- a/src/main/java/com/example/demo/controller/dto/request/ArticleUpdateRequest.java +++ b/src/main/java/com/example/demo/controller/dto/request/ArticleUpdateRequest.java @@ -1,6 +1,7 @@ package com.example.demo.controller.dto.request; public record ArticleUpdateRequest( + Long authorId, Long boardId, String title, String description From 0b8bab06b84066a60eb136fb426e8caba1f74ec6 Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Mon, 3 Jun 2024 15:50:12 +0900 Subject: [PATCH 09/22] =?UTF-8?q?feat:=20getById()=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=8B=A4=ED=8C=A8=EB=A1=9C=20=EB=B0=9C?= =?UTF-8?q?=EC=83=9D=ED=95=98=EB=8A=94=20=EC=98=88=EC=99=B8=EB=A5=BC=20nul?= =?UTF-8?q?l=20=EA=B0=92=EC=9C=BC=EB=A1=9C=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/demo/repository/ArticleRepositoryJdbc.java | 7 ++++++- .../com/example/demo/repository/BoardRepositoryJdbc.java | 7 ++++++- .../com/example/demo/repository/MemberRepositoryJdbc.java | 7 ++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/example/demo/repository/ArticleRepositoryJdbc.java b/src/main/java/com/example/demo/repository/ArticleRepositoryJdbc.java index c9a272e..47bfedf 100644 --- a/src/main/java/com/example/demo/repository/ArticleRepositoryJdbc.java +++ b/src/main/java/com/example/demo/repository/ArticleRepositoryJdbc.java @@ -3,6 +3,7 @@ import java.sql.PreparedStatement; import java.util.List; +import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.support.GeneratedKeyHolder; @@ -58,11 +59,15 @@ public List
findAllByMemberId(Long memberId) { @Override public Article findById(Long id) { - return jdbcTemplate.queryForObject(""" + try { + return jdbcTemplate.queryForObject(""" SELECT id, board_id, author_id, title, content, created_date, modified_date FROM article WHERE id = ? """, articleRowMapper, id); + } catch (EmptyResultDataAccessException e) { + return null; + } } @Override diff --git a/src/main/java/com/example/demo/repository/BoardRepositoryJdbc.java b/src/main/java/com/example/demo/repository/BoardRepositoryJdbc.java index c4fd6f6..d932791 100644 --- a/src/main/java/com/example/demo/repository/BoardRepositoryJdbc.java +++ b/src/main/java/com/example/demo/repository/BoardRepositoryJdbc.java @@ -3,6 +3,7 @@ import java.sql.PreparedStatement; import java.util.List; +import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.support.GeneratedKeyHolder; @@ -35,11 +36,15 @@ public List findAll() { @Override public Board findById(Long id) { - return jdbcTemplate.queryForObject(""" + try { + return jdbcTemplate.queryForObject(""" SELECT id, name FROM board WHERE id = ? """, boardRowMapper, id); + } catch (EmptyResultDataAccessException e) { + return null; + } } @Override diff --git a/src/main/java/com/example/demo/repository/MemberRepositoryJdbc.java b/src/main/java/com/example/demo/repository/MemberRepositoryJdbc.java index 30d2262..8e432a6 100644 --- a/src/main/java/com/example/demo/repository/MemberRepositoryJdbc.java +++ b/src/main/java/com/example/demo/repository/MemberRepositoryJdbc.java @@ -3,6 +3,7 @@ import java.sql.PreparedStatement; import java.util.List; +import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.support.GeneratedKeyHolder; @@ -37,11 +38,15 @@ public List findAll() { @Override public Member findById(Long id) { - return jdbcTemplate.queryForObject(""" + try { + return jdbcTemplate.queryForObject(""" SELECT id, name, email, password FROM member WHERE id = ? """, memberRowMapper, id); + } catch (EmptyResultDataAccessException e) { + return null; + } } @Override From c8d1a4eeb5e64aa19e9fcdb867ce662bf6425163 Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Mon, 3 Jun 2024 16:02:32 +0900 Subject: [PATCH 10/22] =?UTF-8?q?feat:=20=EB=B9=84=EC=A6=88=EB=8B=88?= =?UTF-8?q?=EC=8A=A4=20=EB=A1=9C=EC=A7=81=EC=97=90=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=EC=9E=90=20=EC=98=88=EC=99=B8=20=EB=B0=9C=EC=83=9D=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/demo/service/ArticleService.java | 55 +++++++++++++++++-- .../example/demo/service/BoardService.java | 33 ++++++++++- .../example/demo/service/MemberService.java | 35 +++++++++++- 3 files changed, 116 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/example/demo/service/ArticleService.java b/src/main/java/com/example/demo/service/ArticleService.java index 7f8610b..d0c1b9d 100644 --- a/src/main/java/com/example/demo/service/ArticleService.java +++ b/src/main/java/com/example/demo/service/ArticleService.java @@ -2,6 +2,10 @@ import java.util.List; +import com.example.demo.exception.ArticleNotFoundException; +import com.example.demo.exception.BoardNotExistException; +import com.example.demo.exception.MemberNotExistException; +import com.example.demo.exception.RequestNullExistException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -35,8 +39,23 @@ public ArticleService( public ArticleResponse getById(Long id) { Article article = articleRepository.findById(id); + + if (article == null) { + throw new ArticleNotFoundException(); + } + Member member = memberRepository.findById(article.getAuthorId()); + + if (member == null) { + throw new MemberNotExistException(); + } + Board board = boardRepository.findById(article.getBoardId()); + + if(board == null) { + throw new BoardNotExistException(); + } + return ArticleResponse.of(article, member, board); } @@ -59,19 +78,45 @@ public ArticleResponse create(ArticleCreateRequest request) { request.title(), request.description() ); + + if (request.boardId() == null || request.authorId() == null || request.title() == null || request.description() == null) { + throw new RequestNullExistException(); + } + + Member member = memberRepository.findById(request.authorId()); + + if (member == null) { + throw new MemberNotExistException(); + } + + Board board = boardRepository.findById(request.boardId()); + + if(board == null) { + throw new BoardNotExistException(); + } + Article saved = articleRepository.insert(article); - Member member = memberRepository.findById(saved.getAuthorId()); - Board board = boardRepository.findById(saved.getBoardId()); + return ArticleResponse.of(saved, member, board); } @Transactional public ArticleResponse update(Long id, ArticleUpdateRequest request) { Article article = articleRepository.findById(id); + + Member member = memberRepository.findById(request.authorId()); + + if (member == null) { + throw new MemberNotExistException(); + } + + Board board = boardRepository.findById(request.boardId()); + + if(board == null) { + throw new BoardNotExistException(); + } + article.update(request.boardId(), request.title(), request.description()); - Article updated = articleRepository.update(article); - Member member = memberRepository.findById(updated.getAuthorId()); - Board board = boardRepository.findById(article.getBoardId()); return ArticleResponse.of(article, member, board); } diff --git a/src/main/java/com/example/demo/service/BoardService.java b/src/main/java/com/example/demo/service/BoardService.java index ffff891..f6e47a8 100644 --- a/src/main/java/com/example/demo/service/BoardService.java +++ b/src/main/java/com/example/demo/service/BoardService.java @@ -1,7 +1,14 @@ package com.example.demo.service; import java.util.List; +import java.util.Objects; +import com.example.demo.domain.Article; +import com.example.demo.exception.BoardHasArticleException; +import com.example.demo.exception.BoardNotExistException; +import com.example.demo.exception.BoardNotFoundException; +import com.example.demo.exception.RequestNullExistException; +import com.example.demo.repository.ArticleRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -15,9 +22,11 @@ @Transactional(readOnly = true) public class BoardService { + private final ArticleRepository articleRepository; private final BoardRepository boardRepository; - public BoardService(BoardRepository boardRepository) { + public BoardService(ArticleRepository articleRepository, BoardRepository boardRepository) { + this.articleRepository = articleRepository; this.boardRepository = boardRepository; } @@ -29,24 +38,46 @@ public List getBoards() { public BoardResponse getBoardById(Long id) { Board board = boardRepository.findById(id); + + if(board == null) { + throw new BoardNotFoundException(); + } + return BoardResponse.from(board); } @Transactional public BoardResponse createBoard(BoardCreateRequest request) { Board board = new Board(request.name()); + + if(board.getName() == null) { + throw new RequestNullExistException(); + } + Board saved = boardRepository.insert(board); return BoardResponse.from(saved); } @Transactional public void deleteBoard(Long id) { + List
allArticles = articleRepository.findAll(); + boolean boardHasArticles = allArticles.stream() + .anyMatch(article -> Objects.equals(article.getAuthorId(), id)); + + if (boardHasArticles) { + throw new BoardHasArticleException(); + } boardRepository.deleteById(id); } @Transactional public BoardResponse update(Long id, BoardUpdateRequest request) { Board board = boardRepository.findById(id); + + if (board == null) { + throw new BoardNotExistException(); + } + board.update(request.name()); Board updated = boardRepository.update(board); return BoardResponse.from(updated); diff --git a/src/main/java/com/example/demo/service/MemberService.java b/src/main/java/com/example/demo/service/MemberService.java index 04c1bc8..86442cd 100644 --- a/src/main/java/com/example/demo/service/MemberService.java +++ b/src/main/java/com/example/demo/service/MemberService.java @@ -1,7 +1,11 @@ package com.example.demo.service; import java.util.List; +import java.util.Objects; +import com.example.demo.domain.Article; +import com.example.demo.exception.*; +import com.example.demo.repository.ArticleRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -15,14 +19,20 @@ @Transactional(readOnly = true) public class MemberService { + private final ArticleRepository articleRepository; private final MemberRepository memberRepository; - public MemberService(MemberRepository memberRepository) { + public MemberService(ArticleRepository articleRepository, MemberRepository memberRepository) { + this.articleRepository = articleRepository; this.memberRepository = memberRepository; } public MemberResponse getById(Long id) { Member member = memberRepository.findById(id); + + if (member == null) { + throw new MemberNotFoundException(); + } return MemberResponse.from(member); } @@ -38,17 +48,40 @@ public MemberResponse create(MemberCreateRequest request) { Member member = memberRepository.insert( new Member(request.name(), request.email(), request.password()) ); + + if (member.getName() == null || member.getEmail() == null || member.getPassword() == null) { + throw new RequestNullExistException(); + } return MemberResponse.from(member); } @Transactional public void delete(Long id) { + List
allArticles = articleRepository.findAll(); + boolean memberHasArticles = allArticles.stream() + .anyMatch(article -> Objects.equals(article.getAuthorId(), id)); + + if (memberHasArticles) { + throw new MemberHasArticleException(); + } memberRepository.deleteById(id); } @Transactional public MemberResponse update(Long id, MemberUpdateRequest request) { Member member = memberRepository.findById(id); + + if (member == null) { + throw new MemberNotExistException(); + } + + boolean emailExists = memberRepository.findAll().stream() + .anyMatch(m -> member.getEmail().equals(m.getEmail())); + + if (emailExists) { + throw new AlreadyHasEmailException(); + } + member.update(request.name(), request.email()); memberRepository.update(member); return MemberResponse.from(member); From 733ebccf1624a547dffd3e4a6fb308aac436ff9b Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Sun, 23 Jun 2024 10:14:41 +0900 Subject: [PATCH 11/22] =?UTF-8?q?fix:=20gitignore=EC=97=90=20application.y?= =?UTF-8?q?ml=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c2065bc..0d1258f 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ bin/ out/ !**/src/main/**/out/ !**/src/test/**/out/ +src/main/resources/application.yml ### NetBeans ### /nbproject/private/ From e1eb6e7e6fb7acf63af852d5cd1cd93ff77cd1d3 Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Sun, 23 Jun 2024 10:20:33 +0900 Subject: [PATCH 12/22] =?UTF-8?q?fix:=20status=EC=99=80=20code=EC=9D=98=20?= =?UTF-8?q?=EC=9E=90=EB=A3=8C=ED=98=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/demo/exception/ErrorCode.java | 6 +++--- src/main/java/com/example/demo/exception/ErrorResponse.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/example/demo/exception/ErrorCode.java b/src/main/java/com/example/demo/exception/ErrorCode.java index 5ad680b..411ae12 100644 --- a/src/main/java/com/example/demo/exception/ErrorCode.java +++ b/src/main/java/com/example/demo/exception/ErrorCode.java @@ -18,11 +18,11 @@ public enum ErrorCode { BOARD_ARTICLE_EXIST(400, "BAD REQUEST", "게시판에 작성된 게시물이 존재합니다."), MEMBER_ARTICLE_EXIST(400, "BAD REQUEST", "사용자가 작성한 게시물이 존재합니다."); - private final int status; - private final String code; + private final int code; + private final String status; private final String message; - ErrorCode(int status, String code, String message) { + ErrorCode(int code, String status, String message) { this.status = status; this.code = code; this.message = message; diff --git a/src/main/java/com/example/demo/exception/ErrorResponse.java b/src/main/java/com/example/demo/exception/ErrorResponse.java index ded0cf7..1d8250a 100644 --- a/src/main/java/com/example/demo/exception/ErrorResponse.java +++ b/src/main/java/com/example/demo/exception/ErrorResponse.java @@ -7,8 +7,8 @@ @Getter public class ErrorResponse { private final LocalDateTime timeStamp = LocalDateTime.now(); - private final int status; - private final String code; + private final int code; + private final String status; private final String message; public ErrorResponse(ErrorCode errorCode) { From cfb4ea0ee16c0c2becb3f293d20be05714fa3bf8 Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Tue, 25 Jun 2024 11:46:08 +0900 Subject: [PATCH 13/22] =?UTF-8?q?fix:=20=EC=A0=84=EC=97=AD=EC=98=88?= =?UTF-8?q?=EC=99=B8=EC=B2=98=EB=A6=AC=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=9E=90=EB=B0=94=20=EC=BB=A8=EB=B2=A4=EC=85=98=EC=97=90=20?= =?UTF-8?q?=EB=A7=9E=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../demo/exception/GlobalExceptionHandler.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/example/demo/exception/GlobalExceptionHandler.java b/src/main/java/com/example/demo/exception/GlobalExceptionHandler.java index a15616b..98e615c 100644 --- a/src/main/java/com/example/demo/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/example/demo/exception/GlobalExceptionHandler.java @@ -9,55 +9,55 @@ public class GlobalExceptionHandler { @ExceptionHandler(RequestNullExistException.class) - public ResponseEntity RequestNullExistException() { + public ResponseEntity requestNullExistException() { ErrorResponse response = new ErrorResponse(ErrorCode.REQUEST_NULL_VALUE); return new ResponseEntity<>(response, HttpStatusCode.valueOf(400)); } @ExceptionHandler(MemberNotExistException.class) - public ResponseEntity MemberNotExistException() { + public ResponseEntity memberNotExistException() { ErrorResponse response = new ErrorResponse(ErrorCode.MEMBER_NOT_EXIST); return new ResponseEntity<>(response, HttpStatusCode.valueOf(400)); } @ExceptionHandler(BoardNotExistException.class) - public ResponseEntity BoardNotExistException() { + public ResponseEntity boardNotExistException() { ErrorResponse response = new ErrorResponse(ErrorCode.BOARD_NOT_EXIST); return new ResponseEntity<>(response, HttpStatusCode.valueOf(400)); } @ExceptionHandler(ArticleNotFoundException.class) - public ResponseEntity ArticleNotFoundException() { + public ResponseEntity articleNotFoundException() { ErrorResponse response = new ErrorResponse(ErrorCode.ARTICLE_NOT_EXIST); return new ResponseEntity<>(response, HttpStatusCode.valueOf(404)); } @ExceptionHandler(MemberNotFoundException.class) - public ResponseEntity MemberNotFoundException() { + public ResponseEntity memberNotFoundException() { ErrorResponse response = new ErrorResponse(ErrorCode.MEMBER_NOT_FOUND); return new ResponseEntity<>(response, HttpStatusCode.valueOf(404)); } @ExceptionHandler(BoardNotFoundException.class) - public ResponseEntity BoardNotFoundException() { + public ResponseEntity boardNotFoundException() { ErrorResponse response = new ErrorResponse(ErrorCode.BOARD_NOT_FOUND); return new ResponseEntity<>(response, HttpStatusCode.valueOf(404)); } @ExceptionHandler(AlreadyHasEmailException.class) - public ResponseEntity AlreadyHasEmailException() { + public ResponseEntity alreadyHasEmailException() { ErrorResponse response = new ErrorResponse(ErrorCode.EMAIL_EXIST); return new ResponseEntity<>(response, HttpStatusCode.valueOf(409)); } @ExceptionHandler(MemberHasArticleException.class) - public ResponseEntity MemberHasArticleException() { + public ResponseEntity memberHasArticleException() { ErrorResponse response = new ErrorResponse(ErrorCode.MEMBER_ARTICLE_EXIST); return new ResponseEntity<>(response, HttpStatusCode.valueOf(400)); } @ExceptionHandler(BoardHasArticleException.class) - public ResponseEntity BoardHasArticleException() { + public ResponseEntity boardHasArticleException() { ErrorResponse response = new ErrorResponse(ErrorCode.BOARD_ARTICLE_EXIST); return new ResponseEntity<>(response, HttpStatusCode.valueOf(400)); } From 18e2fd348c2702f7614381b7cf0def41e4b1fcaf Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Tue, 25 Jun 2024 11:47:06 +0900 Subject: [PATCH 14/22] =?UTF-8?q?fix:=20yml=20=ED=8C=8C=EC=9D=BC=20jpa=20?= =?UTF-8?q?=EC=86=8D=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 2ae6a82..c13ca95 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -4,3 +4,11 @@ spring: username: root # 본인의 환경에 맞게 수정한다. password: jabell0310 # 본인의 환경에 맞게 수정한다. driver-class-name: com.mysql.cj.jdbc.Driver + + jpa: + hibernate: + ddl-auto: update + + show-sql: true + + From eca08d98bafda8bbca294b8ffd9d75de85d37c07 Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Tue, 25 Jun 2024 11:47:49 +0900 Subject: [PATCH 15/22] =?UTF-8?q?fix:=20Entity=20=EA=B0=9D=EC=B2=B4=20Mysq?= =?UTF-8?q?l=20=ED=85=8C=EC=9D=B4=EB=B8=94=EA=B3=BC=20=EB=A7=A4=ED=95=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/demo/domain/Article.java | 18 ++++++++++++++++++ .../java/com/example/demo/domain/Board.java | 8 ++++++++ .../java/com/example/demo/domain/Member.java | 12 +++++++++++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/example/demo/domain/Article.java b/src/main/java/com/example/demo/domain/Article.java index 355480d..099433b 100644 --- a/src/main/java/com/example/demo/domain/Article.java +++ b/src/main/java/com/example/demo/domain/Article.java @@ -1,22 +1,40 @@ package com.example.demo.domain; +import jakarta.persistence.*; + import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import java.time.LocalDateTime; +@Entity +@Table(name = "article") @NoArgsConstructor @Getter @Setter public class Article { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @Column(name = "author_id", nullable = false) private Long authorId; + + @Column(name = "board_id", nullable = false) private Long boardId; + + @Column(name = "title", nullable = false) private String title; + + @Column(name = "content", nullable = false) private String content; + + @Column(name = "created_date") private LocalDateTime createdAt; + + @Column(name = "modified_date") private LocalDateTime modifiedAt; public Article( diff --git a/src/main/java/com/example/demo/domain/Board.java b/src/main/java/com/example/demo/domain/Board.java index 2db0216..d296a2e 100644 --- a/src/main/java/com/example/demo/domain/Board.java +++ b/src/main/java/com/example/demo/domain/Board.java @@ -1,14 +1,22 @@ package com.example.demo.domain; +import jakarta.persistence.*; + import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +@Entity +@Table(name = "board") @NoArgsConstructor @Getter @Setter public class Board { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @Column(name = "name", nullable = false) private String name; public Board(Long id, String name) { diff --git a/src/main/java/com/example/demo/domain/Member.java b/src/main/java/com/example/demo/domain/Member.java index c5ecbdf..1fca74a 100644 --- a/src/main/java/com/example/demo/domain/Member.java +++ b/src/main/java/com/example/demo/domain/Member.java @@ -1,18 +1,28 @@ package com.example.demo.domain; +import jakarta.persistence.*; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; - +@Entity +@Table(name = "member") @NoArgsConstructor @Getter @Setter public class Member { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @Column(name = "name", nullable = false) private String name; + + @Column(name = "email", nullable = false) private String email; + + @Column(name = "password", nullable = false) private String password; public Member(Long id, String name, String email, String password) { From 745fc8fee6ea90052c1b91dae94a0493993ecdb6 Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Tue, 25 Jun 2024 11:49:07 +0900 Subject: [PATCH 16/22] =?UTF-8?q?fix:=20Repository=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?JPA=EC=9D=98=20EntityManager=EB=A5=BC=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EC=97=AC=20=EB=8C=80=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/ArticleRepositoryJdbc.java | 106 +++++------------- .../demo/repository/BoardRepositoryJdbc.java | 70 ++++-------- .../demo/repository/MemberRepositoryJdbc.java | 75 ++++--------- 3 files changed, 74 insertions(+), 177 deletions(-) diff --git a/src/main/java/com/example/demo/repository/ArticleRepositoryJdbc.java b/src/main/java/com/example/demo/repository/ArticleRepositoryJdbc.java index 47bfedf..0e8d724 100644 --- a/src/main/java/com/example/demo/repository/ArticleRepositoryJdbc.java +++ b/src/main/java/com/example/demo/repository/ArticleRepositoryJdbc.java @@ -1,13 +1,11 @@ package com.example.demo.repository; -import java.sql.PreparedStatement; import java.util.List; -import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.support.GeneratedKeyHolder; -import org.springframework.jdbc.support.KeyHolder; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import jakarta.transaction.Transactional; + import org.springframework.stereotype.Repository; import com.example.demo.domain.Article; @@ -15,99 +13,57 @@ @Repository public class ArticleRepositoryJdbc implements ArticleRepository { - private final JdbcTemplate jdbcTemplate; + @PersistenceContext + private EntityManager em; - public ArticleRepositoryJdbc(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; + @Override + @Transactional + public Article insert(Article article) { + em.persist(article); + return article; } - private static final RowMapper
articleRowMapper = (rs, rowNum) -> new Article( - rs.getLong("id"), - rs.getLong("author_id"), - rs.getLong("board_id"), - rs.getString("title"), - rs.getString("content"), - rs.getTimestamp("created_date").toLocalDateTime(), - rs.getTimestamp("modified_date").toLocalDateTime() - ); - @Override + @Transactional public List
findAll() { - return jdbcTemplate.query(""" - SELECT id, board_id, author_id, title, content, created_date, modified_date - FROM article - """, articleRowMapper); + String jpql = "SELECT a FROM Article a"; + return em.createQuery(jpql, Article.class).getResultList(); } @Override + @Transactional public List
findAllByBoardId(Long boardId) { - return jdbcTemplate.query(""" - SELECT id, board_id, author_id, title, content, created_date, modified_date - FROM article - WHERE board_id = ? - """, articleRowMapper, boardId); + String jpql = "SELECT a FROM Article a WHERE a.boardId = :boardId"; + return em.createQuery(jpql, Article.class) + .setParameter("boardId", boardId) + .getResultList(); } @Override + @Transactional public List
findAllByMemberId(Long memberId) { - return jdbcTemplate.query(""" - SELECT id, board_id, author_id, title, content, created_date, modified_date - FROM article - WHERE author_id = ? - """, articleRowMapper, memberId); + String jpql = "SELECT a FROM Article a WHERE a.authorId = :memberId"; + return em.createQuery(jpql, Article.class) + .setParameter("memberId", memberId) + .getResultList(); } @Override + @Transactional public Article findById(Long id) { - try { - return jdbcTemplate.queryForObject(""" - SELECT id, board_id, author_id, title, content, created_date, modified_date - FROM article - WHERE id = ? - """, articleRowMapper, id); - } catch (EmptyResultDataAccessException e) { - return null; - } - } - - @Override - public Article insert(Article article) { - KeyHolder keyHolder = new GeneratedKeyHolder(); - jdbcTemplate.update(con -> { - PreparedStatement ps = con.prepareStatement(""" - INSERT INTO article (board_id, author_id, title, content) - VALUES (?, ?, ?, ?) - """, - new String[]{"id"}); - ps.setLong(1, article.getBoardId()); - ps.setLong(2, article.getAuthorId()); - ps.setString(3, article.getTitle()); - ps.setString(4, article.getContent()); - return ps; - }, keyHolder); - return findById(keyHolder.getKey().longValue()); + return em.find(Article.class, id); } @Override + @Transactional public Article update(Article article) { - jdbcTemplate.update(""" - UPDATE article - SET board_id = ?, title = ?, content = ? - WHERE id = ? - """, - article.getBoardId(), - article.getTitle(), - article.getContent(), - article.getId() - ); - return findById(article.getId()); + em.merge(article); + return article; } @Override + @Transactional public void deleteById(Long id) { - jdbcTemplate.update(""" - DELETE FROM article - WHERE id = ? - """, id); + em.remove(findById(id)); } } diff --git a/src/main/java/com/example/demo/repository/BoardRepositoryJdbc.java b/src/main/java/com/example/demo/repository/BoardRepositoryJdbc.java index d932791..74ef1f2 100644 --- a/src/main/java/com/example/demo/repository/BoardRepositoryJdbc.java +++ b/src/main/java/com/example/demo/repository/BoardRepositoryJdbc.java @@ -1,13 +1,11 @@ package com.example.demo.repository; -import java.sql.PreparedStatement; import java.util.List; -import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.support.GeneratedKeyHolder; -import org.springframework.jdbc.support.KeyHolder; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import jakarta.transaction.Transactional; + import org.springframework.stereotype.Repository; import com.example.demo.domain.Board; @@ -15,63 +13,39 @@ @Repository public class BoardRepositoryJdbc implements BoardRepository { - private final JdbcTemplate jdbcTemplate; + @PersistenceContext + private EntityManager em; - public BoardRepositoryJdbc(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; + @Override + @Transactional + public Board insert(Board board) { + em.persist(board); + return board; } - private static final RowMapper boardRowMapper = (rs, rowNum) -> new Board( - rs.getLong("id"), - rs.getString("name") - ); - @Override + @Transactional public List findAll() { - return jdbcTemplate.query(""" - SELECT id, name - FROM board - """, boardRowMapper); + String jpql = "SELECT b from Board b"; + return em.createQuery(jpql, Board.class).getResultList(); } @Override + @Transactional public Board findById(Long id) { - try { - return jdbcTemplate.queryForObject(""" - SELECT id, name - FROM board - WHERE id = ? - """, boardRowMapper, id); - } catch (EmptyResultDataAccessException e) { - return null; - } + return em.find(Board.class, id); } @Override - public Board insert(Board board) { - KeyHolder keyHolder = new GeneratedKeyHolder(); - jdbcTemplate.update(con -> { - PreparedStatement ps = con.prepareStatement(""" - INSERT INTO board (name) VALUES (?) - """, new String[]{"id"}); - ps.setString(1, board.getName()); - return ps; - }, keyHolder); - return findById(keyHolder.getKey().longValue()); + @Transactional + public Board update(Board board) { + em.merge(board); + return board; } @Override + @Transactional public void deleteById(Long id) { - jdbcTemplate.update(""" - DELETE FROM board WHERE id = ? - """, id); - } - - @Override - public Board update(Board board) { - return jdbcTemplate.queryForObject(""" - UPDATE board SET name = ? WHERE id = ? - """, boardRowMapper, board.getName(), board.getId() - ); + em.remove(findById(id)); } } diff --git a/src/main/java/com/example/demo/repository/MemberRepositoryJdbc.java b/src/main/java/com/example/demo/repository/MemberRepositoryJdbc.java index 8e432a6..8e6c11f 100644 --- a/src/main/java/com/example/demo/repository/MemberRepositoryJdbc.java +++ b/src/main/java/com/example/demo/repository/MemberRepositoryJdbc.java @@ -1,13 +1,11 @@ package com.example.demo.repository; -import java.sql.PreparedStatement; import java.util.List; -import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.support.GeneratedKeyHolder; -import org.springframework.jdbc.support.KeyHolder; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import jakarta.transaction.Transactional; + import org.springframework.stereotype.Repository; import com.example.demo.domain.Member; @@ -15,70 +13,39 @@ @Repository public class MemberRepositoryJdbc implements MemberRepository { - private final JdbcTemplate jdbcTemplate; + @PersistenceContext + private EntityManager em; - public MemberRepositoryJdbc(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; + @Override + @Transactional + public Member insert(Member member) { + em.persist(member); + return member; } - private static final RowMapper memberRowMapper = (rs, rowNum) -> new Member( - rs.getLong("id"), - rs.getString("name"), - rs.getString("email"), - rs.getString("password") - ); - @Override + @Transactional public List findAll() { - return jdbcTemplate.query(""" - SELECT id, name, email, password - FROM member - """, memberRowMapper); + String jpql = "SELECT m FROM Member m"; + return em.createQuery(jpql, Member.class).getResultList(); } @Override + @Transactional public Member findById(Long id) { - try { - return jdbcTemplate.queryForObject(""" - SELECT id, name, email, password - FROM member - WHERE id = ? - """, memberRowMapper, id); - } catch (EmptyResultDataAccessException e) { - return null; - } - } - - @Override - public Member insert(Member member) { - KeyHolder keyHolder = new GeneratedKeyHolder(); - jdbcTemplate.update(con -> { - PreparedStatement ps = con.prepareStatement(""" - INSERT INTO member (name, email, password) VALUES (?, ?, ?) - """, new String[]{"id"}); - ps.setString(1, member.getName()); - ps.setString(2, member.getEmail()); - ps.setString(3, member.getPassword()); - return ps; - }, keyHolder); - return findById(keyHolder.getKey().longValue()); + return em.find(Member.class, id); } @Override + @Transactional public Member update(Member member) { - jdbcTemplate.update(""" - UPDATE member - SET name = ?, email = ? - WHERE id = ? - """, member.getName(), member.getEmail(), member.getId()); - return findById(member.getId()); + em.merge(member); + return member; } @Override + @Transactional public void deleteById(Long id) { - jdbcTemplate.update(""" - DELETE FROM member - WHERE id = ? - """, id); + em.remove(findById(id)); } } From 07ee75c5a0ccfdf5710bf371f714dd2566ae912a Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Tue, 25 Jun 2024 11:51:20 +0900 Subject: [PATCH 17/22] =?UTF-8?q?fix:=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20Jpa=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{ArticleRepositoryJdbc.java => ArticleRepositoryJpa.java} | 2 +- .../{BoardRepositoryJdbc.java => BoardRepositoryJpa.java} | 2 +- .../{MemberRepositoryJdbc.java => MemberRepositoryJpa.java} | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename src/main/java/com/example/demo/repository/{ArticleRepositoryJdbc.java => ArticleRepositoryJpa.java} (96%) rename src/main/java/com/example/demo/repository/{BoardRepositoryJdbc.java => BoardRepositoryJpa.java} (94%) rename src/main/java/com/example/demo/repository/{MemberRepositoryJdbc.java => MemberRepositoryJpa.java} (94%) diff --git a/src/main/java/com/example/demo/repository/ArticleRepositoryJdbc.java b/src/main/java/com/example/demo/repository/ArticleRepositoryJpa.java similarity index 96% rename from src/main/java/com/example/demo/repository/ArticleRepositoryJdbc.java rename to src/main/java/com/example/demo/repository/ArticleRepositoryJpa.java index 0e8d724..d626db1 100644 --- a/src/main/java/com/example/demo/repository/ArticleRepositoryJdbc.java +++ b/src/main/java/com/example/demo/repository/ArticleRepositoryJpa.java @@ -11,7 +11,7 @@ import com.example.demo.domain.Article; @Repository -public class ArticleRepositoryJdbc implements ArticleRepository { +public class ArticleRepositoryJpa implements ArticleRepository { @PersistenceContext private EntityManager em; diff --git a/src/main/java/com/example/demo/repository/BoardRepositoryJdbc.java b/src/main/java/com/example/demo/repository/BoardRepositoryJpa.java similarity index 94% rename from src/main/java/com/example/demo/repository/BoardRepositoryJdbc.java rename to src/main/java/com/example/demo/repository/BoardRepositoryJpa.java index 74ef1f2..a25965c 100644 --- a/src/main/java/com/example/demo/repository/BoardRepositoryJdbc.java +++ b/src/main/java/com/example/demo/repository/BoardRepositoryJpa.java @@ -11,7 +11,7 @@ import com.example.demo.domain.Board; @Repository -public class BoardRepositoryJdbc implements BoardRepository { +public class BoardRepositoryJpa implements BoardRepository { @PersistenceContext private EntityManager em; diff --git a/src/main/java/com/example/demo/repository/MemberRepositoryJdbc.java b/src/main/java/com/example/demo/repository/MemberRepositoryJpa.java similarity index 94% rename from src/main/java/com/example/demo/repository/MemberRepositoryJdbc.java rename to src/main/java/com/example/demo/repository/MemberRepositoryJpa.java index 8e6c11f..fd21367 100644 --- a/src/main/java/com/example/demo/repository/MemberRepositoryJdbc.java +++ b/src/main/java/com/example/demo/repository/MemberRepositoryJpa.java @@ -11,7 +11,7 @@ import com.example.demo.domain.Member; @Repository -public class MemberRepositoryJdbc implements MemberRepository { +public class MemberRepositoryJpa implements MemberRepository { @PersistenceContext private EntityManager em; From a66e562c53e7842caf365ccaf3bf04f654f0d180 Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Tue, 25 Jun 2024 11:54:32 +0900 Subject: [PATCH 18/22] =?UTF-8?q?test:=20=EC=98=81=EC=86=8D=EC=84=B1=20?= =?UTF-8?q?=EC=BB=A8=ED=85=8D=EC=8A=A4=ED=8A=B8=EB=A5=BC=20=ED=99=9C?= =?UTF-8?q?=EC=9A=A9=ED=95=9C=20CRUD=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/ArticleRepositoryJpaTest.java | 102 ++++++++++++++++++ .../repository/BoardRepositoryJpaTest.java | 93 ++++++++++++++++ .../repository/MemberRepositoryJpaTest.java | 95 ++++++++++++++++ 3 files changed, 290 insertions(+) create mode 100644 src/test/java/com/example/demo/repository/ArticleRepositoryJpaTest.java create mode 100644 src/test/java/com/example/demo/repository/BoardRepositoryJpaTest.java create mode 100644 src/test/java/com/example/demo/repository/MemberRepositoryJpaTest.java diff --git a/src/test/java/com/example/demo/repository/ArticleRepositoryJpaTest.java b/src/test/java/com/example/demo/repository/ArticleRepositoryJpaTest.java new file mode 100644 index 0000000..e8fd6f3 --- /dev/null +++ b/src/test/java/com/example/demo/repository/ArticleRepositoryJpaTest.java @@ -0,0 +1,102 @@ +package com.example.demo.repository; + +import com.example.demo.domain.Article; + +import jakarta.transaction.Transactional; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.time.LocalDateTime; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +@Transactional +class ArticleRepositoryJpaTest { + + private final ArticleRepositoryJpa articleRepository; + + @Autowired + public ArticleRepositoryJpaTest(ArticleRepositoryJpa articleRepository) { + this.articleRepository = articleRepository; + } + + private Article article; + + @BeforeEach + void setUp() { + article = new Article(null, 1L, 1L, "New Title", "New Content", LocalDateTime.now(), LocalDateTime.now()); + } + + @Test + @DisplayName("게시물이 생성되는지 확인하는 테스트") + void insert() { + //Given + Article savedArticle = articleRepository.insert(article); + //When + assertNotNull(savedArticle.getId()); + //Then + assertEquals(article.getTitle(), savedArticle.getTitle()); + assertEquals(article.getContent(), savedArticle.getContent()); + assertNotNull(savedArticle.getCreatedAt()); + assertNotNull(savedArticle.getModifiedAt()); + } + + @Test + @DisplayName("게시물이 모두 찾아지는지 확인하는 테스트") + void findAll() { + //Given + List
articles = articleRepository.findAll(); + //When + assertFalse(articles.isEmpty()); + //Then + assertEquals(16, articles.size()); + } + + @Test + @DisplayName("특정 게시물이 찾아지는지 확인하는 테스트") + void findById() { + //Given + Article foundArticle = articleRepository.findById(1L); + //When + assertNotNull(foundArticle); + //Then + assertEquals(1L, foundArticle.getId()); + assertEquals("자그레우스", foundArticle.getTitle()); + assertEquals("Hades의 주인공", foundArticle.getContent()); + } + + @Test + @DisplayName("특정 게시물이 수정되는지 확인하는 테스트") + void update() { + //Given + Article savedArticle = articleRepository.insert(article); + //When + savedArticle.update(2L, "Updated Title", "Updated Content"); + Article updatedArticle = articleRepository.update(savedArticle); + //Then + assertEquals("Updated Title", updatedArticle.getTitle()); + assertEquals("Updated Content", updatedArticle.getContent()); + assertEquals(2L, updatedArticle.getBoardId()); + assertNotNull(updatedArticle.getModifiedAt()); + assertTrue(updatedArticle.getModifiedAt().isAfter(updatedArticle.getCreatedAt())); + } + + @Test + @DisplayName("특정 게시물이 삭제되는지 확인하는 테스트") + void deleteById() { + //Given + Article savedArticle = articleRepository.insert(article); + //When + articleRepository.deleteById(savedArticle.getId()); + Article deletedArticle = articleRepository.findById(savedArticle.getId()); + //Then + assertNull(deletedArticle); + } +} \ No newline at end of file diff --git a/src/test/java/com/example/demo/repository/BoardRepositoryJpaTest.java b/src/test/java/com/example/demo/repository/BoardRepositoryJpaTest.java new file mode 100644 index 0000000..fc5a459 --- /dev/null +++ b/src/test/java/com/example/demo/repository/BoardRepositoryJpaTest.java @@ -0,0 +1,93 @@ +package com.example.demo.repository; + +import com.example.demo.domain.Board; + +import jakarta.transaction.Transactional; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +@Transactional +class BoardRepositoryJpaTest { + + private final BoardRepositoryJpa boardRepository; + + @Autowired + public BoardRepositoryJpaTest(BoardRepositoryJpa boardRepository) { + this.boardRepository = boardRepository; + } + + private Board board; + + @BeforeEach + void setUp() { + board = new Board(null,"new board"); + } + + @Test + @DisplayName("게시판이 생성되는지 확인하는 테스트") + void insert() { + //Given + Board savedBoard = boardRepository.insert(board); + //When + assertNotNull(savedBoard.getId()); + //Then + assertEquals(board.getName(), savedBoard.getName()); + } + + @Test + @DisplayName("게시판이 모두 찾아지는지 확인하는 테스트") + void findAll() { + //Given + List boards = boardRepository.findAll(); + //When + assertFalse(boards.isEmpty()); + //Then + assertEquals(5, boards.size()); + } + + @Test + @DisplayName("특정 게시판이 찾아지는지 확인하는 테스트") + void findById() { + //Given + Board foundBoard = boardRepository.findById(1L); + //When + assertNotNull(foundBoard); + //Then + assertEquals(1L, foundBoard.getId()); + assertEquals("하데스", foundBoard.getName()); + } + + @Test + @DisplayName("특정 게시판이 수정되는지 확인하는 테스트") + void update() { + //Given + Board savedBoard = boardRepository.insert(board); + //When + savedBoard.update("수정된 게시판1"); + Board updatedBoard = boardRepository.update(savedBoard); + //Then + assertEquals("수정된 게시판1", updatedBoard.getName()); + } + + @Test + @DisplayName("특정 게시판이 삭제되는지 확인하는 테스트") + void deleteById() { + //Given + Board savedBoard = boardRepository.insert(board); + //When + boardRepository.deleteById(savedBoard.getId()); + Board deletedBoard = boardRepository.findById(savedBoard.getId()); + //Then + assertNull(deletedBoard); + } +} \ No newline at end of file diff --git a/src/test/java/com/example/demo/repository/MemberRepositoryJpaTest.java b/src/test/java/com/example/demo/repository/MemberRepositoryJpaTest.java new file mode 100644 index 0000000..d9430c1 --- /dev/null +++ b/src/test/java/com/example/demo/repository/MemberRepositoryJpaTest.java @@ -0,0 +1,95 @@ +package com.example.demo.repository; + +import com.example.demo.domain.Member; +import jakarta.transaction.Transactional; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +@Transactional +class MemberRepositoryJpaTest { + + private final MemberRepositoryJpa memberRepository; + + @Autowired + public MemberRepositoryJpaTest(MemberRepositoryJpa memberRepository) { + this.memberRepository = memberRepository; + } + + private Member member; + + @BeforeEach + void setUp() { + member = new Member("user7", "member7@gmail.com", "password7"); + } + + @Test + @DisplayName("회원이 생성되는지 확인하는 테스트") + void insert() { + //Given + Member savedMember = memberRepository.insert(member); + //When + assertNotNull(savedMember.getId()); + //Then + assertEquals(member.getName(), savedMember.getName()); + assertEquals(member.getEmail(), savedMember.getEmail()); + assertEquals(member.getPassword(), savedMember.getPassword()); + } + + @Test + @DisplayName("회원이 모두 찾아지는지 확인하는 테스트") + void findAll() { + //Given + List members = memberRepository.findAll(); + //When + assertFalse(members.isEmpty()); + //Then + assertEquals(6, members.size()); + } + + @Test + @DisplayName("특정 회원이 찾아지는지 확인하는 테스트") + void findById() { + //Given + Member foundMember = memberRepository.findById(1L); + //When + assertNotNull(foundMember); + //Then + assertEquals(1L, foundMember.getId()); + assertEquals("user1", foundMember.getName()); + assertEquals("user1@gmail.com", foundMember.getEmail()); + assertEquals("password1", foundMember.getPassword()); + } + + @Test + @DisplayName("특정 회원이 수정되는지 확인하는 테스트") + void update() { + //Given + Member savedMember = memberRepository.insert(member); + //When + savedMember.update("User1", "User1@gmail.com"); + Member updatedMember = memberRepository.update(savedMember); + //Then + assertEquals("User1", updatedMember.getName()); + assertEquals("User1@gmail.com", updatedMember.getEmail()); + } + + @Test + @DisplayName("특정 게시판이 삭제되는지 확인하는 테스트") + void deleteById() { + //Given + Member savedMember = memberRepository.insert(member); + //When + memberRepository.deleteById(savedMember.getId()); + Member deletedMember = memberRepository.findById(savedMember.getId()); + //Then + assertNull(deletedMember); + } +} \ No newline at end of file From 3688fb63e7d311a140988d3ef4215c78b0aa1aeb Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Mon, 1 Jul 2024 21:26:54 +0900 Subject: [PATCH 19/22] =?UTF-8?q?feat:=20=EC=97=B0=EA=B4=80=20=EA=B4=80?= =?UTF-8?q?=EA=B3=84=20=EB=B0=8F=20=EC=98=81=EC=86=8D=EC=84=B1=20=EC=A0=84?= =?UTF-8?q?=EC=9D=B4,=20=EA=B3=A0=EC=95=84=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EA=B0=9C=EB=85=90=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/demo/domain/Article.java | 4 ++++ src/main/java/com/example/demo/domain/Board.java | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/src/main/java/com/example/demo/domain/Article.java b/src/main/java/com/example/demo/domain/Article.java index 099433b..cfd6227 100644 --- a/src/main/java/com/example/demo/domain/Article.java +++ b/src/main/java/com/example/demo/domain/Article.java @@ -37,6 +37,10 @@ public class Article { @Column(name = "modified_date") private LocalDateTime modifiedAt; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "board_id", insertable = false, updatable = false) + private Board board; + public Article( Long id, Long authorId, diff --git a/src/main/java/com/example/demo/domain/Board.java b/src/main/java/com/example/demo/domain/Board.java index d296a2e..1dc1ae6 100644 --- a/src/main/java/com/example/demo/domain/Board.java +++ b/src/main/java/com/example/demo/domain/Board.java @@ -6,6 +6,9 @@ import lombok.NoArgsConstructor; import lombok.Setter; +import java.util.ArrayList; +import java.util.List; + @Entity @Table(name = "board") @NoArgsConstructor @@ -19,6 +22,9 @@ public class Board { @Column(name = "name", nullable = false) private String name; + @OneToMany(mappedBy = "board", cascade = CascadeType.ALL, orphanRemoval = true) + private List
articles = new ArrayList<>(); + public Board(Long id, String name) { this.id = id; this.name = name; From 4904efafa3e1d8f9c32580d0011d9ebf2f3ec2d2 Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Mon, 1 Jul 2024 21:33:14 +0900 Subject: [PATCH 20/22] =?UTF-8?q?refactor:=20Spring=20Data=20JPA=EB=A5=BC?= =?UTF-8?q?=20=EC=82=AC=EC=9A=A9=ED=95=98=EC=97=AC=20=EA=B8=B0=EC=A1=B4=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EB=B3=B4=EC=99=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../demo/repository/ArticleRepository.java | 13 +-- .../demo/repository/ArticleRepositoryJpa.java | 69 ------------ .../repository/ArticleRepositoryMemory.java | 70 ------------ .../demo/repository/BoardRepository.java | 13 +-- .../demo/repository/BoardRepositoryJpa.java | 51 --------- .../repository/BoardRepositoryMemory.java | 50 --------- .../demo/repository/MemberRepository.java | 13 +-- .../demo/repository/MemberRepositoryJpa.java | 51 --------- .../repository/MemberRepositoryMemory.java | 52 --------- .../example/demo/service/ArticleService.java | 57 +++------- .../example/demo/service/BoardService.java | 21 ++-- .../example/demo/service/MemberService.java | 18 ++-- .../example/demo/DemoApplicationTests.java | 13 --- .../repository/ArticleRepositoryJpaTest.java | 102 ------------------ .../repository/BoardRepositoryJpaTest.java | 93 ---------------- .../demo/service/BoardServiceTest.java | 87 +++++++++++++++ 16 files changed, 121 insertions(+), 652 deletions(-) delete mode 100644 src/main/java/com/example/demo/repository/ArticleRepositoryJpa.java delete mode 100644 src/main/java/com/example/demo/repository/ArticleRepositoryMemory.java delete mode 100644 src/main/java/com/example/demo/repository/BoardRepositoryJpa.java delete mode 100644 src/main/java/com/example/demo/repository/BoardRepositoryMemory.java delete mode 100644 src/main/java/com/example/demo/repository/MemberRepositoryJpa.java delete mode 100644 src/main/java/com/example/demo/repository/MemberRepositoryMemory.java delete mode 100644 src/test/java/com/example/demo/DemoApplicationTests.java delete mode 100644 src/test/java/com/example/demo/repository/ArticleRepositoryJpaTest.java delete mode 100644 src/test/java/com/example/demo/repository/BoardRepositoryJpaTest.java create mode 100644 src/test/java/com/example/demo/service/BoardServiceTest.java diff --git a/src/main/java/com/example/demo/repository/ArticleRepository.java b/src/main/java/com/example/demo/repository/ArticleRepository.java index be3ebd4..917e52c 100644 --- a/src/main/java/com/example/demo/repository/ArticleRepository.java +++ b/src/main/java/com/example/demo/repository/ArticleRepository.java @@ -4,19 +4,10 @@ import com.example.demo.domain.Article; -public interface ArticleRepository { +import org.springframework.data.jpa.repository.JpaRepository; - List
findAll(); +public interface ArticleRepository extends JpaRepository { List
findAllByBoardId(Long boardId); - List
findAllByMemberId(Long memberId); - - Article findById(Long id); - - Article insert(Article article); - - Article update(Article article); - - void deleteById(Long id); } diff --git a/src/main/java/com/example/demo/repository/ArticleRepositoryJpa.java b/src/main/java/com/example/demo/repository/ArticleRepositoryJpa.java deleted file mode 100644 index d626db1..0000000 --- a/src/main/java/com/example/demo/repository/ArticleRepositoryJpa.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.example.demo.repository; - -import java.util.List; - -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; -import jakarta.transaction.Transactional; - -import org.springframework.stereotype.Repository; - -import com.example.demo.domain.Article; - -@Repository -public class ArticleRepositoryJpa implements ArticleRepository { - - @PersistenceContext - private EntityManager em; - - @Override - @Transactional - public Article insert(Article article) { - em.persist(article); - return article; - } - - @Override - @Transactional - public List
findAll() { - String jpql = "SELECT a FROM Article a"; - return em.createQuery(jpql, Article.class).getResultList(); - } - - @Override - @Transactional - public List
findAllByBoardId(Long boardId) { - String jpql = "SELECT a FROM Article a WHERE a.boardId = :boardId"; - return em.createQuery(jpql, Article.class) - .setParameter("boardId", boardId) - .getResultList(); - } - - @Override - @Transactional - public List
findAllByMemberId(Long memberId) { - String jpql = "SELECT a FROM Article a WHERE a.authorId = :memberId"; - return em.createQuery(jpql, Article.class) - .setParameter("memberId", memberId) - .getResultList(); - } - - @Override - @Transactional - public Article findById(Long id) { - return em.find(Article.class, id); - } - - @Override - @Transactional - public Article update(Article article) { - em.merge(article); - return article; - } - - @Override - @Transactional - public void deleteById(Long id) { - em.remove(findById(id)); - } -} diff --git a/src/main/java/com/example/demo/repository/ArticleRepositoryMemory.java b/src/main/java/com/example/demo/repository/ArticleRepositoryMemory.java deleted file mode 100644 index 13ba78b..0000000 --- a/src/main/java/com/example/demo/repository/ArticleRepositoryMemory.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.example.demo.repository; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; - -import com.example.demo.domain.Article; - -public class ArticleRepositoryMemory implements ArticleRepository { - - private static final Map articles = new HashMap<>(); - private static final AtomicLong autoincrement = new AtomicLong(1); - - @Override - public List
findAll() { - return articles.entrySet().stream() - .map(it -> { - Article article = it.getValue(); - article.setId(it.getKey()); - return article; - }).toList(); - } - - @Override - public List
findAllByBoardId(Long boardId) { - return articles.entrySet().stream() - .filter(it -> it.getValue().getBoardId().equals(boardId)) - .map(it -> { - Article article = it.getValue(); - article.setId(it.getKey()); - return article; - }).toList(); - } - - @Override - public List
findAllByMemberId(Long memberId) { - return articles.entrySet().stream() - .filter(it -> it.getValue().getAuthorId().equals(memberId)) - .map(it -> { - Article article = it.getValue(); - article.setId(it.getKey()); - return article; - }).toList(); - } - - @Override - public Article findById(Long id) { - return articles.getOrDefault(id, null); - } - - @Override - public Article insert(Article article) { - long id = autoincrement.getAndIncrement(); - articles.put(id, article); - article.setId(id); - return article; - } - - @Override - public Article update(Article article) { - articles.put(article.getId(), article); - return article; - } - - @Override - public void deleteById(Long id) { - articles.remove(id); - } -} diff --git a/src/main/java/com/example/demo/repository/BoardRepository.java b/src/main/java/com/example/demo/repository/BoardRepository.java index cc2dfd0..3a5da9b 100644 --- a/src/main/java/com/example/demo/repository/BoardRepository.java +++ b/src/main/java/com/example/demo/repository/BoardRepository.java @@ -1,18 +1,9 @@ package com.example.demo.repository; -import java.util.List; - import com.example.demo.domain.Board; -public interface BoardRepository { - - List findAll(); - - Board findById(Long id); - - Board insert(Board board); +import org.springframework.data.jpa.repository.JpaRepository; - void deleteById(Long id); +public interface BoardRepository extends JpaRepository { - Board update(Board board); } diff --git a/src/main/java/com/example/demo/repository/BoardRepositoryJpa.java b/src/main/java/com/example/demo/repository/BoardRepositoryJpa.java deleted file mode 100644 index a25965c..0000000 --- a/src/main/java/com/example/demo/repository/BoardRepositoryJpa.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.example.demo.repository; - -import java.util.List; - -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; -import jakarta.transaction.Transactional; - -import org.springframework.stereotype.Repository; - -import com.example.demo.domain.Board; - -@Repository -public class BoardRepositoryJpa implements BoardRepository { - - @PersistenceContext - private EntityManager em; - - @Override - @Transactional - public Board insert(Board board) { - em.persist(board); - return board; - } - - @Override - @Transactional - public List findAll() { - String jpql = "SELECT b from Board b"; - return em.createQuery(jpql, Board.class).getResultList(); - } - - @Override - @Transactional - public Board findById(Long id) { - return em.find(Board.class, id); - } - - @Override - @Transactional - public Board update(Board board) { - em.merge(board); - return board; - } - - @Override - @Transactional - public void deleteById(Long id) { - em.remove(findById(id)); - } -} diff --git a/src/main/java/com/example/demo/repository/BoardRepositoryMemory.java b/src/main/java/com/example/demo/repository/BoardRepositoryMemory.java deleted file mode 100644 index 8cf5ecf..0000000 --- a/src/main/java/com/example/demo/repository/BoardRepositoryMemory.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.example.demo.repository; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; - -import com.example.demo.domain.Board; - -public class BoardRepositoryMemory implements BoardRepository { - - private static final Map boards = new HashMap<>(); - private static final AtomicLong autoincrement = new AtomicLong(1); - - static { - // 1번 게시판을 미리 만들어둔다. - boards.put(autoincrement.getAndIncrement(), new Board("자유게시판")); - } - - @Override - public List findAll() { - return boards.entrySet().stream() - .map(it -> { - Board board = it.getValue(); - board.setId(it.getKey()); - return board; - }).toList(); - } - - @Override - public Board findById(Long id) { - return boards.getOrDefault(id, null); - } - - @Override - public Board insert(Board board) { - boards.put(autoincrement.getAndIncrement(), board); - return board; - } - - @Override - public void deleteById(Long id) { - boards.remove(id); - } - - @Override - public Board update(Board board) { - return boards.put(board.getId(), board); - } -} diff --git a/src/main/java/com/example/demo/repository/MemberRepository.java b/src/main/java/com/example/demo/repository/MemberRepository.java index 8e2ad14..0771b44 100644 --- a/src/main/java/com/example/demo/repository/MemberRepository.java +++ b/src/main/java/com/example/demo/repository/MemberRepository.java @@ -1,18 +1,9 @@ package com.example.demo.repository; -import java.util.List; - import com.example.demo.domain.Member; -public interface MemberRepository { - - List findAll(); - - Member findById(Long id); - - Member insert(Member member); +import org.springframework.data.jpa.repository.JpaRepository; - Member update(Member member); +public interface MemberRepository extends JpaRepository { - void deleteById(Long id); } diff --git a/src/main/java/com/example/demo/repository/MemberRepositoryJpa.java b/src/main/java/com/example/demo/repository/MemberRepositoryJpa.java deleted file mode 100644 index fd21367..0000000 --- a/src/main/java/com/example/demo/repository/MemberRepositoryJpa.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.example.demo.repository; - -import java.util.List; - -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; -import jakarta.transaction.Transactional; - -import org.springframework.stereotype.Repository; - -import com.example.demo.domain.Member; - -@Repository -public class MemberRepositoryJpa implements MemberRepository { - - @PersistenceContext - private EntityManager em; - - @Override - @Transactional - public Member insert(Member member) { - em.persist(member); - return member; - } - - @Override - @Transactional - public List findAll() { - String jpql = "SELECT m FROM Member m"; - return em.createQuery(jpql, Member.class).getResultList(); - } - - @Override - @Transactional - public Member findById(Long id) { - return em.find(Member.class, id); - } - - @Override - @Transactional - public Member update(Member member) { - em.merge(member); - return member; - } - - @Override - @Transactional - public void deleteById(Long id) { - em.remove(findById(id)); - } -} diff --git a/src/main/java/com/example/demo/repository/MemberRepositoryMemory.java b/src/main/java/com/example/demo/repository/MemberRepositoryMemory.java deleted file mode 100644 index b4cf722..0000000 --- a/src/main/java/com/example/demo/repository/MemberRepositoryMemory.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.example.demo.repository; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; - -import com.example.demo.domain.Member; - -public class MemberRepositoryMemory implements MemberRepository { - - private static final Map members = new HashMap<>(); - private static final AtomicLong autoincrement = new AtomicLong(1); - - static { - // 1번 유저를 미리 만들어둔다. - members.put(autoincrement.getAndIncrement(), new Member("최준호", "temp@gmail.com", "password")); - } - - @Override - public List findAll() { - return members.entrySet().stream() - .map(it -> { - Member member = it.getValue(); - member.setId(it.getKey()); - return member; - }).toList(); - } - - @Override - public Member findById(Long id) { - return members.getOrDefault(id, null); - } - - @Override - public Member insert(Member member) { - long id = autoincrement.getAndIncrement(); - members.put(id, member); - member.setId(id); - return member; - } - - @Override - public Member update(Member member) { - return members.put(member.getId(), member); - } - - @Override - public void deleteById(Long id) { - members.remove(id); - } -} diff --git a/src/main/java/com/example/demo/service/ArticleService.java b/src/main/java/com/example/demo/service/ArticleService.java index d0c1b9d..5a291bd 100644 --- a/src/main/java/com/example/demo/service/ArticleService.java +++ b/src/main/java/com/example/demo/service/ArticleService.java @@ -2,19 +2,18 @@ import java.util.List; -import com.example.demo.exception.ArticleNotFoundException; -import com.example.demo.exception.BoardNotExistException; -import com.example.demo.exception.MemberNotExistException; -import com.example.demo.exception.RequestNullExistException; +import com.example.demo.exception.*; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.example.demo.controller.dto.request.ArticleCreateRequest; import com.example.demo.controller.dto.response.ArticleResponse; import com.example.demo.controller.dto.request.ArticleUpdateRequest; + import com.example.demo.domain.Article; import com.example.demo.domain.Board; import com.example.demo.domain.Member; + import com.example.demo.repository.ArticleRepository; import com.example.demo.repository.BoardRepository; import com.example.demo.repository.MemberRepository; @@ -38,23 +37,11 @@ public ArticleService( } public ArticleResponse getById(Long id) { - Article article = articleRepository.findById(id); - - if (article == null) { - throw new ArticleNotFoundException(); - } + Article article = articleRepository.findById(id).orElseThrow(ArticleNotFoundException::new); - Member member = memberRepository.findById(article.getAuthorId()); + Member member = memberRepository.findById(article.getAuthorId()).orElseThrow(MemberNotExistException::new); - if (member == null) { - throw new MemberNotExistException(); - } - - Board board = boardRepository.findById(article.getBoardId()); - - if(board == null) { - throw new BoardNotExistException(); - } + Board board = boardRepository.findById(article.getBoardId()).orElseThrow(BoardNotExistException::new); return ArticleResponse.of(article, member, board); } @@ -63,8 +50,8 @@ public List getByBoardId(Long boardId) { List
articles = articleRepository.findAllByBoardId(boardId); return articles.stream() .map(article -> { - Member member = memberRepository.findById(article.getAuthorId()); - Board board = boardRepository.findById(article.getBoardId()); + Member member = memberRepository.findById(article.getAuthorId()).orElseThrow(MemberNotExistException::new); + Board board = boardRepository.findById(article.getBoardId()).orElseThrow(BoardNotExistException::new); return ArticleResponse.of(article, member, board); }) .toList(); @@ -83,38 +70,22 @@ public ArticleResponse create(ArticleCreateRequest request) { throw new RequestNullExistException(); } - Member member = memberRepository.findById(request.authorId()); + Member member = memberRepository.findById(request.authorId()).orElseThrow(MemberNotExistException::new); - if (member == null) { - throw new MemberNotExistException(); - } - - Board board = boardRepository.findById(request.boardId()); - - if(board == null) { - throw new BoardNotExistException(); - } + Board board = boardRepository.findById(request.boardId()).orElseThrow(BoardNotExistException::new); - Article saved = articleRepository.insert(article); + Article saved = articleRepository.save(article); return ArticleResponse.of(saved, member, board); } @Transactional public ArticleResponse update(Long id, ArticleUpdateRequest request) { - Article article = articleRepository.findById(id); + Article article = articleRepository.findById(id).orElseThrow(ArticleNotFoundException::new); - Member member = memberRepository.findById(request.authorId()); + Member member = memberRepository.findById(request.authorId()).orElseThrow(MemberNotExistException::new); - if (member == null) { - throw new MemberNotExistException(); - } - - Board board = boardRepository.findById(request.boardId()); - - if(board == null) { - throw new BoardNotExistException(); - } + Board board = boardRepository.findById(request.boardId()).orElseThrow(BoardNotExistException::new); article.update(request.boardId(), request.title(), request.description()); return ArticleResponse.of(article, member, board); diff --git a/src/main/java/com/example/demo/service/BoardService.java b/src/main/java/com/example/demo/service/BoardService.java index f6e47a8..a17290f 100644 --- a/src/main/java/com/example/demo/service/BoardService.java +++ b/src/main/java/com/example/demo/service/BoardService.java @@ -4,17 +4,21 @@ import java.util.Objects; import com.example.demo.domain.Article; + import com.example.demo.exception.BoardHasArticleException; import com.example.demo.exception.BoardNotExistException; import com.example.demo.exception.BoardNotFoundException; import com.example.demo.exception.RequestNullExistException; + import com.example.demo.repository.ArticleRepository; + import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.example.demo.controller.dto.request.BoardCreateRequest; import com.example.demo.controller.dto.request.BoardUpdateRequest; import com.example.demo.controller.dto.response.BoardResponse; + import com.example.demo.domain.Board; import com.example.demo.repository.BoardRepository; @@ -37,12 +41,7 @@ public List getBoards() { } public BoardResponse getBoardById(Long id) { - Board board = boardRepository.findById(id); - - if(board == null) { - throw new BoardNotFoundException(); - } - + Board board = boardRepository.findById(id).orElseThrow(BoardNotFoundException::new); return BoardResponse.from(board); } @@ -54,7 +53,7 @@ public BoardResponse createBoard(BoardCreateRequest request) { throw new RequestNullExistException(); } - Board saved = boardRepository.insert(board); + Board saved = boardRepository.save(board); return BoardResponse.from(saved); } @@ -72,14 +71,10 @@ public void deleteBoard(Long id) { @Transactional public BoardResponse update(Long id, BoardUpdateRequest request) { - Board board = boardRepository.findById(id); - - if (board == null) { - throw new BoardNotExistException(); - } + Board board = boardRepository.findById(id).orElseThrow(BoardNotExistException::new); board.update(request.name()); - Board updated = boardRepository.update(board); + Board updated = boardRepository.save(board); return BoardResponse.from(updated); } } diff --git a/src/main/java/com/example/demo/service/MemberService.java b/src/main/java/com/example/demo/service/MemberService.java index 86442cd..52d7919 100644 --- a/src/main/java/com/example/demo/service/MemberService.java +++ b/src/main/java/com/example/demo/service/MemberService.java @@ -6,12 +6,14 @@ import com.example.demo.domain.Article; import com.example.demo.exception.*; import com.example.demo.repository.ArticleRepository; + import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.example.demo.controller.dto.request.MemberCreateRequest; import com.example.demo.controller.dto.request.MemberUpdateRequest; import com.example.demo.controller.dto.response.MemberResponse; + import com.example.demo.domain.Member; import com.example.demo.repository.MemberRepository; @@ -28,11 +30,7 @@ public MemberService(ArticleRepository articleRepository, MemberRepository membe } public MemberResponse getById(Long id) { - Member member = memberRepository.findById(id); - - if (member == null) { - throw new MemberNotFoundException(); - } + Member member = memberRepository.findById(id).orElseThrow(MemberNotFoundException::new); return MemberResponse.from(member); } @@ -45,7 +43,7 @@ public List getAll() { @Transactional public MemberResponse create(MemberCreateRequest request) { - Member member = memberRepository.insert( + Member member = memberRepository.save( new Member(request.name(), request.email(), request.password()) ); @@ -69,11 +67,7 @@ public void delete(Long id) { @Transactional public MemberResponse update(Long id, MemberUpdateRequest request) { - Member member = memberRepository.findById(id); - - if (member == null) { - throw new MemberNotExistException(); - } + Member member = memberRepository.findById(id).orElseThrow(MemberNotExistException::new); boolean emailExists = memberRepository.findAll().stream() .anyMatch(m -> member.getEmail().equals(m.getEmail())); @@ -83,7 +77,7 @@ public MemberResponse update(Long id, MemberUpdateRequest request) { } member.update(request.name(), request.email()); - memberRepository.update(member); + memberRepository.save(member); return MemberResponse.from(member); } } diff --git a/src/test/java/com/example/demo/DemoApplicationTests.java b/src/test/java/com/example/demo/DemoApplicationTests.java deleted file mode 100644 index 2778a6a..0000000 --- a/src/test/java/com/example/demo/DemoApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.demo; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class DemoApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/src/test/java/com/example/demo/repository/ArticleRepositoryJpaTest.java b/src/test/java/com/example/demo/repository/ArticleRepositoryJpaTest.java deleted file mode 100644 index e8fd6f3..0000000 --- a/src/test/java/com/example/demo/repository/ArticleRepositoryJpaTest.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.example.demo.repository; - -import com.example.demo.domain.Article; - -import jakarta.transaction.Transactional; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; - -import java.time.LocalDateTime; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -@SpringBootTest -@Transactional -class ArticleRepositoryJpaTest { - - private final ArticleRepositoryJpa articleRepository; - - @Autowired - public ArticleRepositoryJpaTest(ArticleRepositoryJpa articleRepository) { - this.articleRepository = articleRepository; - } - - private Article article; - - @BeforeEach - void setUp() { - article = new Article(null, 1L, 1L, "New Title", "New Content", LocalDateTime.now(), LocalDateTime.now()); - } - - @Test - @DisplayName("게시물이 생성되는지 확인하는 테스트") - void insert() { - //Given - Article savedArticle = articleRepository.insert(article); - //When - assertNotNull(savedArticle.getId()); - //Then - assertEquals(article.getTitle(), savedArticle.getTitle()); - assertEquals(article.getContent(), savedArticle.getContent()); - assertNotNull(savedArticle.getCreatedAt()); - assertNotNull(savedArticle.getModifiedAt()); - } - - @Test - @DisplayName("게시물이 모두 찾아지는지 확인하는 테스트") - void findAll() { - //Given - List
articles = articleRepository.findAll(); - //When - assertFalse(articles.isEmpty()); - //Then - assertEquals(16, articles.size()); - } - - @Test - @DisplayName("특정 게시물이 찾아지는지 확인하는 테스트") - void findById() { - //Given - Article foundArticle = articleRepository.findById(1L); - //When - assertNotNull(foundArticle); - //Then - assertEquals(1L, foundArticle.getId()); - assertEquals("자그레우스", foundArticle.getTitle()); - assertEquals("Hades의 주인공", foundArticle.getContent()); - } - - @Test - @DisplayName("특정 게시물이 수정되는지 확인하는 테스트") - void update() { - //Given - Article savedArticle = articleRepository.insert(article); - //When - savedArticle.update(2L, "Updated Title", "Updated Content"); - Article updatedArticle = articleRepository.update(savedArticle); - //Then - assertEquals("Updated Title", updatedArticle.getTitle()); - assertEquals("Updated Content", updatedArticle.getContent()); - assertEquals(2L, updatedArticle.getBoardId()); - assertNotNull(updatedArticle.getModifiedAt()); - assertTrue(updatedArticle.getModifiedAt().isAfter(updatedArticle.getCreatedAt())); - } - - @Test - @DisplayName("특정 게시물이 삭제되는지 확인하는 테스트") - void deleteById() { - //Given - Article savedArticle = articleRepository.insert(article); - //When - articleRepository.deleteById(savedArticle.getId()); - Article deletedArticle = articleRepository.findById(savedArticle.getId()); - //Then - assertNull(deletedArticle); - } -} \ No newline at end of file diff --git a/src/test/java/com/example/demo/repository/BoardRepositoryJpaTest.java b/src/test/java/com/example/demo/repository/BoardRepositoryJpaTest.java deleted file mode 100644 index fc5a459..0000000 --- a/src/test/java/com/example/demo/repository/BoardRepositoryJpaTest.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.example.demo.repository; - -import com.example.demo.domain.Board; - -import jakarta.transaction.Transactional; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; - -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -@SpringBootTest -@Transactional -class BoardRepositoryJpaTest { - - private final BoardRepositoryJpa boardRepository; - - @Autowired - public BoardRepositoryJpaTest(BoardRepositoryJpa boardRepository) { - this.boardRepository = boardRepository; - } - - private Board board; - - @BeforeEach - void setUp() { - board = new Board(null,"new board"); - } - - @Test - @DisplayName("게시판이 생성되는지 확인하는 테스트") - void insert() { - //Given - Board savedBoard = boardRepository.insert(board); - //When - assertNotNull(savedBoard.getId()); - //Then - assertEquals(board.getName(), savedBoard.getName()); - } - - @Test - @DisplayName("게시판이 모두 찾아지는지 확인하는 테스트") - void findAll() { - //Given - List boards = boardRepository.findAll(); - //When - assertFalse(boards.isEmpty()); - //Then - assertEquals(5, boards.size()); - } - - @Test - @DisplayName("특정 게시판이 찾아지는지 확인하는 테스트") - void findById() { - //Given - Board foundBoard = boardRepository.findById(1L); - //When - assertNotNull(foundBoard); - //Then - assertEquals(1L, foundBoard.getId()); - assertEquals("하데스", foundBoard.getName()); - } - - @Test - @DisplayName("특정 게시판이 수정되는지 확인하는 테스트") - void update() { - //Given - Board savedBoard = boardRepository.insert(board); - //When - savedBoard.update("수정된 게시판1"); - Board updatedBoard = boardRepository.update(savedBoard); - //Then - assertEquals("수정된 게시판1", updatedBoard.getName()); - } - - @Test - @DisplayName("특정 게시판이 삭제되는지 확인하는 테스트") - void deleteById() { - //Given - Board savedBoard = boardRepository.insert(board); - //When - boardRepository.deleteById(savedBoard.getId()); - Board deletedBoard = boardRepository.findById(savedBoard.getId()); - //Then - assertNull(deletedBoard); - } -} \ No newline at end of file diff --git a/src/test/java/com/example/demo/service/BoardServiceTest.java b/src/test/java/com/example/demo/service/BoardServiceTest.java new file mode 100644 index 0000000..1aeb8d7 --- /dev/null +++ b/src/test/java/com/example/demo/service/BoardServiceTest.java @@ -0,0 +1,87 @@ +package com.example.demo.service; + +import com.example.demo.domain.Article; +import com.example.demo.domain.Board; +import com.example.demo.repository.ArticleRepository; +import com.example.demo.repository.BoardRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@DataJpaTest +public class BoardServiceTest { + + @Autowired + private BoardRepository boardRepository; + + @Autowired + private ArticleRepository articleRepository; + + private Board board; + + @BeforeEach + void setUp() { + board = new Board("Test Board"); + } + + @Test + @Transactional + void testCascadePersist() { + Article article1 = new Article(null, 1L, 1L, "Title1", "Content1", LocalDateTime.now(), LocalDateTime.now()); + Article article2 = new Article(null, 2L, 1L, "Title2", "Content2", LocalDateTime.now(), LocalDateTime.now()); + board.getArticles().add(article1); + board.getArticles().add(article2); + article1.setBoard(board); + article2.setBoard(board); + + boardRepository.save(board); + + List
articles = articleRepository.findAll(); + + assertThat(articles).hasSize(2); + assertThat(articles.get(0).getBoard().getName()).isEqualTo("Test Board"); + assertThat(articles.get(1).getBoard().getName()).isEqualTo("Test Board"); + } + + @Test + @Transactional + void testCascadeUpdate() { + Article article = new Article(null, 1L, 1L, "Title", "Content", LocalDateTime.now(), LocalDateTime.now()); + board.getArticles().add(article); + article.setBoard(board); + + boardRepository.save(board); + + board.setName("Updated Board"); + article.setTitle("Updated Title"); + boardRepository.save(board); + + Board updatedBoard = boardRepository.findById(board.getId()).get(); + Article updatedArticle = articleRepository.findById(article.getId()).get(); + + assertThat(updatedBoard.getName()).isEqualTo("Updated Board"); + assertThat(updatedArticle.getTitle()).isEqualTo("Updated Title"); + } + + @Test + @Transactional + void testCascadeRemove() { + Article article = new Article(null, 1L, 1L, "Title", "Content", LocalDateTime.now(), LocalDateTime.now()); + board.getArticles().add(article); + article.setBoard(board); + + boardRepository.save(board); + + boardRepository.delete(board); + + List
articles = articleRepository.findAll(); + assertThat(articles).isEmpty(); + } +} From 378413fdbc12b2b9f38a7a649aa8d6cf5c8bb3c9 Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Mon, 1 Jul 2024 21:38:41 +0900 Subject: [PATCH 21/22] =?UTF-8?q?refactor:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20Test=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/demo/DemoApplicationTests.java | 13 +++ .../repository/MemberRepositoryJpaTest.java | 95 ------------------- .../demo/service/BoardServiceTest.java | 87 ----------------- 3 files changed, 13 insertions(+), 182 deletions(-) create mode 100644 src/test/java/com/example/demo/DemoApplicationTests.java delete mode 100644 src/test/java/com/example/demo/repository/MemberRepositoryJpaTest.java delete mode 100644 src/test/java/com/example/demo/service/BoardServiceTest.java diff --git a/src/test/java/com/example/demo/DemoApplicationTests.java b/src/test/java/com/example/demo/DemoApplicationTests.java new file mode 100644 index 0000000..2778a6a --- /dev/null +++ b/src/test/java/com/example/demo/DemoApplicationTests.java @@ -0,0 +1,13 @@ +package com.example.demo; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class DemoApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/src/test/java/com/example/demo/repository/MemberRepositoryJpaTest.java b/src/test/java/com/example/demo/repository/MemberRepositoryJpaTest.java deleted file mode 100644 index d9430c1..0000000 --- a/src/test/java/com/example/demo/repository/MemberRepositoryJpaTest.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.example.demo.repository; - -import com.example.demo.domain.Member; -import jakarta.transaction.Transactional; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; - -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -@SpringBootTest -@Transactional -class MemberRepositoryJpaTest { - - private final MemberRepositoryJpa memberRepository; - - @Autowired - public MemberRepositoryJpaTest(MemberRepositoryJpa memberRepository) { - this.memberRepository = memberRepository; - } - - private Member member; - - @BeforeEach - void setUp() { - member = new Member("user7", "member7@gmail.com", "password7"); - } - - @Test - @DisplayName("회원이 생성되는지 확인하는 테스트") - void insert() { - //Given - Member savedMember = memberRepository.insert(member); - //When - assertNotNull(savedMember.getId()); - //Then - assertEquals(member.getName(), savedMember.getName()); - assertEquals(member.getEmail(), savedMember.getEmail()); - assertEquals(member.getPassword(), savedMember.getPassword()); - } - - @Test - @DisplayName("회원이 모두 찾아지는지 확인하는 테스트") - void findAll() { - //Given - List members = memberRepository.findAll(); - //When - assertFalse(members.isEmpty()); - //Then - assertEquals(6, members.size()); - } - - @Test - @DisplayName("특정 회원이 찾아지는지 확인하는 테스트") - void findById() { - //Given - Member foundMember = memberRepository.findById(1L); - //When - assertNotNull(foundMember); - //Then - assertEquals(1L, foundMember.getId()); - assertEquals("user1", foundMember.getName()); - assertEquals("user1@gmail.com", foundMember.getEmail()); - assertEquals("password1", foundMember.getPassword()); - } - - @Test - @DisplayName("특정 회원이 수정되는지 확인하는 테스트") - void update() { - //Given - Member savedMember = memberRepository.insert(member); - //When - savedMember.update("User1", "User1@gmail.com"); - Member updatedMember = memberRepository.update(savedMember); - //Then - assertEquals("User1", updatedMember.getName()); - assertEquals("User1@gmail.com", updatedMember.getEmail()); - } - - @Test - @DisplayName("특정 게시판이 삭제되는지 확인하는 테스트") - void deleteById() { - //Given - Member savedMember = memberRepository.insert(member); - //When - memberRepository.deleteById(savedMember.getId()); - Member deletedMember = memberRepository.findById(savedMember.getId()); - //Then - assertNull(deletedMember); - } -} \ No newline at end of file diff --git a/src/test/java/com/example/demo/service/BoardServiceTest.java b/src/test/java/com/example/demo/service/BoardServiceTest.java deleted file mode 100644 index 1aeb8d7..0000000 --- a/src/test/java/com/example/demo/service/BoardServiceTest.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.example.demo.service; - -import com.example.demo.domain.Article; -import com.example.demo.domain.Board; -import com.example.demo.repository.ArticleRepository; -import com.example.demo.repository.BoardRepository; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - -@DataJpaTest -public class BoardServiceTest { - - @Autowired - private BoardRepository boardRepository; - - @Autowired - private ArticleRepository articleRepository; - - private Board board; - - @BeforeEach - void setUp() { - board = new Board("Test Board"); - } - - @Test - @Transactional - void testCascadePersist() { - Article article1 = new Article(null, 1L, 1L, "Title1", "Content1", LocalDateTime.now(), LocalDateTime.now()); - Article article2 = new Article(null, 2L, 1L, "Title2", "Content2", LocalDateTime.now(), LocalDateTime.now()); - board.getArticles().add(article1); - board.getArticles().add(article2); - article1.setBoard(board); - article2.setBoard(board); - - boardRepository.save(board); - - List
articles = articleRepository.findAll(); - - assertThat(articles).hasSize(2); - assertThat(articles.get(0).getBoard().getName()).isEqualTo("Test Board"); - assertThat(articles.get(1).getBoard().getName()).isEqualTo("Test Board"); - } - - @Test - @Transactional - void testCascadeUpdate() { - Article article = new Article(null, 1L, 1L, "Title", "Content", LocalDateTime.now(), LocalDateTime.now()); - board.getArticles().add(article); - article.setBoard(board); - - boardRepository.save(board); - - board.setName("Updated Board"); - article.setTitle("Updated Title"); - boardRepository.save(board); - - Board updatedBoard = boardRepository.findById(board.getId()).get(); - Article updatedArticle = articleRepository.findById(article.getId()).get(); - - assertThat(updatedBoard.getName()).isEqualTo("Updated Board"); - assertThat(updatedArticle.getTitle()).isEqualTo("Updated Title"); - } - - @Test - @Transactional - void testCascadeRemove() { - Article article = new Article(null, 1L, 1L, "Title", "Content", LocalDateTime.now(), LocalDateTime.now()); - board.getArticles().add(article); - article.setBoard(board); - - boardRepository.save(board); - - boardRepository.delete(board); - - List
articles = articleRepository.findAll(); - assertThat(articles).isEmpty(); - } -} From 01f368ba3133db63e4ffd14a520ce15ec351780c Mon Sep 17 00:00:00 2001 From: jabell0310 Date: Wed, 10 Jul 2024 09:01:14 +0900 Subject: [PATCH 22/22] =?UTF-8?q?error:=20=EC=98=A4=EB=A5=98=20=EB=AF=B8?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 + .../example/demo/config/SecurityConfig.java | 54 +++++++++++++++++ .../demo/controller/SignController.java | 59 +++++++++++++++++++ .../demo/controller/dto/MemberDetails.java | 57 ++++++++++++++++++ .../dto/response/MemberResponse.java | 4 +- .../java/com/example/demo/domain/Member.java | 21 ++++--- .../demo/repository/MemberRepository.java | 5 ++ .../demo/service/MemberDetailsService.java | 36 +++++++++++ .../example/demo/service/MemberService.java | 23 +++++--- src/main/resources/application.yml | 3 +- src/main/resources/templates/admin.html | 18 ++++++ src/main/resources/templates/home.html | 18 ++++++ src/main/resources/templates/signin.html | 43 ++++++++++++++ src/main/resources/templates/signup.html | 47 +++++++++++++++ 14 files changed, 372 insertions(+), 18 deletions(-) create mode 100644 src/main/java/com/example/demo/config/SecurityConfig.java create mode 100644 src/main/java/com/example/demo/controller/SignController.java create mode 100644 src/main/java/com/example/demo/controller/dto/MemberDetails.java create mode 100644 src/main/java/com/example/demo/service/MemberDetailsService.java create mode 100644 src/main/resources/templates/admin.html create mode 100644 src/main/resources/templates/home.html create mode 100644 src/main/resources/templates/signin.html create mode 100644 src/main/resources/templates/signup.html diff --git a/build.gradle b/build.gradle index a4e1ef9..6815fc3 100644 --- a/build.gradle +++ b/build.gradle @@ -25,6 +25,8 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-aop' + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6' } tasks.named('test') { diff --git a/src/main/java/com/example/demo/config/SecurityConfig.java b/src/main/java/com/example/demo/config/SecurityConfig.java new file mode 100644 index 0000000..f106f42 --- /dev/null +++ b/src/main/java/com/example/demo/config/SecurityConfig.java @@ -0,0 +1,54 @@ +package com.example.demo.config; + +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; + + +@Configuration +@EnableWebSecurity +@RequiredArgsConstructor +public class SecurityConfig { + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + http + .authorizeHttpRequests((auth) -> auth + .requestMatchers("/members/home","/members/register","/members/signup", "/members/view","/members/signin").permitAll() + .requestMatchers("/members/admin").hasRole("ADMIN") + .requestMatchers("/my/**").hasAnyRole("ADMIN", "USER") + .anyRequest().authenticated() + ); + + http + .formLogin((auth) -> auth.loginPage("/members/signin") + .loginProcessingUrl("/members/view") + .permitAll() + ); + + http + .csrf(AbstractHttpConfigurer::disable); + + http + .sessionManagement((auth)-> auth + .maximumSessions(1) + .maxSessionsPreventsLogin(true)); + + http + .sessionManagement((auth)-> auth + .sessionFixation().changeSessionId()); + + return http.build(); + } + + @Bean + public BCryptPasswordEncoder bCryptPasswordEncoder() { + return new BCryptPasswordEncoder(); + } + +} diff --git a/src/main/java/com/example/demo/controller/SignController.java b/src/main/java/com/example/demo/controller/SignController.java new file mode 100644 index 0000000..4492ea7 --- /dev/null +++ b/src/main/java/com/example/demo/controller/SignController.java @@ -0,0 +1,59 @@ +package com.example.demo.controller; + +import com.example.demo.controller.dto.request.MemberCreateRequest; +import com.example.demo.controller.dto.response.MemberResponse; +import com.example.demo.service.MemberService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; + +@Controller +public class SignController { + + private final MemberService memberService; + + @Autowired + public SignController(MemberService memberService) { + this.memberService = memberService; + } + + @PostMapping("/members/register") + public String register(MemberCreateRequest request) { + MemberResponse response = memberService.create(request); + ResponseEntity.ok(response); + return "redirect:/members/signin"; + } + + @PostMapping("/members/view") + public String login() { + return "redirect:/members/home"; + } + + @GetMapping("/members/signup") + public String signUp() { + return "signup"; + } + + @GetMapping("/members/signin") + public String signIn() { + return "signin"; + } + + @GetMapping("/members/home") + public String home(Model model) { + String id = SecurityContextHolder.getContext().getAuthentication().getName(); + + model.addAttribute("id", id); + return "home"; + } + + @GetMapping("/members/admin") + public String admin() { + return "admin"; + } + +} diff --git a/src/main/java/com/example/demo/controller/dto/MemberDetails.java b/src/main/java/com/example/demo/controller/dto/MemberDetails.java new file mode 100644 index 0000000..9900d86 --- /dev/null +++ b/src/main/java/com/example/demo/controller/dto/MemberDetails.java @@ -0,0 +1,57 @@ +package com.example.demo.controller.dto; + +import com.example.demo.domain.Member; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.ArrayList; +import java.util.Collection; + +public class MemberDetails implements UserDetails { + + private final Member member; + + + public MemberDetails(Member member) { + this.member = member; + } + + @Override + public Collection getAuthorities() { + Collection collection = new ArrayList<>(); + + collection.add((GrantedAuthority) member::getRole); + + return collection; + } + + @Override + public String getPassword() { + return member.getPassword(); + } + + @Override + public String getUsername() { + return member.getUsername(); + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } +} diff --git a/src/main/java/com/example/demo/controller/dto/response/MemberResponse.java b/src/main/java/com/example/demo/controller/dto/response/MemberResponse.java index f79aeb6..48cdb29 100644 --- a/src/main/java/com/example/demo/controller/dto/response/MemberResponse.java +++ b/src/main/java/com/example/demo/controller/dto/response/MemberResponse.java @@ -4,12 +4,12 @@ public record MemberResponse( Long id, - String name, + String username, String email ) { public static MemberResponse from(Member member) { - return new MemberResponse(member.getId(), member.getName(), member.getEmail()); + return new MemberResponse(member.getId(), member.getUsername(), member.getEmail()); } } diff --git a/src/main/java/com/example/demo/domain/Member.java b/src/main/java/com/example/demo/domain/Member.java index 1fca74a..5353002 100644 --- a/src/main/java/com/example/demo/domain/Member.java +++ b/src/main/java/com/example/demo/domain/Member.java @@ -16,8 +16,8 @@ public class Member { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(name = "name", nullable = false) - private String name; + @Column(name = "username", nullable = false, unique = true) + private String username; @Column(name = "email", nullable = false) private String email; @@ -25,21 +25,26 @@ public class Member { @Column(name = "password", nullable = false) private String password; - public Member(Long id, String name, String email, String password) { + @Column(name = "role", nullable = false) + private String role; + + public Member(Long id, String username, String email, String password, String role) { this.id = id; - this.name = name; + this.username = username; this.email = email; this.password = password; + this.role = role; } - public Member(String name, String email, String password) { - this.name = name; + public Member(String username, String email, String password, String role) { + this.username = username; this.email = email; this.password = password; + this.role = role; } - public void update(String name, String email) { - this.name = name; + public void update(String username, String email) { + this.username = username; this.email = email; } diff --git a/src/main/java/com/example/demo/repository/MemberRepository.java b/src/main/java/com/example/demo/repository/MemberRepository.java index 0771b44..50ed367 100644 --- a/src/main/java/com/example/demo/repository/MemberRepository.java +++ b/src/main/java/com/example/demo/repository/MemberRepository.java @@ -3,7 +3,12 @@ import com.example.demo.domain.Member; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.Optional; public interface MemberRepository extends JpaRepository { + boolean existsByEmail(String email); + Member findMemberByUsername(String username); } diff --git a/src/main/java/com/example/demo/service/MemberDetailsService.java b/src/main/java/com/example/demo/service/MemberDetailsService.java new file mode 100644 index 0000000..6e8d149 --- /dev/null +++ b/src/main/java/com/example/demo/service/MemberDetailsService.java @@ -0,0 +1,36 @@ +package com.example.demo.service; + +import com.example.demo.controller.dto.MemberDetails; +import com.example.demo.domain.Member; +import com.example.demo.repository.MemberRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; +import org.springframework.web.bind.annotation.PathVariable; + +@Service +public class MemberDetailsService implements UserDetailsService { + + + private final MemberRepository memberRepository; + + + @Autowired + public MemberDetailsService(MemberRepository memberRepository) { + this.memberRepository = memberRepository; + } + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + System.out.println("@@@@" + username); + Member member = memberRepository.findMemberByUsername(username); + System.out.println("@@@@" + member); + if(member != null) { + return new MemberDetails(member); + } + + return null; + } +} diff --git a/src/main/java/com/example/demo/service/MemberService.java b/src/main/java/com/example/demo/service/MemberService.java index 52d7919..3c656d9 100644 --- a/src/main/java/com/example/demo/service/MemberService.java +++ b/src/main/java/com/example/demo/service/MemberService.java @@ -7,6 +7,7 @@ import com.example.demo.exception.*; import com.example.demo.repository.ArticleRepository; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -23,10 +24,12 @@ public class MemberService { private final ArticleRepository articleRepository; private final MemberRepository memberRepository; + private final BCryptPasswordEncoder bCryptPasswordEncoder; - public MemberService(ArticleRepository articleRepository, MemberRepository memberRepository) { + public MemberService(ArticleRepository articleRepository, MemberRepository memberRepository, BCryptPasswordEncoder bCryptPasswordEncoder) { this.articleRepository = articleRepository; this.memberRepository = memberRepository; + this.bCryptPasswordEncoder = bCryptPasswordEncoder; } public MemberResponse getById(Long id) { @@ -43,13 +46,20 @@ public List getAll() { @Transactional public MemberResponse create(MemberCreateRequest request) { + if (request.name() == null || request.email() == null || request.password() == null) { + throw new RequestNullExistException(); + } + + boolean emailExists = memberRepository.existsByEmail(request.email()); + + if (emailExists) { + throw new AlreadyHasEmailException(); + } + Member member = memberRepository.save( - new Member(request.name(), request.email(), request.password()) + new Member(request.name(), request.email(), bCryptPasswordEncoder.encode(request.password()), "ROLE_ADMIN") ); - if (member.getName() == null || member.getEmail() == null || member.getPassword() == null) { - throw new RequestNullExistException(); - } return MemberResponse.from(member); } @@ -69,8 +79,7 @@ public void delete(Long id) { public MemberResponse update(Long id, MemberUpdateRequest request) { Member member = memberRepository.findById(id).orElseThrow(MemberNotExistException::new); - boolean emailExists = memberRepository.findAll().stream() - .anyMatch(m -> member.getEmail().equals(m.getEmail())); + boolean emailExists = memberRepository.existsByEmail(request.email()); if (emailExists) { throw new AlreadyHasEmailException(); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index c13ca95..4868267 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -11,4 +11,5 @@ spring: show-sql: true - + session: + timeout: 1800s diff --git a/src/main/resources/templates/admin.html b/src/main/resources/templates/admin.html new file mode 100644 index 0000000..2299033 --- /dev/null +++ b/src/main/resources/templates/admin.html @@ -0,0 +1,18 @@ + + + + + 메인화면 + + + + + +

메인 화면

+

로그인 상태

+ + \ No newline at end of file diff --git a/src/main/resources/templates/home.html b/src/main/resources/templates/home.html new file mode 100644 index 0000000..f96e8af --- /dev/null +++ b/src/main/resources/templates/home.html @@ -0,0 +1,18 @@ + + + + + 메인화면 + + + + + +

메인 화면

+

로그인 상태

+ + \ No newline at end of file diff --git a/src/main/resources/templates/signin.html b/src/main/resources/templates/signin.html new file mode 100644 index 0000000..f60e619 --- /dev/null +++ b/src/main/resources/templates/signin.html @@ -0,0 +1,43 @@ + + + + + 로그인 + + + + + +
+
+
+
+

LOGIN

+

서비스를 사용하려면 로그인을 해주세요!

+ +
+
+ +
+ + +
+
+ + +
+ +
+ + +
+
+
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/signup.html b/src/main/resources/templates/signup.html new file mode 100644 index 0000000..aa48dcf --- /dev/null +++ b/src/main/resources/templates/signup.html @@ -0,0 +1,47 @@ + + + + + 회원 가입 + + + + + +
+
+
+
+

SIGN UP

+

서비스 사용을 위한 회원 가입

+ +
+
+ + +
+ + +
+
+ + +
+
+ + +
+ + +
+
+
+
+
+
+ + \ No newline at end of file