From b1dbd49c5f38b1a05e281eda79680bb509264fc1 Mon Sep 17 00:00:00 2001 From: scholar-star Date: Mon, 6 Oct 2025 22:22:44 +0900 Subject: [PATCH 01/22] =?UTF-8?q?Controller,=20Service,=20Repository=20?= =?UTF-8?q?=EA=B8=B0=EC=B4=88=20=EC=9E=91=EC=97=85=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 + .../com/example/devSns/DevSnsApplication.java | 1 - src/main/java/controllers/PostController.java | 48 ++++++++++++ src/main/java/dto/Post.java | 7 ++ src/main/java/dto/PostResponse.java | 15 ++++ src/main/java/entities/Posts.java | 33 +++++++++ .../java/repositories/PostRepository.java | 11 +++ src/main/java/services/PostService.java | 74 +++++++++++++++++++ 8 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 src/main/java/controllers/PostController.java create mode 100644 src/main/java/dto/Post.java create mode 100644 src/main/java/dto/PostResponse.java create mode 100644 src/main/java/entities/Posts.java create mode 100644 src/main/java/repositories/PostRepository.java create mode 100644 src/main/java/services/PostService.java diff --git a/build.gradle b/build.gradle index 610d6a6..d08dbea 100644 --- a/build.gradle +++ b/build.gradle @@ -20,6 +20,8 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } diff --git a/src/main/java/com/example/devSns/DevSnsApplication.java b/src/main/java/com/example/devSns/DevSnsApplication.java index b965724..4a30ad0 100644 --- a/src/main/java/com/example/devSns/DevSnsApplication.java +++ b/src/main/java/com/example/devSns/DevSnsApplication.java @@ -5,7 +5,6 @@ @SpringBootApplication public class DevSnsApplication { - public static void main(String[] args) { SpringApplication.run(DevSnsApplication.class, args); } diff --git a/src/main/java/controllers/PostController.java b/src/main/java/controllers/PostController.java new file mode 100644 index 0000000..1cb5595 --- /dev/null +++ b/src/main/java/controllers/PostController.java @@ -0,0 +1,48 @@ +package controllers; + +import dto.Post; +import dto.PostResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import services.PostService; + +import java.util.List; + +@RestController +@RequestMapping("/sns") +@RequiredArgsConstructor +public class PostController { + private PostService postService; + + @GetMapping("/show") + public ResponseEntity> showPosts() { + List posts = postService.findAll(); + return new ResponseEntity<>(posts, HttpStatus.OK); + } + + @GetMapping("/show/{username}") + public ResponseEntity showPost(@PathVariable String username) { + PostResponse post = postService.findByUsername(username); + return new ResponseEntity<>(post, HttpStatus.OK); + } + + @PostMapping("/add") + public ResponseEntity addPost(@RequestBody Post post) { + PostResponse postResponse = postService.save(post); + return new ResponseEntity<>(postResponse, HttpStatus.CREATED); + } + + @PutMapping("/update") + public ResponseEntity updatePost(@RequestBody Post post) { + PostResponse postResponse = postService.update(post); + return new ResponseEntity<>(postResponse, HttpStatus.OK); + } + + @DeleteMapping("/delete") + public ResponseEntity deletePost(@RequestBody Post post) { + postService.delete(post); + return new ResponseEntity<>("Post deleted", HttpStatus.OK); + } +} diff --git a/src/main/java/dto/Post.java b/src/main/java/dto/Post.java new file mode 100644 index 0000000..03fad94 --- /dev/null +++ b/src/main/java/dto/Post.java @@ -0,0 +1,7 @@ +package dto; + +public record Post( + Integer id, + String username, + String content +) { } diff --git a/src/main/java/dto/PostResponse.java b/src/main/java/dto/PostResponse.java new file mode 100644 index 0000000..5d756b8 --- /dev/null +++ b/src/main/java/dto/PostResponse.java @@ -0,0 +1,15 @@ +package dto; + +import lombok.*; + +import java.time.LocalDateTime; + +@Builder +public record PostResponse( + Integer id, + String username, + String content, + Integer like, + LocalDateTime createAt, + LocalDateTime updateAt +) {} diff --git a/src/main/java/entities/Posts.java b/src/main/java/entities/Posts.java new file mode 100644 index 0000000..af44592 --- /dev/null +++ b/src/main/java/entities/Posts.java @@ -0,0 +1,33 @@ +package entities; + +import jakarta.persistence.*; +import lombok.*; + +import java.time.LocalDateTime; + +@Entity +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class Posts { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private int id; + + @Column + private String content; + + @Column + private String username; + + @Column + private int likeit; + + @Column + private LocalDateTime createat; + + @Column + private LocalDateTime updateat; +} diff --git a/src/main/java/repositories/PostRepository.java b/src/main/java/repositories/PostRepository.java new file mode 100644 index 0000000..5e7c026 --- /dev/null +++ b/src/main/java/repositories/PostRepository.java @@ -0,0 +1,11 @@ +package repositories; + +import entities.Posts; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface PostRepository extends JpaRepository { + public List findAll(); + public Posts findByUsername(String username); +} diff --git a/src/main/java/services/PostService.java b/src/main/java/services/PostService.java new file mode 100644 index 0000000..b32cb68 --- /dev/null +++ b/src/main/java/services/PostService.java @@ -0,0 +1,74 @@ +package services; + +import dto.Post; +import dto.PostResponse; +import entities.Posts; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import repositories.PostRepository; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +@Service +@RequiredArgsConstructor +public class PostService { + private PostRepository postRepository; + + public Posts dtoToEntity(Post post) { + Posts postEntity = new Posts().builder() + .username(post.username()) + .content(post.content()) + .createat(LocalDateTime.now()) + .build(); + return postEntity; + } + + public PostResponse entityToDto(Posts post) { + return PostResponse.builder() + .username(post.getUsername()) + .content(post.getContent()) + .like(post.getLikeit()) + .createAt(post.getCreateat()) + .updateAt(post.getUpdateat()) + .build(); + } + + @Transactional + public PostResponse save(Post post) { + Posts postEntity = dtoToEntity(post); + postRepository.save(postEntity); + return entityToDto(postEntity); + } + + @Transactional + public List findAll() { + List posts = postRepository.findAll(); + List postResponses = new ArrayList<>(); + for (Posts post : posts) { + postResponses.add(entityToDto(post)); + } + return postResponses; + } + + @Transactional + public PostResponse findByUsername(String username) { + Posts post = postRepository.findByUsername(username); + return entityToDto(post); + } + + @Transactional + public PostResponse update(Post post) { + Posts postEntity = dtoToEntity(post); + postEntity.setUpdateat(LocalDateTime.now()); + postRepository.save(postEntity); + return entityToDto(postEntity); + } + + @Transactional + public void delete(Post post) { + postRepository.delete(dtoToEntity(post)); + } +} From 1e63d38785508b3eba561b265bb3a0cf3892cf9e Mon Sep 17 00:00:00 2001 From: scholar-star Date: Wed, 8 Oct 2025 19:50:00 +0900 Subject: [PATCH 02/22] =?UTF-8?q?CRUD=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 + .../com/example/devSns/DevSnsApplication.java | 2 +- .../devSns}/controllers/PostController.java | 23 +++--- .../example/devSns/dto/PostDTO.java} | 4 +- .../example/devSns}/dto/PostResponse.java | 2 +- .../example/devSns}/entities/Posts.java | 5 +- .../devSns}/repositories/PostRepository.java | 5 +- .../example/devSns/services/PostService.java | 76 +++++++++++++++++++ src/main/java/services/PostService.java | 74 ------------------ src/main/resources/application.properties | 9 +++ 10 files changed, 111 insertions(+), 93 deletions(-) rename src/main/java/{ => com/example/devSns}/controllers/PostController.java (70%) rename src/main/java/{dto/Post.java => com/example/devSns/dto/PostDTO.java} (53%) rename src/main/java/{ => com/example/devSns}/dto/PostResponse.java (87%) rename src/main/java/{ => com/example/devSns}/entities/Posts.java (81%) rename src/main/java/{ => com/example/devSns}/repositories/PostRepository.java (66%) create mode 100644 src/main/java/com/example/devSns/services/PostService.java delete mode 100644 src/main/java/services/PostService.java diff --git a/build.gradle b/build.gradle index d08dbea..1552412 100644 --- a/build.gradle +++ b/build.gradle @@ -21,9 +21,13 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + compileOnly 'org.projectlombok:lombok' + runtimeOnly 'org.postgresql:postgresql' + annotationProcessor 'org.projectlombok:lombok' } tasks.named('test') { diff --git a/src/main/java/com/example/devSns/DevSnsApplication.java b/src/main/java/com/example/devSns/DevSnsApplication.java index 4a30ad0..e30538d 100644 --- a/src/main/java/com/example/devSns/DevSnsApplication.java +++ b/src/main/java/com/example/devSns/DevSnsApplication.java @@ -7,6 +7,6 @@ public class DevSnsApplication { public static void main(String[] args) { SpringApplication.run(DevSnsApplication.class, args); - } + } } diff --git a/src/main/java/controllers/PostController.java b/src/main/java/com/example/devSns/controllers/PostController.java similarity index 70% rename from src/main/java/controllers/PostController.java rename to src/main/java/com/example/devSns/controllers/PostController.java index 1cb5595..bef5379 100644 --- a/src/main/java/controllers/PostController.java +++ b/src/main/java/com/example/devSns/controllers/PostController.java @@ -1,20 +1,19 @@ -package controllers; +package com.example.devSns.controllers; -import dto.Post; -import dto.PostResponse; +import com.example.devSns.dto.PostDTO; +import com.example.devSns.dto.PostResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import services.PostService; - +import com.example.devSns.services.PostService; import java.util.List; @RestController @RequestMapping("/sns") @RequiredArgsConstructor public class PostController { - private PostService postService; + private final PostService postService; @GetMapping("/show") public ResponseEntity> showPosts() { @@ -29,20 +28,20 @@ public ResponseEntity showPost(@PathVariable String username) { } @PostMapping("/add") - public ResponseEntity addPost(@RequestBody Post post) { - PostResponse postResponse = postService.save(post); + public ResponseEntity addPost(@RequestBody PostDTO postDTO) { + PostResponse postResponse = postService.save(postDTO); return new ResponseEntity<>(postResponse, HttpStatus.CREATED); } @PutMapping("/update") - public ResponseEntity updatePost(@RequestBody Post post) { - PostResponse postResponse = postService.update(post); + public ResponseEntity updatePost(@RequestBody PostDTO postDTO) { + PostResponse postResponse = postService.update(postDTO); return new ResponseEntity<>(postResponse, HttpStatus.OK); } @DeleteMapping("/delete") - public ResponseEntity deletePost(@RequestBody Post post) { - postService.delete(post); + public ResponseEntity deletePost(@RequestBody PostDTO postDTO) { + postService.delete(postDTO); return new ResponseEntity<>("Post deleted", HttpStatus.OK); } } diff --git a/src/main/java/dto/Post.java b/src/main/java/com/example/devSns/dto/PostDTO.java similarity index 53% rename from src/main/java/dto/Post.java rename to src/main/java/com/example/devSns/dto/PostDTO.java index 03fad94..612d2e2 100644 --- a/src/main/java/dto/Post.java +++ b/src/main/java/com/example/devSns/dto/PostDTO.java @@ -1,6 +1,6 @@ -package dto; +package com.example.devSns.dto; -public record Post( +public record PostDTO( Integer id, String username, String content diff --git a/src/main/java/dto/PostResponse.java b/src/main/java/com/example/devSns/dto/PostResponse.java similarity index 87% rename from src/main/java/dto/PostResponse.java rename to src/main/java/com/example/devSns/dto/PostResponse.java index 5d756b8..45ab0eb 100644 --- a/src/main/java/dto/PostResponse.java +++ b/src/main/java/com/example/devSns/dto/PostResponse.java @@ -1,4 +1,4 @@ -package dto; +package com.example.devSns.dto; import lombok.*; diff --git a/src/main/java/entities/Posts.java b/src/main/java/com/example/devSns/entities/Posts.java similarity index 81% rename from src/main/java/entities/Posts.java rename to src/main/java/com/example/devSns/entities/Posts.java index af44592..521884f 100644 --- a/src/main/java/entities/Posts.java +++ b/src/main/java/com/example/devSns/entities/Posts.java @@ -1,6 +1,7 @@ -package entities; +package com.example.devSns.entities; import jakarta.persistence.*; +import jakarta.validation.constraints.NotNull; import lombok.*; import java.time.LocalDateTime; @@ -16,9 +17,11 @@ public class Posts { @GeneratedValue(strategy = GenerationType.AUTO) private int id; + @NotNull @Column private String content; + @NotNull @Column private String username; diff --git a/src/main/java/repositories/PostRepository.java b/src/main/java/com/example/devSns/repositories/PostRepository.java similarity index 66% rename from src/main/java/repositories/PostRepository.java rename to src/main/java/com/example/devSns/repositories/PostRepository.java index 5e7c026..a515181 100644 --- a/src/main/java/repositories/PostRepository.java +++ b/src/main/java/com/example/devSns/repositories/PostRepository.java @@ -1,11 +1,12 @@ -package repositories; +package com.example.devSns.repositories; -import entities.Posts; +import com.example.devSns.entities.Posts; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; public interface PostRepository extends JpaRepository { public List findAll(); + public Posts findById(Integer id); public Posts findByUsername(String username); } diff --git a/src/main/java/com/example/devSns/services/PostService.java b/src/main/java/com/example/devSns/services/PostService.java new file mode 100644 index 0000000..e9b10e2 --- /dev/null +++ b/src/main/java/com/example/devSns/services/PostService.java @@ -0,0 +1,76 @@ +package com.example.devSns.services; + +import com.example.devSns.dto.PostDTO; +import com.example.devSns.dto.PostResponse; +import com.example.devSns.entities.Posts; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import com.example.devSns.repositories.PostRepository; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +@Service +@RequiredArgsConstructor +public class PostService { + private final PostRepository postRepository; + + public Posts dtoToEntity(PostDTO postDTO) { + Posts postEntity = Posts.builder() + .username(postDTO.username()) + .content(postDTO.content()) + .build(); + return postEntity; + } + + public PostResponse entityToDto(Posts post) { + return PostResponse.builder() + .id(post.getId()) + .username(post.getUsername()) + .content(post.getContent()) + .like(post.getLikeit()) + .createAt(post.getCreateat()) + .updateAt(post.getUpdateat()) + .build(); + } + + @Transactional // 트랜잭션 보장 + public PostResponse save(PostDTO postDTO) { // post insert + Posts postEntity = dtoToEntity(postDTO); + postEntity.setCreateat(LocalDateTime.now()); + Posts resultEntity = postRepository.save(postEntity); + return entityToDto(resultEntity); + } + + @Transactional + public List findAll() { // 전체 post 조회 + List posts = postRepository.findAll(); + List postResponses = new ArrayList<>(); + for (Posts post : posts) { + postResponses.add(entityToDto(post)); + } + return postResponses; + } + + @Transactional + public PostResponse findByUsername(String username) { // 작성자 기준 post 조회 + Posts post = postRepository.findByUsername(username); + return entityToDto(post); + } + + @Transactional + public PostResponse update(PostDTO postDTO) { // 수정된 post 반영 + Posts postEntity = postRepository.findById(postDTO.id()); + postEntity.setContent(postDTO.content()); + postEntity.setUpdateat(LocalDateTime.now()); + return entityToDto(postEntity); + } + + @Transactional + public void delete(PostDTO postDTO) { // post 삭제 + Posts object = postRepository.findById(postDTO.id()); + postRepository.delete(object); + } +} diff --git a/src/main/java/services/PostService.java b/src/main/java/services/PostService.java deleted file mode 100644 index b32cb68..0000000 --- a/src/main/java/services/PostService.java +++ /dev/null @@ -1,74 +0,0 @@ -package services; - -import dto.Post; -import dto.PostResponse; -import entities.Posts; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import repositories.PostRepository; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; - -@Service -@RequiredArgsConstructor -public class PostService { - private PostRepository postRepository; - - public Posts dtoToEntity(Post post) { - Posts postEntity = new Posts().builder() - .username(post.username()) - .content(post.content()) - .createat(LocalDateTime.now()) - .build(); - return postEntity; - } - - public PostResponse entityToDto(Posts post) { - return PostResponse.builder() - .username(post.getUsername()) - .content(post.getContent()) - .like(post.getLikeit()) - .createAt(post.getCreateat()) - .updateAt(post.getUpdateat()) - .build(); - } - - @Transactional - public PostResponse save(Post post) { - Posts postEntity = dtoToEntity(post); - postRepository.save(postEntity); - return entityToDto(postEntity); - } - - @Transactional - public List findAll() { - List posts = postRepository.findAll(); - List postResponses = new ArrayList<>(); - for (Posts post : posts) { - postResponses.add(entityToDto(post)); - } - return postResponses; - } - - @Transactional - public PostResponse findByUsername(String username) { - Posts post = postRepository.findByUsername(username); - return entityToDto(post); - } - - @Transactional - public PostResponse update(Post post) { - Posts postEntity = dtoToEntity(post); - postEntity.setUpdateat(LocalDateTime.now()); - postRepository.save(postEntity); - return entityToDto(postEntity); - } - - @Transactional - public void delete(Post post) { - postRepository.delete(dtoToEntity(post)); - } -} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f3f10af..2326d4f 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,10 @@ spring.application.name=devSns +spring.datasource.url=jdbc:postgresql://localhost:5432/crud +spring.datasource.username=crudsns +spring.datasource.password=crud^124 +spring.datasource.driver-class-name=org.postgresql.Driver + +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect + From 43cb73062d2118b7d13121a30bdf72c795c12fd5 Mon Sep 17 00:00:00 2001 From: scholar-star Date: Wed, 8 Oct 2025 20:02:08 +0900 Subject: [PATCH 03/22] =?UTF-8?q?EntityNotFoundException=20handler=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80,=20findByName=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devSns/controllers/PostController.java | 12 ++++++++++-- .../devSns/repositories/PostRepository.java | 5 +++-- .../example/devSns/services/PostService.java | 18 +++++++++++++----- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/example/devSns/controllers/PostController.java b/src/main/java/com/example/devSns/controllers/PostController.java index bef5379..9ecf6cd 100644 --- a/src/main/java/com/example/devSns/controllers/PostController.java +++ b/src/main/java/com/example/devSns/controllers/PostController.java @@ -2,6 +2,7 @@ import com.example.devSns.dto.PostDTO; import com.example.devSns.dto.PostResponse; +import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -22,8 +23,8 @@ public ResponseEntity> showPosts() { } @GetMapping("/show/{username}") - public ResponseEntity showPost(@PathVariable String username) { - PostResponse post = postService.findByUsername(username); + public ResponseEntity> showPost(@PathVariable String username) { + List post = postService.findByUsername(username); return new ResponseEntity<>(post, HttpStatus.OK); } @@ -44,4 +45,11 @@ public ResponseEntity deletePost(@RequestBody PostDTO postDTO) { postService.delete(postDTO); return new ResponseEntity<>("Post deleted", HttpStatus.OK); } + + @ExceptionHandler + public ResponseEntity handleEntityNotFoundException(EntityNotFoundException e) { + ResponseEntity response = + new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + return response; + } } diff --git a/src/main/java/com/example/devSns/repositories/PostRepository.java b/src/main/java/com/example/devSns/repositories/PostRepository.java index a515181..44dc0f1 100644 --- a/src/main/java/com/example/devSns/repositories/PostRepository.java +++ b/src/main/java/com/example/devSns/repositories/PostRepository.java @@ -4,9 +4,10 @@ import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; +import java.util.Optional; public interface PostRepository extends JpaRepository { public List findAll(); - public Posts findById(Integer id); - public Posts findByUsername(String username); + public Optional findById(Integer id); + public List findByUsername(String username); } diff --git a/src/main/java/com/example/devSns/services/PostService.java b/src/main/java/com/example/devSns/services/PostService.java index e9b10e2..d14121c 100644 --- a/src/main/java/com/example/devSns/services/PostService.java +++ b/src/main/java/com/example/devSns/services/PostService.java @@ -3,6 +3,7 @@ import com.example.devSns.dto.PostDTO; import com.example.devSns.dto.PostResponse; import com.example.devSns.entities.Posts; +import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -11,6 +12,7 @@ import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; +import java.util.Optional; @Service @RequiredArgsConstructor @@ -55,14 +57,19 @@ public List findAll() { // 전체 post 조회 } @Transactional - public PostResponse findByUsername(String username) { // 작성자 기준 post 조회 - Posts post = postRepository.findByUsername(username); - return entityToDto(post); + public List findByUsername(String username) { // 작성자 기준 post 조회 + List postsByName = postRepository.findByUsername(username); + List postResponses = new ArrayList<>(); + for (Posts post : postsByName) { + postResponses.add(entityToDto(post)); + } + return postResponses; } @Transactional public PostResponse update(PostDTO postDTO) { // 수정된 post 반영 - Posts postEntity = postRepository.findById(postDTO.id()); + Posts postEntity = postRepository.findById(postDTO.id()) + .orElseThrow(() -> new EntityNotFoundException("수정하려는 Post를 찾을 수 없습니다.")); postEntity.setContent(postDTO.content()); postEntity.setUpdateat(LocalDateTime.now()); return entityToDto(postEntity); @@ -70,7 +77,8 @@ public PostResponse update(PostDTO postDTO) { // 수정된 post 반영 @Transactional public void delete(PostDTO postDTO) { // post 삭제 - Posts object = postRepository.findById(postDTO.id()); + Posts object = postRepository.findById(postDTO.id()) + .orElseThrow(() -> new EntityNotFoundException("삭제하려는 Post를 찾을 수 없습니다.")); postRepository.delete(object); } } From 299dc06014da185647be9660ae05c4a48e01a792 Mon Sep 17 00:00:00 2001 From: scholar-star Date: Wed, 8 Oct 2025 23:44:37 +0900 Subject: [PATCH 04/22] =?UTF-8?q?DataAccessException(SQL)=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20handler=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/devSns/controllers/PostController.java | 8 ++++++++ .../java/com/example/devSns/services/PostService.java | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/example/devSns/controllers/PostController.java b/src/main/java/com/example/devSns/controllers/PostController.java index 9ecf6cd..48d5ffe 100644 --- a/src/main/java/com/example/devSns/controllers/PostController.java +++ b/src/main/java/com/example/devSns/controllers/PostController.java @@ -4,6 +4,7 @@ import com.example.devSns.dto.PostResponse; import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; +import org.springframework.dao.DataAccessException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -52,4 +53,11 @@ public ResponseEntity handleEntityNotFoundException(EntityNotFoundExcept new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); return response; } + + @ExceptionHandler + public ResponseEntity handleDataAccessException(DataAccessException e) { + ResponseEntity response = + new ResponseEntity<>("DB 오류", HttpStatus.INTERNAL_SERVER_ERROR); + return response; + } } diff --git a/src/main/java/com/example/devSns/services/PostService.java b/src/main/java/com/example/devSns/services/PostService.java index d14121c..0b0e8a0 100644 --- a/src/main/java/com/example/devSns/services/PostService.java +++ b/src/main/java/com/example/devSns/services/PostService.java @@ -12,7 +12,6 @@ import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; -import java.util.Optional; @Service @RequiredArgsConstructor From ac326f8b087c6537aff77d199187807f712593ff Mon Sep 17 00:00:00 2001 From: scholar-star Date: Fri, 10 Oct 2025 10:13:45 +0900 Subject: [PATCH 05/22] =?UTF-8?q?update/delete=EC=9D=98=20Postbody?= =?UTF-8?q?=EB=A1=9C=20id=EB=A5=BC=20=ED=8F=AC=ED=95=A8=ED=95=98=EC=97=AC?= =?UTF-8?q?=20=EB=B3=B4=EB=82=B4=EB=8D=98=20=EB=B6=80=EB=B6=84=EC=9D=84=20?= =?UTF-8?q?@PathVariable=EB=A1=9C=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/devSns/controllers/PostController.java | 12 ++++++------ src/main/java/com/example/devSns/dto/PostDTO.java | 1 - .../java/com/example/devSns/dto/PostResponse.java | 2 +- src/main/java/com/example/devSns/entities/Posts.java | 2 +- .../com/example/devSns/services/PostService.java | 8 ++++---- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/example/devSns/controllers/PostController.java b/src/main/java/com/example/devSns/controllers/PostController.java index 48d5ffe..bfc52d3 100644 --- a/src/main/java/com/example/devSns/controllers/PostController.java +++ b/src/main/java/com/example/devSns/controllers/PostController.java @@ -35,15 +35,15 @@ public ResponseEntity addPost(@RequestBody PostDTO postDTO) { return new ResponseEntity<>(postResponse, HttpStatus.CREATED); } - @PutMapping("/update") - public ResponseEntity updatePost(@RequestBody PostDTO postDTO) { - PostResponse postResponse = postService.update(postDTO); + @PutMapping("/update/{id}") + public ResponseEntity updatePost(@PathVariable Long id, @RequestBody PostDTO postDTO) { + PostResponse postResponse = postService.update(id, postDTO); return new ResponseEntity<>(postResponse, HttpStatus.OK); } - @DeleteMapping("/delete") - public ResponseEntity deletePost(@RequestBody PostDTO postDTO) { - postService.delete(postDTO); + @DeleteMapping("/delete/{id}") + public ResponseEntity deletePost(@PathVariable Long id) { + postService.delete(id); return new ResponseEntity<>("Post deleted", HttpStatus.OK); } diff --git a/src/main/java/com/example/devSns/dto/PostDTO.java b/src/main/java/com/example/devSns/dto/PostDTO.java index 612d2e2..c3cc3cc 100644 --- a/src/main/java/com/example/devSns/dto/PostDTO.java +++ b/src/main/java/com/example/devSns/dto/PostDTO.java @@ -1,7 +1,6 @@ package com.example.devSns.dto; public record PostDTO( - Integer id, String username, String content ) { } diff --git a/src/main/java/com/example/devSns/dto/PostResponse.java b/src/main/java/com/example/devSns/dto/PostResponse.java index 45ab0eb..c8ff865 100644 --- a/src/main/java/com/example/devSns/dto/PostResponse.java +++ b/src/main/java/com/example/devSns/dto/PostResponse.java @@ -6,7 +6,7 @@ @Builder public record PostResponse( - Integer id, + Long id, String username, String content, Integer like, diff --git a/src/main/java/com/example/devSns/entities/Posts.java b/src/main/java/com/example/devSns/entities/Posts.java index 521884f..60e2789 100644 --- a/src/main/java/com/example/devSns/entities/Posts.java +++ b/src/main/java/com/example/devSns/entities/Posts.java @@ -15,7 +15,7 @@ public class Posts { @Id @GeneratedValue(strategy = GenerationType.AUTO) - private int id; + private Long id; @NotNull @Column diff --git a/src/main/java/com/example/devSns/services/PostService.java b/src/main/java/com/example/devSns/services/PostService.java index 0b0e8a0..13958ab 100644 --- a/src/main/java/com/example/devSns/services/PostService.java +++ b/src/main/java/com/example/devSns/services/PostService.java @@ -66,8 +66,8 @@ public List findByUsername(String username) { // 작성자 기준 } @Transactional - public PostResponse update(PostDTO postDTO) { // 수정된 post 반영 - Posts postEntity = postRepository.findById(postDTO.id()) + public PostResponse update(Long id, PostDTO postDTO) { // 수정된 post 반영 + Posts postEntity = postRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("수정하려는 Post를 찾을 수 없습니다.")); postEntity.setContent(postDTO.content()); postEntity.setUpdateat(LocalDateTime.now()); @@ -75,8 +75,8 @@ public PostResponse update(PostDTO postDTO) { // 수정된 post 반영 } @Transactional - public void delete(PostDTO postDTO) { // post 삭제 - Posts object = postRepository.findById(postDTO.id()) + public void delete(Long id) { // post 삭제 + Posts object = postRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("삭제하려는 Post를 찾을 수 없습니다.")); postRepository.delete(object); } From a24b3aa77075b933a8a5913fe963bf8115476b76 Mon Sep 17 00:00:00 2001 From: scholar-star Date: Sat, 1 Nov 2025 23:16:38 +0900 Subject: [PATCH 06/22] =?UTF-8?q?=EA=B8=B0=EC=A1=B4=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EB=B0=98=EC=98=81,=20Entity=EC=99=80=20Co?= =?UTF-8?q?ntroller,=20Service=20=ED=86=A0=EB=8C=80=20=EB=A7=8C=EB=93=A4?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devSns/controllers/ReplyController.java | 4 +++ .../java/com/example/devSns/dto/PostDTO.java | 12 ++++++++- .../com/example/devSns/dto/PostResponse.java | 14 +++++++++- .../com/example/devSns/entities/Replies.java | 26 +++++++++++++++++++ .../devSns/repositories/ReplyRepository.java | 4 +++ .../example/devSns/services/PostService.java | 22 +++------------- .../example/devSns/services/ReplyService.java | 7 +++++ 7 files changed, 68 insertions(+), 21 deletions(-) create mode 100644 src/main/java/com/example/devSns/controllers/ReplyController.java create mode 100644 src/main/java/com/example/devSns/entities/Replies.java create mode 100644 src/main/java/com/example/devSns/repositories/ReplyRepository.java create mode 100644 src/main/java/com/example/devSns/services/ReplyService.java diff --git a/src/main/java/com/example/devSns/controllers/ReplyController.java b/src/main/java/com/example/devSns/controllers/ReplyController.java new file mode 100644 index 0000000..c279426 --- /dev/null +++ b/src/main/java/com/example/devSns/controllers/ReplyController.java @@ -0,0 +1,4 @@ +package com.example.devSns.controllers; + +public class ReplyController { +} diff --git a/src/main/java/com/example/devSns/dto/PostDTO.java b/src/main/java/com/example/devSns/dto/PostDTO.java index c3cc3cc..4fae29a 100644 --- a/src/main/java/com/example/devSns/dto/PostDTO.java +++ b/src/main/java/com/example/devSns/dto/PostDTO.java @@ -1,6 +1,16 @@ package com.example.devSns.dto; +import com.example.devSns.entities.Posts; + public record PostDTO( String username, String content -) { } +) { + public static Posts dtoToEntity(PostDTO postDTO) { + Posts postEntity = Posts.builder() + .username(postDTO.username()) + .content(postDTO.content()) + .build(); + return postEntity; + } +} diff --git a/src/main/java/com/example/devSns/dto/PostResponse.java b/src/main/java/com/example/devSns/dto/PostResponse.java index c8ff865..d8b37d0 100644 --- a/src/main/java/com/example/devSns/dto/PostResponse.java +++ b/src/main/java/com/example/devSns/dto/PostResponse.java @@ -1,5 +1,6 @@ package com.example.devSns.dto; +import com.example.devSns.entities.Posts; import lombok.*; import java.time.LocalDateTime; @@ -12,4 +13,15 @@ public record PostResponse( Integer like, LocalDateTime createAt, LocalDateTime updateAt -) {} +) { + public static PostResponse entityToDto(Posts post) { + return PostResponse.builder() + .id(post.getId()) + .username(post.getUsername()) + .content(post.getContent()) + .like(post.getLikeit()) + .createAt(post.getCreateat()) + .updateAt(post.getUpdateat()) + .build(); + } +} diff --git a/src/main/java/com/example/devSns/entities/Replies.java b/src/main/java/com/example/devSns/entities/Replies.java new file mode 100644 index 0000000..66739b8 --- /dev/null +++ b/src/main/java/com/example/devSns/entities/Replies.java @@ -0,0 +1,26 @@ +package com.example.devSns.entities; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.NoArgsConstructor; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class Replies { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + @NotNull + private String username; + + @NotNull + private String reply; +} diff --git a/src/main/java/com/example/devSns/repositories/ReplyRepository.java b/src/main/java/com/example/devSns/repositories/ReplyRepository.java new file mode 100644 index 0000000..5dd85df --- /dev/null +++ b/src/main/java/com/example/devSns/repositories/ReplyRepository.java @@ -0,0 +1,4 @@ +package com.example.devSns.repositories; + +public interface ReplyRepository { +} diff --git a/src/main/java/com/example/devSns/services/PostService.java b/src/main/java/com/example/devSns/services/PostService.java index 13958ab..fcb7988 100644 --- a/src/main/java/com/example/devSns/services/PostService.java +++ b/src/main/java/com/example/devSns/services/PostService.java @@ -13,30 +13,14 @@ import java.util.ArrayList; import java.util.List; +import static com.example.devSns.dto.PostDTO.dtoToEntity; +import static com.example.devSns.dto.PostResponse.entityToDto; + @Service @RequiredArgsConstructor public class PostService { private final PostRepository postRepository; - public Posts dtoToEntity(PostDTO postDTO) { - Posts postEntity = Posts.builder() - .username(postDTO.username()) - .content(postDTO.content()) - .build(); - return postEntity; - } - - public PostResponse entityToDto(Posts post) { - return PostResponse.builder() - .id(post.getId()) - .username(post.getUsername()) - .content(post.getContent()) - .like(post.getLikeit()) - .createAt(post.getCreateat()) - .updateAt(post.getUpdateat()) - .build(); - } - @Transactional // 트랜잭션 보장 public PostResponse save(PostDTO postDTO) { // post insert Posts postEntity = dtoToEntity(postDTO); diff --git a/src/main/java/com/example/devSns/services/ReplyService.java b/src/main/java/com/example/devSns/services/ReplyService.java new file mode 100644 index 0000000..12d7f6a --- /dev/null +++ b/src/main/java/com/example/devSns/services/ReplyService.java @@ -0,0 +1,7 @@ +package com.example.devSns.services; + +import org.springframework.stereotype.Service; + +@Service +public class ReplyService { +} From 676e68d9e3defa275dfc44545709e61c5a316bb8 Mon Sep 17 00:00:00 2001 From: scholar-star Date: Sat, 1 Nov 2025 23:51:12 +0900 Subject: [PATCH 07/22] =?UTF-8?q?Controller=EC=99=80=20Service=20get,=20cr?= =?UTF-8?q?eate=20=EC=A7=84=ED=96=89,=20Entity=EC=97=90=20Join=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devSns/controllers/ReplyController.java | 25 +++++++++++++++++++ .../java/com/example/devSns/dto/ReplyDTO.java | 9 +++++++ .../com/example/devSns/dto/ReplyResponse.java | 8 ++++++ .../com/example/devSns/entities/Replies.java | 10 +++++--- .../example/devSns/services/ReplyService.java | 20 +++++++++++++++ 5 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/example/devSns/dto/ReplyDTO.java create mode 100644 src/main/java/com/example/devSns/dto/ReplyResponse.java diff --git a/src/main/java/com/example/devSns/controllers/ReplyController.java b/src/main/java/com/example/devSns/controllers/ReplyController.java index c279426..7e5ac8f 100644 --- a/src/main/java/com/example/devSns/controllers/ReplyController.java +++ b/src/main/java/com/example/devSns/controllers/ReplyController.java @@ -1,4 +1,29 @@ package com.example.devSns.controllers; +import com.example.devSns.dto.ReplyDTO; +import com.example.devSns.dto.ReplyResponse; +import com.example.devSns.services.ReplyService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping +@RequiredArgsConstructor public class ReplyController { + private final ReplyService replyService; + + @GetMapping("/{postId}/comments") + public ResponseEntity> getComments(@PathVariable long postId) { + + } + + @PostMapping("/{postId}/comment") + public ResponseEntity> writeComment(@PathVariable long postId, ReplyDTO comment) { + + } + + } diff --git a/src/main/java/com/example/devSns/dto/ReplyDTO.java b/src/main/java/com/example/devSns/dto/ReplyDTO.java new file mode 100644 index 0000000..ae46057 --- /dev/null +++ b/src/main/java/com/example/devSns/dto/ReplyDTO.java @@ -0,0 +1,9 @@ +package com.example.devSns.dto; + +public record ReplyDTO( + String title, + String username, + String comment +) { + +} diff --git a/src/main/java/com/example/devSns/dto/ReplyResponse.java b/src/main/java/com/example/devSns/dto/ReplyResponse.java new file mode 100644 index 0000000..2fa966c --- /dev/null +++ b/src/main/java/com/example/devSns/dto/ReplyResponse.java @@ -0,0 +1,8 @@ +package com.example.devSns.dto; + +public record ReplyResponse( + long replyId, + String title, + String username, + String comment +) {} \ No newline at end of file diff --git a/src/main/java/com/example/devSns/entities/Replies.java b/src/main/java/com/example/devSns/entities/Replies.java index 66739b8..ea7ae12 100644 --- a/src/main/java/com/example/devSns/entities/Replies.java +++ b/src/main/java/com/example/devSns/entities/Replies.java @@ -1,9 +1,6 @@ package com.example.devSns.entities; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Builder; @@ -18,6 +15,11 @@ public class Replies { @GeneratedValue(strategy = GenerationType.AUTO) private long id; + @JoinColumn(name = "posts_id") + @ManyToOne + @NotNull + private Posts posts; + @NotNull private String username; diff --git a/src/main/java/com/example/devSns/services/ReplyService.java b/src/main/java/com/example/devSns/services/ReplyService.java index 12d7f6a..9413d63 100644 --- a/src/main/java/com/example/devSns/services/ReplyService.java +++ b/src/main/java/com/example/devSns/services/ReplyService.java @@ -1,7 +1,27 @@ package com.example.devSns.services; +import com.example.devSns.dto.ReplyDTO; +import com.example.devSns.dto.ReplyResponse; +import com.example.devSns.repositories.ReplyRepository; +import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.PathVariable; + +import java.util.List; @Service +@RequiredArgsConstructor public class ReplyService { + private final ReplyRepository replyRepository; + + @Transactional + public List replyGetAll(@PathVariable long postId) { + + } + + @Transactional + public ReplyResponse writeReply(@PathVariable long postId, ReplyDTO reply) { + + } } From 7b94fda3bb27ef524bb6b1188046dce72ccb8a1b Mon Sep 17 00:00:00 2001 From: scholar-star Date: Sat, 1 Nov 2025 23:51:30 +0900 Subject: [PATCH 08/22] =?UTF-8?q?Controller=EC=99=80=20Service=20get,=20cr?= =?UTF-8?q?eate=20=EC=A7=84=ED=96=89,=20Entity=EC=97=90=20Join=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/devSns/controllers/ReplyController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/example/devSns/controllers/ReplyController.java b/src/main/java/com/example/devSns/controllers/ReplyController.java index 7e5ac8f..48bc26d 100644 --- a/src/main/java/com/example/devSns/controllers/ReplyController.java +++ b/src/main/java/com/example/devSns/controllers/ReplyController.java @@ -17,12 +17,12 @@ public class ReplyController { @GetMapping("/{postId}/comments") public ResponseEntity> getComments(@PathVariable long postId) { - + return null; } @PostMapping("/{postId}/comment") public ResponseEntity> writeComment(@PathVariable long postId, ReplyDTO comment) { - + return null; } From 7b53c52aba5431918db1a3628c8f9999308f9fe5 Mon Sep 17 00:00:00 2001 From: scholar-star Date: Sun, 2 Nov 2025 18:44:21 +0900 Subject: [PATCH 09/22] =?UTF-8?q?User=20Entity=20=EC=B6=94=EA=B0=80,=20Rep?= =?UTF-8?q?ly=EC=97=90=20Post=EC=99=80=20User=EC=9D=98=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=20=EA=B4=80=EA=B3=84=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devSns/controllers/ReplyController.java | 2 +- .../java/com/example/devSns/dto/ReplyDTO.java | 16 ++++++++-- .../com/example/devSns/dto/ReplyResponse.java | 15 +++++++-- .../com/example/devSns/entities/Posts.java | 13 +++++++- .../com/example/devSns/entities/Replies.java | 9 +++--- .../com/example/devSns/entities/Users.java | 32 +++++++++++++++++++ .../devSns/repositories/ReplyRepository.java | 8 ++++- .../devSns/repositories/UserRepository.java | 8 +++++ .../example/devSns/services/ReplyService.java | 27 ++++++++++++++-- 9 files changed, 115 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/example/devSns/entities/Users.java create mode 100644 src/main/java/com/example/devSns/repositories/UserRepository.java diff --git a/src/main/java/com/example/devSns/controllers/ReplyController.java b/src/main/java/com/example/devSns/controllers/ReplyController.java index 48bc26d..f02505d 100644 --- a/src/main/java/com/example/devSns/controllers/ReplyController.java +++ b/src/main/java/com/example/devSns/controllers/ReplyController.java @@ -21,7 +21,7 @@ public ResponseEntity> getComments(@PathVariable long postId } @PostMapping("/{postId}/comment") - public ResponseEntity> writeComment(@PathVariable long postId, ReplyDTO comment) { + public ResponseEntity> writeComment(@PathVariable long postId, long userId, ReplyDTO comment) { return null; } diff --git a/src/main/java/com/example/devSns/dto/ReplyDTO.java b/src/main/java/com/example/devSns/dto/ReplyDTO.java index ae46057..c557f8f 100644 --- a/src/main/java/com/example/devSns/dto/ReplyDTO.java +++ b/src/main/java/com/example/devSns/dto/ReplyDTO.java @@ -1,9 +1,19 @@ package com.example.devSns.dto; +import com.example.devSns.entities.Posts; +import com.example.devSns.entities.Replies; +import com.example.devSns.entities.Users; + +import java.util.Optional; + public record ReplyDTO( - String title, - String username, String comment ) { - + public static Replies dtoToEntity(Posts post, Users user, ReplyDTO replyDTO) { + return Replies.builder() + .posts(post) + .users(user) + .reply(replyDTO.comment()) + .build(); + } } diff --git a/src/main/java/com/example/devSns/dto/ReplyResponse.java b/src/main/java/com/example/devSns/dto/ReplyResponse.java index 2fa966c..a5b6b21 100644 --- a/src/main/java/com/example/devSns/dto/ReplyResponse.java +++ b/src/main/java/com/example/devSns/dto/ReplyResponse.java @@ -1,8 +1,19 @@ package com.example.devSns.dto; +import com.example.devSns.entities.Replies; +import lombok.Builder; + +@Builder public record ReplyResponse( long replyId, - String title, String username, String comment -) {} \ No newline at end of file +) { + public static ReplyResponse entityToDTO(Replies replies) { + return ReplyResponse.builder() + .replyId(replies.getId()) + .username(replies.getUsers().getUsername()) + .comment(replies.getReply()) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/devSns/entities/Posts.java b/src/main/java/com/example/devSns/entities/Posts.java index 60e2789..e54d567 100644 --- a/src/main/java/com/example/devSns/entities/Posts.java +++ b/src/main/java/com/example/devSns/entities/Posts.java @@ -8,7 +8,6 @@ @Entity @Getter -@Setter @NoArgsConstructor @AllArgsConstructor @Builder @@ -33,4 +32,16 @@ public class Posts { @Column private LocalDateTime updateat; + + public void setCreateat(LocalDateTime createat) { + this.createat = createat; + } + + public void setUpdateat(LocalDateTime updateat) { + this.updateat = updateat; + } + + public void setContent(String content) { + this.content = content; + } } diff --git a/src/main/java/com/example/devSns/entities/Replies.java b/src/main/java/com/example/devSns/entities/Replies.java index ea7ae12..3a4ff6b 100644 --- a/src/main/java/com/example/devSns/entities/Replies.java +++ b/src/main/java/com/example/devSns/entities/Replies.java @@ -2,13 +2,12 @@ import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.NoArgsConstructor; +import lombok.*; @Entity @NoArgsConstructor @AllArgsConstructor +@Getter @Builder public class Replies { @Id @@ -20,8 +19,10 @@ public class Replies { @NotNull private Posts posts; + @JoinColumn(name = "users_id") + @ManyToOne @NotNull - private String username; + private Users users; @NotNull private String reply; diff --git a/src/main/java/com/example/devSns/entities/Users.java b/src/main/java/com/example/devSns/entities/Users.java new file mode 100644 index 0000000..8bae64c --- /dev/null +++ b/src/main/java/com/example/devSns/entities/Users.java @@ -0,0 +1,32 @@ +package com.example.devSns.entities; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.Date; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Builder +public class Users { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + @NotNull + private String username; + + @NotNull + private Integer age; + + private Date birthday; +} diff --git a/src/main/java/com/example/devSns/repositories/ReplyRepository.java b/src/main/java/com/example/devSns/repositories/ReplyRepository.java index 5dd85df..6ca53db 100644 --- a/src/main/java/com/example/devSns/repositories/ReplyRepository.java +++ b/src/main/java/com/example/devSns/repositories/ReplyRepository.java @@ -1,4 +1,10 @@ package com.example.devSns.repositories; -public interface ReplyRepository { +import com.example.devSns.entities.Replies; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface ReplyRepository extends JpaRepository { + public List findByPostId(Long postId); } diff --git a/src/main/java/com/example/devSns/repositories/UserRepository.java b/src/main/java/com/example/devSns/repositories/UserRepository.java new file mode 100644 index 0000000..9be1992 --- /dev/null +++ b/src/main/java/com/example/devSns/repositories/UserRepository.java @@ -0,0 +1,8 @@ +package com.example.devSns.repositories; + +import com.example.devSns.entities.Users; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository { + public Users findById(long userId); +} diff --git a/src/main/java/com/example/devSns/services/ReplyService.java b/src/main/java/com/example/devSns/services/ReplyService.java index 9413d63..1bed343 100644 --- a/src/main/java/com/example/devSns/services/ReplyService.java +++ b/src/main/java/com/example/devSns/services/ReplyService.java @@ -2,26 +2,47 @@ import com.example.devSns.dto.ReplyDTO; import com.example.devSns.dto.ReplyResponse; +import com.example.devSns.entities.Posts; +import com.example.devSns.entities.Replies; +import com.example.devSns.entities.Users; +import com.example.devSns.repositories.PostRepository; import com.example.devSns.repositories.ReplyRepository; +import com.example.devSns.repositories.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.PathVariable; +import java.util.ArrayList; import java.util.List; +import java.util.Optional; @Service @RequiredArgsConstructor public class ReplyService { private final ReplyRepository replyRepository; + private final PostRepository postRepository; + private final UserRepository userRepository; @Transactional public List replyGetAll(@PathVariable long postId) { - + Posts post = postRepository.findById(postId).orElseThrow(); + List replies = replyRepository.findByPostId(postId); + List repliesResponse = new ArrayList<>(); + for (Replies reply: replies) { + repliesResponse.add(ReplyResponse.entityToDTO(reply)); + } + return repliesResponse; } @Transactional - public ReplyResponse writeReply(@PathVariable long postId, ReplyDTO reply) { - + public ReplyResponse writeReply(@PathVariable long postId, long userId, ReplyDTO reply) { + Posts post = postRepository.findById(postId).orElseThrow(); + Users user = userRepository.findById(userId); + Replies replyEntity = ReplyDTO.dtoToEntity(post, user, reply); + replyRepository.save(replyEntity); + return ReplyResponse.entityToDTO(replyEntity); } + + } From 90ce72330771b5243e63d480a72a0a0f0d49f8c3 Mon Sep 17 00:00:00 2001 From: scholar-star Date: Sun, 2 Nov 2025 23:32:01 +0900 Subject: [PATCH 10/22] =?UTF-8?q?service,=20controller=20=ED=86=A0?= =?UTF-8?q?=EB=8C=80=20=EB=A7=8C=EB=93=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devSns/controllers/ReplyController.java | 10 +++++++++- .../com/example/devSns/entities/Replies.java | 8 ++++++++ .../example/devSns/services/ReplyService.java | 17 ++++++++++++++++- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/example/devSns/controllers/ReplyController.java b/src/main/java/com/example/devSns/controllers/ReplyController.java index f02505d..bde6053 100644 --- a/src/main/java/com/example/devSns/controllers/ReplyController.java +++ b/src/main/java/com/example/devSns/controllers/ReplyController.java @@ -20,10 +20,18 @@ public ResponseEntity> getComments(@PathVariable long postId return null; } - @PostMapping("/{postId}/comment") + @PostMapping("/{postId}") public ResponseEntity> writeComment(@PathVariable long postId, long userId, ReplyDTO comment) { return null; } + @PatchMapping("/{postid}") + public ResponseEntity updateComment(@PathVariable long postId, long userId, ReplyDTO comment) { + return null; + } + @DeleteMapping("/{postId}") + public ResponseEntity deleteComment(@PathVariable long postId, long userId) { + return null; + } } diff --git a/src/main/java/com/example/devSns/entities/Replies.java b/src/main/java/com/example/devSns/entities/Replies.java index 3a4ff6b..1966e63 100644 --- a/src/main/java/com/example/devSns/entities/Replies.java +++ b/src/main/java/com/example/devSns/entities/Replies.java @@ -4,6 +4,8 @@ import jakarta.validation.constraints.NotNull; import lombok.*; +import java.time.LocalDateTime; + @Entity @NoArgsConstructor @AllArgsConstructor @@ -26,4 +28,10 @@ public class Replies { @NotNull private String reply; + + @NotNull + private LocalDateTime createAt; + + @NotNull + private LocalDateTime updateAt; } diff --git a/src/main/java/com/example/devSns/services/ReplyService.java b/src/main/java/com/example/devSns/services/ReplyService.java index 1bed343..1e6b998 100644 --- a/src/main/java/com/example/devSns/services/ReplyService.java +++ b/src/main/java/com/example/devSns/services/ReplyService.java @@ -15,7 +15,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Optional; @Service @RequiredArgsConstructor @@ -44,5 +43,21 @@ public ReplyResponse writeReply(@PathVariable long postId, long userId, ReplyDTO return ReplyResponse.entityToDTO(replyEntity); } + @Transactional + public ReplyResponse updateReply(@PathVariable long postId, long userId, ReplyDTO reply) { + Posts post = postRepository.findById(postId).orElseThrow(); + Users user = userRepository.findById(userId); + Replies replyEntity = ReplyDTO.dtoToEntity(post, user, reply); + replyRepository.save(replyEntity); + return ReplyResponse.entityToDTO(replyEntity); + } + @Transactional + public String deleteReply(@PathVariable long postId, long userId) { + Posts post = postRepository.findById(postId).orElseThrow(); + Users user = userRepository.findById(userId); + Replies replyEntity = replyRepository.findById(postId).orElseThrow(); + replyRepository.delete(replyEntity); + return "성공적으로 삭제되었습니다"; + } } From 3df566e77283de485bc864d7fb004b100187450f Mon Sep 17 00:00:00 2001 From: scholar-star Date: Mon, 3 Nov 2025 15:01:43 +0900 Subject: [PATCH 11/22] =?UTF-8?q?GlobalExceptionHandler=EB=A1=9C=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EC=98=AE=EA=B8=B0?= =?UTF-8?q?=EA=B8=B0,=20Controller=20=EA=B8=B0=EB=B3=B8=20=EC=B1=84?= =?UTF-8?q?=EC=9B=8C=EB=84=A3=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devSns/controllers/PostController.java | 14 ---------- .../devSns/controllers/ReplyController.java | 27 ++++++++++++------- .../exceptions/GlobalExceptionHandler.java | 26 ++++++++++++++++++ 3 files changed, 44 insertions(+), 23 deletions(-) create mode 100644 src/main/java/exceptions/GlobalExceptionHandler.java diff --git a/src/main/java/com/example/devSns/controllers/PostController.java b/src/main/java/com/example/devSns/controllers/PostController.java index bfc52d3..a2b971e 100644 --- a/src/main/java/com/example/devSns/controllers/PostController.java +++ b/src/main/java/com/example/devSns/controllers/PostController.java @@ -46,18 +46,4 @@ public ResponseEntity deletePost(@PathVariable Long id) { postService.delete(id); return new ResponseEntity<>("Post deleted", HttpStatus.OK); } - - @ExceptionHandler - public ResponseEntity handleEntityNotFoundException(EntityNotFoundException e) { - ResponseEntity response = - new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); - return response; - } - - @ExceptionHandler - public ResponseEntity handleDataAccessException(DataAccessException e) { - ResponseEntity response = - new ResponseEntity<>("DB 오류", HttpStatus.INTERNAL_SERVER_ERROR); - return response; - } } diff --git a/src/main/java/com/example/devSns/controllers/ReplyController.java b/src/main/java/com/example/devSns/controllers/ReplyController.java index bde6053..cc1c352 100644 --- a/src/main/java/com/example/devSns/controllers/ReplyController.java +++ b/src/main/java/com/example/devSns/controllers/ReplyController.java @@ -4,6 +4,7 @@ import com.example.devSns.dto.ReplyResponse; import com.example.devSns.services.ReplyService; import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -15,23 +16,31 @@ public class ReplyController { private final ReplyService replyService; - @GetMapping("/{postId}/comments") - public ResponseEntity> getComments(@PathVariable long postId) { - return null; + @GetMapping("/{postId}/replies") + public ResponseEntity> getReplies(@PathVariable long postId) { + List replies = replyService.replyGetAll(postId); + ResponseEntity> responseEntity = new ResponseEntity<>(replies, HttpStatus.OK); + return responseEntity; } @PostMapping("/{postId}") - public ResponseEntity> writeComment(@PathVariable long postId, long userId, ReplyDTO comment) { - return null; + public ResponseEntity writeReply(@PathVariable long postId, long userId, ReplyDTO reply) { + ReplyResponse replyResponse = replyService.writeReply(postId, userId, reply); + ResponseEntity responseEntity = new ResponseEntity<>(replyResponse, HttpStatus.OK); + return responseEntity; } @PatchMapping("/{postid}") - public ResponseEntity updateComment(@PathVariable long postId, long userId, ReplyDTO comment) { - return null; + public ResponseEntity updateReply(@PathVariable long postId, long userId, ReplyDTO reply) { + ReplyResponse replyResponse = replyService.updateReply(postId, userId, reply); + ResponseEntity responseEntity = new ResponseEntity<>(replyResponse, HttpStatus.OK); + return responseEntity; } @DeleteMapping("/{postId}") - public ResponseEntity deleteComment(@PathVariable long postId, long userId) { - return null; + public ResponseEntity deleteReply(@PathVariable long postId, long userId) { + String deleteCheck = replyService.deleteReply(postId, userId); + ResponseEntity responseEntity = new ResponseEntity<>(deleteCheck, HttpStatus.OK); + return responseEntity; } } diff --git a/src/main/java/exceptions/GlobalExceptionHandler.java b/src/main/java/exceptions/GlobalExceptionHandler.java new file mode 100644 index 0000000..9e7eaad --- /dev/null +++ b/src/main/java/exceptions/GlobalExceptionHandler.java @@ -0,0 +1,26 @@ +package exceptions; + +import jakarta.persistence.EntityNotFoundException; +import org.springframework.dao.DataAccessException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +@RestControllerAdvice +public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { + @ExceptionHandler + public ResponseEntity handleEntityNotFoundException(EntityNotFoundException e) { + ResponseEntity response = + new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + return response; + } + + @ExceptionHandler + public ResponseEntity handleDataAccessException(DataAccessException e) { + ResponseEntity response = + new ResponseEntity<>("DB 오류", HttpStatus.INTERNAL_SERVER_ERROR); + return response; + } +} From 7fe66e92ae488d79d9366bcb1004d248d2ce70ab Mon Sep 17 00:00:00 2001 From: scholar-star Date: Tue, 4 Nov 2025 10:41:57 +0900 Subject: [PATCH 12/22] =?UTF-8?q?ReplyRepository=20findby=20=ED=98=95?= =?UTF-8?q?=ED=83=9C=20=EB=B3=80=EA=B2=BD(postId->Posts),=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/devSns/repositories/ReplyRepository.java | 3 ++- src/main/java/com/example/devSns/services/ReplyService.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/example/devSns/repositories/ReplyRepository.java b/src/main/java/com/example/devSns/repositories/ReplyRepository.java index 6ca53db..d8fc040 100644 --- a/src/main/java/com/example/devSns/repositories/ReplyRepository.java +++ b/src/main/java/com/example/devSns/repositories/ReplyRepository.java @@ -1,10 +1,11 @@ package com.example.devSns.repositories; +import com.example.devSns.entities.Posts; import com.example.devSns.entities.Replies; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; public interface ReplyRepository extends JpaRepository { - public List findByPostId(Long postId); + public List findByPosts(Posts posts); } diff --git a/src/main/java/com/example/devSns/services/ReplyService.java b/src/main/java/com/example/devSns/services/ReplyService.java index 1e6b998..7bc83bc 100644 --- a/src/main/java/com/example/devSns/services/ReplyService.java +++ b/src/main/java/com/example/devSns/services/ReplyService.java @@ -26,7 +26,7 @@ public class ReplyService { @Transactional public List replyGetAll(@PathVariable long postId) { Posts post = postRepository.findById(postId).orElseThrow(); - List replies = replyRepository.findByPostId(postId); + List replies = replyRepository.findByPosts(post); List repliesResponse = new ArrayList<>(); for (Replies reply: replies) { repliesResponse.add(ReplyResponse.entityToDTO(reply)); From 5f6e17940a6cc70d91aa68e571a57deebc45895c Mon Sep 17 00:00:00 2001 From: scholar-star Date: Tue, 4 Nov 2025 23:56:05 +0900 Subject: [PATCH 13/22] =?UTF-8?q?Post=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/devSns/controllers/PostController.java | 8 +++----- src/main/java/com/example/devSns/dto/PostDTO.java | 6 ++++-- .../java/com/example/devSns/dto/PostResponse.java | 3 ++- src/main/java/com/example/devSns/entities/Posts.java | 5 +++-- .../java/com/example/devSns/entities/Replies.java | 5 +++++ src/main/java/com/example/devSns/entities/Users.java | 5 +---- .../example/devSns/repositories/PostRepository.java | 2 +- .../com/example/devSns/services/PostService.java | 12 ++++++++---- 8 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/example/devSns/controllers/PostController.java b/src/main/java/com/example/devSns/controllers/PostController.java index a2b971e..2534399 100644 --- a/src/main/java/com/example/devSns/controllers/PostController.java +++ b/src/main/java/com/example/devSns/controllers/PostController.java @@ -2,9 +2,7 @@ import com.example.devSns.dto.PostDTO; import com.example.devSns.dto.PostResponse; -import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; -import org.springframework.dao.DataAccessException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -23,9 +21,9 @@ public ResponseEntity> showPosts() { return new ResponseEntity<>(posts, HttpStatus.OK); } - @GetMapping("/show/{username}") - public ResponseEntity> showPost(@PathVariable String username) { - List post = postService.findByUsername(username); + @GetMapping("/show/{userID}") + public ResponseEntity> showPost(@PathVariable Long userID) { + List post = postService.findByUserID(userID); return new ResponseEntity<>(post, HttpStatus.OK); } diff --git a/src/main/java/com/example/devSns/dto/PostDTO.java b/src/main/java/com/example/devSns/dto/PostDTO.java index 4fae29a..118ec9c 100644 --- a/src/main/java/com/example/devSns/dto/PostDTO.java +++ b/src/main/java/com/example/devSns/dto/PostDTO.java @@ -1,14 +1,16 @@ package com.example.devSns.dto; import com.example.devSns.entities.Posts; +import com.example.devSns.entities.Users; public record PostDTO( + Long userId, String username, String content ) { - public static Posts dtoToEntity(PostDTO postDTO) { + public static Posts dtoToEntity(PostDTO postDTO, Users user) { Posts postEntity = Posts.builder() - .username(postDTO.username()) + .users(user) .content(postDTO.content()) .build(); return postEntity; diff --git a/src/main/java/com/example/devSns/dto/PostResponse.java b/src/main/java/com/example/devSns/dto/PostResponse.java index d8b37d0..467fd48 100644 --- a/src/main/java/com/example/devSns/dto/PostResponse.java +++ b/src/main/java/com/example/devSns/dto/PostResponse.java @@ -1,6 +1,7 @@ package com.example.devSns.dto; import com.example.devSns.entities.Posts; +import com.example.devSns.entities.Users; import lombok.*; import java.time.LocalDateTime; @@ -17,7 +18,7 @@ public record PostResponse( public static PostResponse entityToDto(Posts post) { return PostResponse.builder() .id(post.getId()) - .username(post.getUsername()) + .username(post.getUsers().getUsername()) .content(post.getContent()) .like(post.getLikeit()) .createAt(post.getCreateat()) diff --git a/src/main/java/com/example/devSns/entities/Posts.java b/src/main/java/com/example/devSns/entities/Posts.java index e54d567..87fa483 100644 --- a/src/main/java/com/example/devSns/entities/Posts.java +++ b/src/main/java/com/example/devSns/entities/Posts.java @@ -20,9 +20,10 @@ public class Posts { @Column private String content; + @JoinColumn(name = "users_id") + @ManyToOne @NotNull - @Column - private String username; + private Users users; @Column private int likeit; diff --git a/src/main/java/com/example/devSns/entities/Replies.java b/src/main/java/com/example/devSns/entities/Replies.java index 1966e63..e703199 100644 --- a/src/main/java/com/example/devSns/entities/Replies.java +++ b/src/main/java/com/example/devSns/entities/Replies.java @@ -5,6 +5,8 @@ import lombok.*; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; @Entity @NoArgsConstructor @@ -34,4 +36,7 @@ public class Replies { @NotNull private LocalDateTime updateAt; + + @OneToMany(mappedBy = "posts", cascade = CascadeType.REMOVE, orphanRemoval = true) + private List replies = new ArrayList<>(); } diff --git a/src/main/java/com/example/devSns/entities/Users.java b/src/main/java/com/example/devSns/entities/Users.java index 8bae64c..600fb2a 100644 --- a/src/main/java/com/example/devSns/entities/Users.java +++ b/src/main/java/com/example/devSns/entities/Users.java @@ -1,9 +1,6 @@ package com.example.devSns.entities; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/src/main/java/com/example/devSns/repositories/PostRepository.java b/src/main/java/com/example/devSns/repositories/PostRepository.java index 44dc0f1..eeaaae1 100644 --- a/src/main/java/com/example/devSns/repositories/PostRepository.java +++ b/src/main/java/com/example/devSns/repositories/PostRepository.java @@ -9,5 +9,5 @@ public interface PostRepository extends JpaRepository { public List findAll(); public Optional findById(Integer id); - public List findByUsername(String username); + public List findByUsersId(Long userID); } diff --git a/src/main/java/com/example/devSns/services/PostService.java b/src/main/java/com/example/devSns/services/PostService.java index fcb7988..a444aac 100644 --- a/src/main/java/com/example/devSns/services/PostService.java +++ b/src/main/java/com/example/devSns/services/PostService.java @@ -3,6 +3,8 @@ import com.example.devSns.dto.PostDTO; import com.example.devSns.dto.PostResponse; import com.example.devSns.entities.Posts; +import com.example.devSns.entities.Users; +import com.example.devSns.repositories.UserRepository; import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -20,10 +22,12 @@ @RequiredArgsConstructor public class PostService { private final PostRepository postRepository; + private final UserRepository userRepository; @Transactional // 트랜잭션 보장 - public PostResponse save(PostDTO postDTO) { // post insert - Posts postEntity = dtoToEntity(postDTO); + public PostResponse save(PostDTO postDTO) { + Users user = userRepository.findById(postDTO.userId()).orElseThrow(EntityNotFoundException::new); + Posts postEntity = dtoToEntity(postDTO, user); postEntity.setCreateat(LocalDateTime.now()); Posts resultEntity = postRepository.save(postEntity); return entityToDto(resultEntity); @@ -40,8 +44,8 @@ public List findAll() { // 전체 post 조회 } @Transactional - public List findByUsername(String username) { // 작성자 기준 post 조회 - List postsByName = postRepository.findByUsername(username); + public List findByUserID(Long userID) { // 작성자 기준 post 조회 + List postsByName = postRepository.findByUsersId(userID); List postResponses = new ArrayList<>(); for (Posts post : postsByName) { postResponses.add(entityToDto(post)); From bb8aaf7249598943673059f9b9198f3091f6dc44 Mon Sep 17 00:00:00 2001 From: scholar-star Date: Sun, 9 Nov 2025 23:29:41 +0900 Subject: [PATCH 14/22] =?UTF-8?q?Post,=20Reply=20Like=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devSns/controllers/PostController.java | 10 ++++- .../devSns/controllers/ReplyController.java | 27 +++++++++----- .../com/example/devSns/dto/PostResponse.java | 1 - .../java/com/example/devSns/dto/ReplyDTO.java | 3 +- .../com/example/devSns/entities/Posts.java | 7 +++- .../com/example/devSns/entities/Replies.java | 23 ++++++++++-- .../devSns/repositories/ReplyRepository.java | 1 + .../example/devSns/services/PostService.java | 7 ++++ .../example/devSns/services/ReplyService.java | 37 +++++++++++++------ .../exceptions/GlobalExceptionHandler.java | 9 +++++ 10 files changed, 95 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/example/devSns/controllers/PostController.java b/src/main/java/com/example/devSns/controllers/PostController.java index 2534399..2e4b56e 100644 --- a/src/main/java/com/example/devSns/controllers/PostController.java +++ b/src/main/java/com/example/devSns/controllers/PostController.java @@ -33,13 +33,19 @@ public ResponseEntity addPost(@RequestBody PostDTO postDTO) { return new ResponseEntity<>(postResponse, HttpStatus.CREATED); } - @PutMapping("/update/{id}") + @PutMapping("/{id}") public ResponseEntity updatePost(@PathVariable Long id, @RequestBody PostDTO postDTO) { PostResponse postResponse = postService.update(id, postDTO); return new ResponseEntity<>(postResponse, HttpStatus.OK); } - @DeleteMapping("/delete/{id}") + @PatchMapping("/{id}/likeit") + public ResponseEntity likePost(@PathVariable Long id) { + PostResponse postResponse = postService.likePost(id); + return new ResponseEntity<>(postResponse, HttpStatus.OK); + } + + @DeleteMapping("/{id}") public ResponseEntity deletePost(@PathVariable Long id) { postService.delete(id); return new ResponseEntity<>("Post deleted", HttpStatus.OK); diff --git a/src/main/java/com/example/devSns/controllers/ReplyController.java b/src/main/java/com/example/devSns/controllers/ReplyController.java index cc1c352..5ee439b 100644 --- a/src/main/java/com/example/devSns/controllers/ReplyController.java +++ b/src/main/java/com/example/devSns/controllers/ReplyController.java @@ -11,7 +11,7 @@ import java.util.List; @RestController -@RequestMapping +@RequestMapping("/sns/reply") @RequiredArgsConstructor public class ReplyController { private final ReplyService replyService; @@ -23,23 +23,30 @@ public ResponseEntity> getReplies(@PathVariable long postId) return responseEntity; } - @PostMapping("/{postId}") - public ResponseEntity writeReply(@PathVariable long postId, long userId, ReplyDTO reply) { - ReplyResponse replyResponse = replyService.writeReply(postId, userId, reply); + @PostMapping("/{postId}/add") + public ResponseEntity writeReply(@PathVariable long postId, @RequestBody ReplyDTO reply) { + ReplyResponse replyResponse = replyService.writeReply(postId, reply); ResponseEntity responseEntity = new ResponseEntity<>(replyResponse, HttpStatus.OK); return responseEntity; } - @PatchMapping("/{postid}") - public ResponseEntity updateReply(@PathVariable long postId, long userId, ReplyDTO reply) { - ReplyResponse replyResponse = replyService.updateReply(postId, userId, reply); + @PutMapping("/{replyId}") + public ResponseEntity updateReply(@PathVariable long replyId, @RequestBody ReplyDTO reply) { + ReplyResponse replyResponse = replyService.updateReply(replyId, reply); ResponseEntity responseEntity = new ResponseEntity<>(replyResponse, HttpStatus.OK); return responseEntity; } - @DeleteMapping("/{postId}") - public ResponseEntity deleteReply(@PathVariable long postId, long userId) { - String deleteCheck = replyService.deleteReply(postId, userId); + @PatchMapping("/{id}") + public ResponseEntity likeReply(@PathVariable long id) { + ReplyResponse replyResponse = replyService.likeReply(id); + ResponseEntity responseEntity = new ResponseEntity<>(replyResponse, HttpStatus.OK); + return responseEntity; + } + + @DeleteMapping("/{replyId}") + public ResponseEntity deleteReply(@PathVariable long replyId) { + String deleteCheck = replyService.deleteReply(replyId); ResponseEntity responseEntity = new ResponseEntity<>(deleteCheck, HttpStatus.OK); return responseEntity; } diff --git a/src/main/java/com/example/devSns/dto/PostResponse.java b/src/main/java/com/example/devSns/dto/PostResponse.java index 467fd48..90a3316 100644 --- a/src/main/java/com/example/devSns/dto/PostResponse.java +++ b/src/main/java/com/example/devSns/dto/PostResponse.java @@ -1,7 +1,6 @@ package com.example.devSns.dto; import com.example.devSns.entities.Posts; -import com.example.devSns.entities.Users; import lombok.*; import java.time.LocalDateTime; diff --git a/src/main/java/com/example/devSns/dto/ReplyDTO.java b/src/main/java/com/example/devSns/dto/ReplyDTO.java index c557f8f..c9420bf 100644 --- a/src/main/java/com/example/devSns/dto/ReplyDTO.java +++ b/src/main/java/com/example/devSns/dto/ReplyDTO.java @@ -4,9 +4,8 @@ import com.example.devSns.entities.Replies; import com.example.devSns.entities.Users; -import java.util.Optional; - public record ReplyDTO( + Long userID, String comment ) { public static Replies dtoToEntity(Posts post, Users user, ReplyDTO replyDTO) { diff --git a/src/main/java/com/example/devSns/entities/Posts.java b/src/main/java/com/example/devSns/entities/Posts.java index 87fa483..d8a88ec 100644 --- a/src/main/java/com/example/devSns/entities/Posts.java +++ b/src/main/java/com/example/devSns/entities/Posts.java @@ -3,6 +3,7 @@ import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import lombok.*; +import org.hibernate.annotations.ColumnDefault; import java.time.LocalDateTime; @@ -25,7 +26,7 @@ public class Posts { @NotNull private Users users; - @Column + @ColumnDefault("0") private int likeit; @Column @@ -45,4 +46,8 @@ public void setUpdateat(LocalDateTime updateat) { public void setContent(String content) { this.content = content; } + + public void setLikeit(int likeit) { + this.likeit = likeit; + } } diff --git a/src/main/java/com/example/devSns/entities/Replies.java b/src/main/java/com/example/devSns/entities/Replies.java index e703199..83a42d1 100644 --- a/src/main/java/com/example/devSns/entities/Replies.java +++ b/src/main/java/com/example/devSns/entities/Replies.java @@ -3,6 +3,7 @@ import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import lombok.*; +import org.hibernate.annotations.ColumnDefault; import java.time.LocalDateTime; import java.util.ArrayList; @@ -28,15 +29,31 @@ public class Replies { @NotNull private Users users; + @Column + @ColumnDefault("0") // Table 생성 시점 기본값 + private int likeit; + @NotNull private String reply; @NotNull private LocalDateTime createAt; - @NotNull private LocalDateTime updateAt; - @OneToMany(mappedBy = "posts", cascade = CascadeType.REMOVE, orphanRemoval = true) - private List replies = new ArrayList<>(); + public void setReply(String reply) { + this.reply = reply; + } + + public void setCreateAt(LocalDateTime createAt) { + this.createAt = createAt; + } + + public void setUpdateAt(LocalDateTime updateAt) { + this.updateAt = updateAt; + } + + public void setLikeit(int likeit) { + this.likeit = likeit; + } } diff --git a/src/main/java/com/example/devSns/repositories/ReplyRepository.java b/src/main/java/com/example/devSns/repositories/ReplyRepository.java index d8fc040..8735736 100644 --- a/src/main/java/com/example/devSns/repositories/ReplyRepository.java +++ b/src/main/java/com/example/devSns/repositories/ReplyRepository.java @@ -8,4 +8,5 @@ public interface ReplyRepository extends JpaRepository { public List findByPosts(Posts posts); + public Replies findById(long id); } diff --git a/src/main/java/com/example/devSns/services/PostService.java b/src/main/java/com/example/devSns/services/PostService.java index a444aac..7312b42 100644 --- a/src/main/java/com/example/devSns/services/PostService.java +++ b/src/main/java/com/example/devSns/services/PostService.java @@ -62,6 +62,13 @@ public PostResponse update(Long id, PostDTO postDTO) { // 수정된 post 반영 return entityToDto(postEntity); } + @Transactional + public PostResponse likePost(Long id) { + Posts postEntity = postRepository.findById(id).orElseThrow(EntityNotFoundException::new); + postEntity.setLikeit(postEntity.getLikeit() + 1); + return entityToDto(postEntity); + } + @Transactional public void delete(Long id) { // post 삭제 Posts object = postRepository.findById(id) diff --git a/src/main/java/com/example/devSns/services/ReplyService.java b/src/main/java/com/example/devSns/services/ReplyService.java index 7bc83bc..9193b5c 100644 --- a/src/main/java/com/example/devSns/services/ReplyService.java +++ b/src/main/java/com/example/devSns/services/ReplyService.java @@ -8,15 +8,19 @@ import com.example.devSns.repositories.PostRepository; import com.example.devSns.repositories.ReplyRepository; import com.example.devSns.repositories.UserRepository; +import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.PathVariable; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @Service +@Slf4j @RequiredArgsConstructor public class ReplyService { private final ReplyRepository replyRepository; @@ -35,28 +39,39 @@ public List replyGetAll(@PathVariable long postId) { } @Transactional - public ReplyResponse writeReply(@PathVariable long postId, long userId, ReplyDTO reply) { - Posts post = postRepository.findById(postId).orElseThrow(); - Users user = userRepository.findById(userId); + public ReplyResponse writeReply(@PathVariable long postId, ReplyDTO reply) { + Posts post = postRepository.findById(postId).orElseThrow(EntityNotFoundException::new); + Users user = userRepository.findById(reply.userID()).orElseThrow(EntityNotFoundException::new); Replies replyEntity = ReplyDTO.dtoToEntity(post, user, reply); + replyEntity.setCreateAt(LocalDateTime.now()); replyRepository.save(replyEntity); return ReplyResponse.entityToDTO(replyEntity); } @Transactional - public ReplyResponse updateReply(@PathVariable long postId, long userId, ReplyDTO reply) { - Posts post = postRepository.findById(postId).orElseThrow(); - Users user = userRepository.findById(userId); - Replies replyEntity = ReplyDTO.dtoToEntity(post, user, reply); + public ReplyResponse likeReply(@PathVariable long replyId) { + Replies replyEntity = replyRepository.findById(replyId); + replyEntity.setLikeit(replyEntity.getLikeit() + 1); replyRepository.save(replyEntity); return ReplyResponse.entityToDTO(replyEntity); } @Transactional - public String deleteReply(@PathVariable long postId, long userId) { - Posts post = postRepository.findById(postId).orElseThrow(); - Users user = userRepository.findById(userId); - Replies replyEntity = replyRepository.findById(postId).orElseThrow(); + public ReplyResponse updateReply (@PathVariable long replyId, ReplyDTO reply) { + Users user = userRepository.findById(reply.userID()).orElseThrow(); + if(user.getId() != reply.userID()) { + throw new SecurityException(); + } + Replies replyEntity = replyRepository.findById(replyId); + replyEntity.setReply(reply.comment()); + replyEntity.setUpdateAt(LocalDateTime.now()); + replyRepository.save(replyEntity); + return ReplyResponse.entityToDTO(replyEntity); + } + + @Transactional + public String deleteReply(@PathVariable long replyId) { + Replies replyEntity = replyRepository.findById(replyId); replyRepository.delete(replyEntity); return "성공적으로 삭제되었습니다"; } diff --git a/src/main/java/exceptions/GlobalExceptionHandler.java b/src/main/java/exceptions/GlobalExceptionHandler.java index 9e7eaad..b1edc11 100644 --- a/src/main/java/exceptions/GlobalExceptionHandler.java +++ b/src/main/java/exceptions/GlobalExceptionHandler.java @@ -8,6 +8,8 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; +import javax.naming.AuthenticationException; + @RestControllerAdvice public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { @ExceptionHandler @@ -23,4 +25,11 @@ public ResponseEntity handleDataAccessException(DataAccessException e) { new ResponseEntity<>("DB 오류", HttpStatus.INTERNAL_SERVER_ERROR); return response; } + + @ExceptionHandler + public ResponseEntity handleSecurityException(SecurityException e) { + ResponseEntity response = + new ResponseEntity<>("접근 권한 없음", HttpStatus.FORBIDDEN); + return response; + } } From 0ba91594a2372b43494d735226f837d49dcafeaf Mon Sep 17 00:00:00 2001 From: scholar-star Date: Tue, 11 Nov 2025 16:31:31 +0900 Subject: [PATCH 15/22] =?UTF-8?q?=EC=A2=8B=EC=95=84=EC=9A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80=20Test=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- .../com/example/devSns/dto/ReplyResponse.java | 4 +- .../com/example/devSns/entities/Replies.java | 3 - .../com/example/devSns/entities/Users.java | 4 +- .../java/com/example/devSns/likeTest.java | 90 +++++++++++++++++++ 5 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 src/test/java/com/example/devSns/likeTest.java diff --git a/build.gradle b/build.gradle index 1552412..56d88da 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.projectlombok:lombok' - testImplementation 'org.springframework.boot:spring-boot-starter-test' + implementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' compileOnly 'org.projectlombok:lombok' runtimeOnly 'org.postgresql:postgresql' diff --git a/src/main/java/com/example/devSns/dto/ReplyResponse.java b/src/main/java/com/example/devSns/dto/ReplyResponse.java index a5b6b21..13cb09e 100644 --- a/src/main/java/com/example/devSns/dto/ReplyResponse.java +++ b/src/main/java/com/example/devSns/dto/ReplyResponse.java @@ -7,13 +7,15 @@ public record ReplyResponse( long replyId, String username, - String comment + String comment, + Integer like ) { public static ReplyResponse entityToDTO(Replies replies) { return ReplyResponse.builder() .replyId(replies.getId()) .username(replies.getUsers().getUsername()) .comment(replies.getReply()) + .like(replies.getLikeit()) .build(); } } \ No newline at end of file diff --git a/src/main/java/com/example/devSns/entities/Replies.java b/src/main/java/com/example/devSns/entities/Replies.java index 83a42d1..26cb482 100644 --- a/src/main/java/com/example/devSns/entities/Replies.java +++ b/src/main/java/com/example/devSns/entities/Replies.java @@ -4,10 +4,7 @@ import jakarta.validation.constraints.NotNull; import lombok.*; import org.hibernate.annotations.ColumnDefault; - import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; @Entity @NoArgsConstructor diff --git a/src/main/java/com/example/devSns/entities/Users.java b/src/main/java/com/example/devSns/entities/Users.java index 600fb2a..a5bc0a8 100644 --- a/src/main/java/com/example/devSns/entities/Users.java +++ b/src/main/java/com/example/devSns/entities/Users.java @@ -7,7 +7,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; -import java.util.Date; +import java.time.LocalDate; @Entity @NoArgsConstructor @@ -25,5 +25,5 @@ public class Users { @NotNull private Integer age; - private Date birthday; + private LocalDate birthday; } diff --git a/src/test/java/com/example/devSns/likeTest.java b/src/test/java/com/example/devSns/likeTest.java new file mode 100644 index 0000000..c320614 --- /dev/null +++ b/src/test/java/com/example/devSns/likeTest.java @@ -0,0 +1,90 @@ +package com.example.devSns; + +import com.example.devSns.dto.PostResponse; +import com.example.devSns.dto.ReplyResponse; +import com.example.devSns.entities.Posts; +import com.example.devSns.entities.Replies; +import com.example.devSns.entities.Users; +import com.example.devSns.repositories.PostRepository; +import com.example.devSns.repositories.ReplyRepository; +import com.example.devSns.repositories.UserRepository; +import com.example.devSns.services.PostService; +import com.example.devSns.services.ReplyService; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.time.LocalDateTime; + +@SpringBootTest +public class likeTest { + @Autowired + ReplyRepository replyRepository; + + @Autowired + PostRepository postRepository; + + @Autowired + UserRepository userRepository; + + @Autowired + private ReplyService replyService; + + @Autowired + private PostService postService; + + private long postId; + private long replyId; + + @BeforeEach + void setUp() { + replyRepository.deleteAll(); + postRepository.deleteAll(); + userRepository.deleteAll(); + + Users user1 = Users.builder() + .age(28) + .username("Java") + .build(); + + userRepository.save(user1); + + Users user2 = Users.builder() + .age(57) + .username("Unix") + .build(); + userRepository.save(user2); + + Posts post = Posts.builder() + .content("Hello, Java!") + .users(user1) + .build(); + postRepository.save(post); + postId = post.getId(); + + Replies reply = Replies.builder() + .posts(post) + .reply("Me too") + .createAt(LocalDateTime.now()) + .users(user2) + .build(); + + replyRepository.save(reply); + replyId = reply.getId(); + } + + @Test + public void likePostTest() { + PostResponse postResponse = postService.likePost(postId); + Assertions.assertEquals(1, postResponse.like()); + } + + @Test + public void likeReplyTest() { + ReplyResponse replyResponse = replyService.likeReply(replyId); + Assertions.assertEquals(1, replyResponse.like()); + } +} From 6bb6db24e28c558c1633cf06ad9ce751a07c682d Mon Sep 17 00:00:00 2001 From: scholar-star Date: Tue, 11 Nov 2025 16:35:10 +0900 Subject: [PATCH 16/22] =?UTF-8?q?=EC=A2=8B=EC=95=84=EC=9A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80=20Test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- .../com/example/devSns/dto/ReplyResponse.java | 4 +- .../com/example/devSns/entities/Replies.java | 3 + .../com/example/devSns/entities/Users.java | 4 +- .../java/com/example/devSns/likeTest.java | 90 ------------------- 5 files changed, 7 insertions(+), 96 deletions(-) delete mode 100644 src/test/java/com/example/devSns/likeTest.java diff --git a/build.gradle b/build.gradle index 56d88da..1552412 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.projectlombok:lombok' - implementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' compileOnly 'org.projectlombok:lombok' runtimeOnly 'org.postgresql:postgresql' diff --git a/src/main/java/com/example/devSns/dto/ReplyResponse.java b/src/main/java/com/example/devSns/dto/ReplyResponse.java index 13cb09e..a5b6b21 100644 --- a/src/main/java/com/example/devSns/dto/ReplyResponse.java +++ b/src/main/java/com/example/devSns/dto/ReplyResponse.java @@ -7,15 +7,13 @@ public record ReplyResponse( long replyId, String username, - String comment, - Integer like + String comment ) { public static ReplyResponse entityToDTO(Replies replies) { return ReplyResponse.builder() .replyId(replies.getId()) .username(replies.getUsers().getUsername()) .comment(replies.getReply()) - .like(replies.getLikeit()) .build(); } } \ No newline at end of file diff --git a/src/main/java/com/example/devSns/entities/Replies.java b/src/main/java/com/example/devSns/entities/Replies.java index 26cb482..83a42d1 100644 --- a/src/main/java/com/example/devSns/entities/Replies.java +++ b/src/main/java/com/example/devSns/entities/Replies.java @@ -4,7 +4,10 @@ import jakarta.validation.constraints.NotNull; import lombok.*; import org.hibernate.annotations.ColumnDefault; + import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; @Entity @NoArgsConstructor diff --git a/src/main/java/com/example/devSns/entities/Users.java b/src/main/java/com/example/devSns/entities/Users.java index a5bc0a8..600fb2a 100644 --- a/src/main/java/com/example/devSns/entities/Users.java +++ b/src/main/java/com/example/devSns/entities/Users.java @@ -7,7 +7,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; -import java.time.LocalDate; +import java.util.Date; @Entity @NoArgsConstructor @@ -25,5 +25,5 @@ public class Users { @NotNull private Integer age; - private LocalDate birthday; + private Date birthday; } diff --git a/src/test/java/com/example/devSns/likeTest.java b/src/test/java/com/example/devSns/likeTest.java deleted file mode 100644 index c320614..0000000 --- a/src/test/java/com/example/devSns/likeTest.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.example.devSns; - -import com.example.devSns.dto.PostResponse; -import com.example.devSns.dto.ReplyResponse; -import com.example.devSns.entities.Posts; -import com.example.devSns.entities.Replies; -import com.example.devSns.entities.Users; -import com.example.devSns.repositories.PostRepository; -import com.example.devSns.repositories.ReplyRepository; -import com.example.devSns.repositories.UserRepository; -import com.example.devSns.services.PostService; -import com.example.devSns.services.ReplyService; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Assertions.*; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; - -import java.time.LocalDateTime; - -@SpringBootTest -public class likeTest { - @Autowired - ReplyRepository replyRepository; - - @Autowired - PostRepository postRepository; - - @Autowired - UserRepository userRepository; - - @Autowired - private ReplyService replyService; - - @Autowired - private PostService postService; - - private long postId; - private long replyId; - - @BeforeEach - void setUp() { - replyRepository.deleteAll(); - postRepository.deleteAll(); - userRepository.deleteAll(); - - Users user1 = Users.builder() - .age(28) - .username("Java") - .build(); - - userRepository.save(user1); - - Users user2 = Users.builder() - .age(57) - .username("Unix") - .build(); - userRepository.save(user2); - - Posts post = Posts.builder() - .content("Hello, Java!") - .users(user1) - .build(); - postRepository.save(post); - postId = post.getId(); - - Replies reply = Replies.builder() - .posts(post) - .reply("Me too") - .createAt(LocalDateTime.now()) - .users(user2) - .build(); - - replyRepository.save(reply); - replyId = reply.getId(); - } - - @Test - public void likePostTest() { - PostResponse postResponse = postService.likePost(postId); - Assertions.assertEquals(1, postResponse.like()); - } - - @Test - public void likeReplyTest() { - ReplyResponse replyResponse = replyService.likeReply(replyId); - Assertions.assertEquals(1, replyResponse.like()); - } -} From 39a61b6de285364a19a2e08ea4cfbf97e182c479 Mon Sep 17 00:00:00 2001 From: scholar-star Date: Tue, 11 Nov 2025 16:36:51 +0900 Subject: [PATCH 17/22] =?UTF-8?q?Revert=20"=EC=A2=8B=EC=95=84=EC=9A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20Test"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 6bb6db24e28c558c1633cf06ad9ce751a07c682d. --- build.gradle | 2 +- .../com/example/devSns/dto/ReplyResponse.java | 4 +- .../com/example/devSns/entities/Replies.java | 3 - .../com/example/devSns/entities/Users.java | 4 +- .../java/com/example/devSns/likeTest.java | 90 +++++++++++++++++++ 5 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 src/test/java/com/example/devSns/likeTest.java diff --git a/build.gradle b/build.gradle index 1552412..56d88da 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.projectlombok:lombok' - testImplementation 'org.springframework.boot:spring-boot-starter-test' + implementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' compileOnly 'org.projectlombok:lombok' runtimeOnly 'org.postgresql:postgresql' diff --git a/src/main/java/com/example/devSns/dto/ReplyResponse.java b/src/main/java/com/example/devSns/dto/ReplyResponse.java index a5b6b21..13cb09e 100644 --- a/src/main/java/com/example/devSns/dto/ReplyResponse.java +++ b/src/main/java/com/example/devSns/dto/ReplyResponse.java @@ -7,13 +7,15 @@ public record ReplyResponse( long replyId, String username, - String comment + String comment, + Integer like ) { public static ReplyResponse entityToDTO(Replies replies) { return ReplyResponse.builder() .replyId(replies.getId()) .username(replies.getUsers().getUsername()) .comment(replies.getReply()) + .like(replies.getLikeit()) .build(); } } \ No newline at end of file diff --git a/src/main/java/com/example/devSns/entities/Replies.java b/src/main/java/com/example/devSns/entities/Replies.java index 83a42d1..26cb482 100644 --- a/src/main/java/com/example/devSns/entities/Replies.java +++ b/src/main/java/com/example/devSns/entities/Replies.java @@ -4,10 +4,7 @@ import jakarta.validation.constraints.NotNull; import lombok.*; import org.hibernate.annotations.ColumnDefault; - import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; @Entity @NoArgsConstructor diff --git a/src/main/java/com/example/devSns/entities/Users.java b/src/main/java/com/example/devSns/entities/Users.java index 600fb2a..a5bc0a8 100644 --- a/src/main/java/com/example/devSns/entities/Users.java +++ b/src/main/java/com/example/devSns/entities/Users.java @@ -7,7 +7,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; -import java.util.Date; +import java.time.LocalDate; @Entity @NoArgsConstructor @@ -25,5 +25,5 @@ public class Users { @NotNull private Integer age; - private Date birthday; + private LocalDate birthday; } diff --git a/src/test/java/com/example/devSns/likeTest.java b/src/test/java/com/example/devSns/likeTest.java new file mode 100644 index 0000000..c320614 --- /dev/null +++ b/src/test/java/com/example/devSns/likeTest.java @@ -0,0 +1,90 @@ +package com.example.devSns; + +import com.example.devSns.dto.PostResponse; +import com.example.devSns.dto.ReplyResponse; +import com.example.devSns.entities.Posts; +import com.example.devSns.entities.Replies; +import com.example.devSns.entities.Users; +import com.example.devSns.repositories.PostRepository; +import com.example.devSns.repositories.ReplyRepository; +import com.example.devSns.repositories.UserRepository; +import com.example.devSns.services.PostService; +import com.example.devSns.services.ReplyService; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.time.LocalDateTime; + +@SpringBootTest +public class likeTest { + @Autowired + ReplyRepository replyRepository; + + @Autowired + PostRepository postRepository; + + @Autowired + UserRepository userRepository; + + @Autowired + private ReplyService replyService; + + @Autowired + private PostService postService; + + private long postId; + private long replyId; + + @BeforeEach + void setUp() { + replyRepository.deleteAll(); + postRepository.deleteAll(); + userRepository.deleteAll(); + + Users user1 = Users.builder() + .age(28) + .username("Java") + .build(); + + userRepository.save(user1); + + Users user2 = Users.builder() + .age(57) + .username("Unix") + .build(); + userRepository.save(user2); + + Posts post = Posts.builder() + .content("Hello, Java!") + .users(user1) + .build(); + postRepository.save(post); + postId = post.getId(); + + Replies reply = Replies.builder() + .posts(post) + .reply("Me too") + .createAt(LocalDateTime.now()) + .users(user2) + .build(); + + replyRepository.save(reply); + replyId = reply.getId(); + } + + @Test + public void likePostTest() { + PostResponse postResponse = postService.likePost(postId); + Assertions.assertEquals(1, postResponse.like()); + } + + @Test + public void likeReplyTest() { + ReplyResponse replyResponse = replyService.likeReply(replyId); + Assertions.assertEquals(1, replyResponse.like()); + } +} From e52f1a228afc503a3a71d4b5fde6e3d6bd4221ef Mon Sep 17 00:00:00 2001 From: scholar-star Date: Wed, 12 Nov 2025 13:32:18 +0900 Subject: [PATCH 18/22] =?UTF-8?q?=EC=88=98=EC=A0=95=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=20=EC=B2=AB=20=EB=B2=88=EC=A7=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/devSns/dto/PostDTO.java | 6 +++++- src/main/java/com/example/devSns/entities/Posts.java | 4 ---- src/main/java/com/example/devSns/services/PostService.java | 1 - src/main/java/com/example/devSns/services/ReplyService.java | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/example/devSns/dto/PostDTO.java b/src/main/java/com/example/devSns/dto/PostDTO.java index 118ec9c..9c6a369 100644 --- a/src/main/java/com/example/devSns/dto/PostDTO.java +++ b/src/main/java/com/example/devSns/dto/PostDTO.java @@ -2,16 +2,20 @@ import com.example.devSns.entities.Posts; import com.example.devSns.entities.Users; +import jakarta.validation.constraints.NotBlank; + +import java.time.LocalDateTime; public record PostDTO( Long userId, - String username, + @NotBlank String username, String content ) { public static Posts dtoToEntity(PostDTO postDTO, Users user) { Posts postEntity = Posts.builder() .users(user) .content(postDTO.content()) + .createat(LocalDateTime.now()) .build(); return postEntity; } diff --git a/src/main/java/com/example/devSns/entities/Posts.java b/src/main/java/com/example/devSns/entities/Posts.java index d8a88ec..9c92f07 100644 --- a/src/main/java/com/example/devSns/entities/Posts.java +++ b/src/main/java/com/example/devSns/entities/Posts.java @@ -35,10 +35,6 @@ public class Posts { @Column private LocalDateTime updateat; - public void setCreateat(LocalDateTime createat) { - this.createat = createat; - } - public void setUpdateat(LocalDateTime updateat) { this.updateat = updateat; } diff --git a/src/main/java/com/example/devSns/services/PostService.java b/src/main/java/com/example/devSns/services/PostService.java index 7312b42..075031f 100644 --- a/src/main/java/com/example/devSns/services/PostService.java +++ b/src/main/java/com/example/devSns/services/PostService.java @@ -28,7 +28,6 @@ public class PostService { public PostResponse save(PostDTO postDTO) { Users user = userRepository.findById(postDTO.userId()).orElseThrow(EntityNotFoundException::new); Posts postEntity = dtoToEntity(postDTO, user); - postEntity.setCreateat(LocalDateTime.now()); Posts resultEntity = postRepository.save(postEntity); return entityToDto(resultEntity); } diff --git a/src/main/java/com/example/devSns/services/ReplyService.java b/src/main/java/com/example/devSns/services/ReplyService.java index 9193b5c..2ed513c 100644 --- a/src/main/java/com/example/devSns/services/ReplyService.java +++ b/src/main/java/com/example/devSns/services/ReplyService.java @@ -27,7 +27,7 @@ public class ReplyService { private final PostRepository postRepository; private final UserRepository userRepository; - @Transactional + @Transactional(readOnly = true) public List replyGetAll(@PathVariable long postId) { Posts post = postRepository.findById(postId).orElseThrow(); List replies = replyRepository.findByPosts(post); From b759e4b99b8689e26d31b72baf6673e00cc4ad27 Mon Sep 17 00:00:00 2001 From: scholar-star Date: Thu, 13 Nov 2025 14:14:45 +0900 Subject: [PATCH 19/22] =?UTF-8?q?=EC=88=98=EC=A0=95=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=20=EB=91=90=20=EB=B2=88=EC=A7=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/devSns/dto/PostDTO.java | 2 +- src/main/java/com/example/devSns/dto/ReplyDTO.java | 3 +++ src/main/java/com/example/devSns/entities/Replies.java | 4 ---- .../com/example/devSns/repositories/PostRepository.java | 3 ++- .../java/com/example/devSns/services/PostService.java | 7 ++++--- .../java/com/example/devSns/services/ReplyService.java | 9 ++++----- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/example/devSns/dto/PostDTO.java b/src/main/java/com/example/devSns/dto/PostDTO.java index 9c6a369..68b504a 100644 --- a/src/main/java/com/example/devSns/dto/PostDTO.java +++ b/src/main/java/com/example/devSns/dto/PostDTO.java @@ -7,7 +7,7 @@ import java.time.LocalDateTime; public record PostDTO( - Long userId, + @NotBlank Long userId, @NotBlank String username, String content ) { diff --git a/src/main/java/com/example/devSns/dto/ReplyDTO.java b/src/main/java/com/example/devSns/dto/ReplyDTO.java index c9420bf..a8acbe9 100644 --- a/src/main/java/com/example/devSns/dto/ReplyDTO.java +++ b/src/main/java/com/example/devSns/dto/ReplyDTO.java @@ -4,6 +4,8 @@ import com.example.devSns.entities.Replies; import com.example.devSns.entities.Users; +import java.time.LocalDateTime; + public record ReplyDTO( Long userID, String comment @@ -12,6 +14,7 @@ public static Replies dtoToEntity(Posts post, Users user, ReplyDTO replyDTO) { return Replies.builder() .posts(post) .users(user) + .createAt(LocalDateTime.now()) .reply(replyDTO.comment()) .build(); } diff --git a/src/main/java/com/example/devSns/entities/Replies.java b/src/main/java/com/example/devSns/entities/Replies.java index 26cb482..0ed9432 100644 --- a/src/main/java/com/example/devSns/entities/Replies.java +++ b/src/main/java/com/example/devSns/entities/Replies.java @@ -42,10 +42,6 @@ public void setReply(String reply) { this.reply = reply; } - public void setCreateAt(LocalDateTime createAt) { - this.createAt = createAt; - } - public void setUpdateAt(LocalDateTime updateAt) { this.updateAt = updateAt; } diff --git a/src/main/java/com/example/devSns/repositories/PostRepository.java b/src/main/java/com/example/devSns/repositories/PostRepository.java index eeaaae1..504b580 100644 --- a/src/main/java/com/example/devSns/repositories/PostRepository.java +++ b/src/main/java/com/example/devSns/repositories/PostRepository.java @@ -1,6 +1,7 @@ package com.example.devSns.repositories; import com.example.devSns.entities.Posts; +import com.example.devSns.entities.Users; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; @@ -9,5 +10,5 @@ public interface PostRepository extends JpaRepository { public List findAll(); public Optional findById(Integer id); - public List findByUsersId(Long userID); + public List findByUsers(Users user); } diff --git a/src/main/java/com/example/devSns/services/PostService.java b/src/main/java/com/example/devSns/services/PostService.java index 075031f..5e08492 100644 --- a/src/main/java/com/example/devSns/services/PostService.java +++ b/src/main/java/com/example/devSns/services/PostService.java @@ -26,7 +26,7 @@ public class PostService { @Transactional // 트랜잭션 보장 public PostResponse save(PostDTO postDTO) { - Users user = userRepository.findById(postDTO.userId()).orElseThrow(EntityNotFoundException::new); + Users user = userRepository.findById(postDTO.userId()).orElseThrow(() -> new EntityNotFoundException("존재하지 않는 사용자입니다.")); Posts postEntity = dtoToEntity(postDTO, user); Posts resultEntity = postRepository.save(postEntity); return entityToDto(resultEntity); @@ -43,8 +43,9 @@ public List findAll() { // 전체 post 조회 } @Transactional - public List findByUserID(Long userID) { // 작성자 기준 post 조회 - List postsByName = postRepository.findByUsersId(userID); + public List findByUserID(Long userID) { + Users user = userRepository.findById(userID).orElseThrow(() -> new EntityNotFoundException("존재하지 않는 사용자입니다."));// 작성자 기준 post 조회 + List postsByName = postRepository.findByUsers(user); List postResponses = new ArrayList<>(); for (Posts post : postsByName) { postResponses.add(entityToDto(post)); diff --git a/src/main/java/com/example/devSns/services/ReplyService.java b/src/main/java/com/example/devSns/services/ReplyService.java index 2ed513c..0a5e0fc 100644 --- a/src/main/java/com/example/devSns/services/ReplyService.java +++ b/src/main/java/com/example/devSns/services/ReplyService.java @@ -29,7 +29,7 @@ public class ReplyService { @Transactional(readOnly = true) public List replyGetAll(@PathVariable long postId) { - Posts post = postRepository.findById(postId).orElseThrow(); + Posts post = postRepository.findById(postId).orElseThrow(() -> new EntityNotFoundException("존재하지 않는 게시글입니다.")); List replies = replyRepository.findByPosts(post); List repliesResponse = new ArrayList<>(); for (Replies reply: replies) { @@ -40,10 +40,9 @@ public List replyGetAll(@PathVariable long postId) { @Transactional public ReplyResponse writeReply(@PathVariable long postId, ReplyDTO reply) { - Posts post = postRepository.findById(postId).orElseThrow(EntityNotFoundException::new); - Users user = userRepository.findById(reply.userID()).orElseThrow(EntityNotFoundException::new); + Posts post = postRepository.findById(postId).orElseThrow(() -> new EntityNotFoundException("존재하지 않는 게시글입니다.")); + Users user = userRepository.findById(reply.userID()).orElseThrow(() -> new EntityNotFoundException("존재하지 않는 사용자입니다.")); Replies replyEntity = ReplyDTO.dtoToEntity(post, user, reply); - replyEntity.setCreateAt(LocalDateTime.now()); replyRepository.save(replyEntity); return ReplyResponse.entityToDTO(replyEntity); } @@ -58,7 +57,7 @@ public ReplyResponse likeReply(@PathVariable long replyId) { @Transactional public ReplyResponse updateReply (@PathVariable long replyId, ReplyDTO reply) { - Users user = userRepository.findById(reply.userID()).orElseThrow(); + Users user = userRepository.findById(reply.userID()).orElseThrow(() -> new EntityNotFoundException("존재하지 않는 사용자입니다.")); if(user.getId() != reply.userID()) { throw new SecurityException(); } From 3042d2a411a15b282c3096446abe4a0a45818807 Mon Sep 17 00:00:00 2001 From: scholar-star Date: Fri, 14 Nov 2025 12:36:33 +0900 Subject: [PATCH 20/22] =?UTF-8?q?Post=20=EA=B2=80=EC=83=89=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devSns/controllers/PostController.java | 6 ++ .../devSns/repositories/PostRepository.java | 1 + .../devSns/repositories/UserRepository.java | 3 + .../example/devSns/services/PostService.java | 10 +++ .../java/com/example/devSns/searchTest.java | 83 +++++++++++++++++++ 5 files changed, 103 insertions(+) create mode 100644 src/test/java/com/example/devSns/searchTest.java diff --git a/src/main/java/com/example/devSns/controllers/PostController.java b/src/main/java/com/example/devSns/controllers/PostController.java index 2e4b56e..588c5b5 100644 --- a/src/main/java/com/example/devSns/controllers/PostController.java +++ b/src/main/java/com/example/devSns/controllers/PostController.java @@ -27,6 +27,12 @@ public ResponseEntity> showPost(@PathVariable Long userID) { return new ResponseEntity<>(post, HttpStatus.OK); } + @GetMapping("/show/{content}") + public ResponseEntity> showPost(@PathVariable String content) { + List post = postService.findByContent(content); + return new ResponseEntity<>(post, HttpStatus.OK); + } + @PostMapping("/add") public ResponseEntity addPost(@RequestBody PostDTO postDTO) { PostResponse postResponse = postService.save(postDTO); diff --git a/src/main/java/com/example/devSns/repositories/PostRepository.java b/src/main/java/com/example/devSns/repositories/PostRepository.java index 504b580..1e0d690 100644 --- a/src/main/java/com/example/devSns/repositories/PostRepository.java +++ b/src/main/java/com/example/devSns/repositories/PostRepository.java @@ -11,4 +11,5 @@ public interface PostRepository extends JpaRepository { public List findAll(); public Optional findById(Integer id); public List findByUsers(Users user); + public List findByContentContaining(String partialContent); } diff --git a/src/main/java/com/example/devSns/repositories/UserRepository.java b/src/main/java/com/example/devSns/repositories/UserRepository.java index 9be1992..9247cfa 100644 --- a/src/main/java/com/example/devSns/repositories/UserRepository.java +++ b/src/main/java/com/example/devSns/repositories/UserRepository.java @@ -3,6 +3,9 @@ import com.example.devSns.entities.Users; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + public interface UserRepository extends JpaRepository { public Users findById(long userId); + public List findByUsernameContaining(String partialUsername); } diff --git a/src/main/java/com/example/devSns/services/PostService.java b/src/main/java/com/example/devSns/services/PostService.java index 5e08492..1d88fb0 100644 --- a/src/main/java/com/example/devSns/services/PostService.java +++ b/src/main/java/com/example/devSns/services/PostService.java @@ -53,6 +53,16 @@ public List findByUserID(Long userID) { return postResponses; } + @Transactional + public List findByContent(String content) { + List postsByContent = postRepository.findByContentContaining(content); + List postResponses = new ArrayList<>(); + for (Posts post : postsByContent) { + postResponses.add(entityToDto(post)); + } + return postResponses; + } + @Transactional public PostResponse update(Long id, PostDTO postDTO) { // 수정된 post 반영 Posts postEntity = postRepository.findById(id) diff --git a/src/test/java/com/example/devSns/searchTest.java b/src/test/java/com/example/devSns/searchTest.java new file mode 100644 index 0000000..1785fe3 --- /dev/null +++ b/src/test/java/com/example/devSns/searchTest.java @@ -0,0 +1,83 @@ +package com.example.devSns; + +import com.example.devSns.dto.PostResponse; +import com.example.devSns.entities.Posts; +import com.example.devSns.entities.Replies; +import com.example.devSns.entities.Users; +import com.example.devSns.repositories.PostRepository; +import com.example.devSns.repositories.ReplyRepository; +import com.example.devSns.repositories.UserRepository; +import com.example.devSns.services.PostService; +import com.example.devSns.services.ReplyService; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +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; + +@SpringBootTest +public class searchTest { + @Autowired + ReplyRepository replyRepository; + + @Autowired + PostRepository postRepository; + + @Autowired + UserRepository userRepository; + + @Autowired + private ReplyService replyService; + + @Autowired + private PostService postService; + + private long postId; + private long replyId; + + @BeforeEach + void setUp() { + replyRepository.deleteAll(); + postRepository.deleteAll(); + userRepository.deleteAll(); + + Users user1 = Users.builder() + .age(28) + .username("Java") + .build(); + + userRepository.save(user1); + + Users user2 = Users.builder() + .age(57) + .username("Unix") + .build(); + userRepository.save(user2); + + Posts post = Posts.builder() + .content("Hello, Java!") + .users(user1) + .build(); + postRepository.save(post); + postId = post.getId(); + + Replies reply = Replies.builder() + .posts(post) + .reply("Me too") + .createAt(LocalDateTime.now()) + .users(user2) + .build(); + + replyRepository.save(reply); + replyId = reply.getId(); + } + + @Test + public void likePostTest() { + List list = postService.findByContent("Hello"); + Assertions.assertEquals(1, list.size()); + } +} From b6cfd3d6867bea40ed356207eec2b62daa813e5d Mon Sep 17 00:00:00 2001 From: scholar-star Date: Thu, 27 Nov 2025 14:53:05 +0900 Subject: [PATCH 21/22] =?UTF-8?q?JWT=20=ED=86=A0=ED=81=B0=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20&=20=EC=9D=B8=EA=B0=80=20=EB=A7=A4=EC=BB=A4?= =?UTF-8?q?=EB=8B=88=EC=A6=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devSns/authorities/MemberDetails.java | 29 ++++++++ .../authorities/MemberDetailsService.java | 19 ++++++ .../com/example/devSns/authorities/Role.java | 6 ++ .../com/example/devSns/config/WebConfig.java | 23 +++++++ .../devSns/controllers/PostController.java | 4 +- .../devSns/controllers/UserController.java | 25 +++++++ .../java/com/example/devSns/dto/JwtDTO.java | 8 +++ .../java/com/example/devSns/dto/LoginDTO.java | 6 ++ .../java/com/example/devSns/dto/UserDTO.java | 24 +++++++ .../com/example/devSns/entities/Users.java | 7 +- .../devSns/repositories/UserRepository.java | 2 + .../example/devSns/services/UserService.java | 39 +++++++++++ .../com/example/devSns/util/JwtFilter.java | 42 ++++++++++++ .../java/com/example/devSns/util/JwtUtil.java | 68 +++++++++++++++++++ .../exceptions/GlobalExceptionHandler.java | 7 ++ 15 files changed, 306 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/example/devSns/authorities/MemberDetails.java create mode 100644 src/main/java/com/example/devSns/authorities/MemberDetailsService.java create mode 100644 src/main/java/com/example/devSns/authorities/Role.java create mode 100644 src/main/java/com/example/devSns/config/WebConfig.java create mode 100644 src/main/java/com/example/devSns/controllers/UserController.java create mode 100644 src/main/java/com/example/devSns/dto/JwtDTO.java create mode 100644 src/main/java/com/example/devSns/dto/LoginDTO.java create mode 100644 src/main/java/com/example/devSns/dto/UserDTO.java create mode 100644 src/main/java/com/example/devSns/services/UserService.java create mode 100644 src/main/java/com/example/devSns/util/JwtFilter.java create mode 100644 src/main/java/com/example/devSns/util/JwtUtil.java diff --git a/src/main/java/com/example/devSns/authorities/MemberDetails.java b/src/main/java/com/example/devSns/authorities/MemberDetails.java new file mode 100644 index 0000000..9146a9e --- /dev/null +++ b/src/main/java/com/example/devSns/authorities/MemberDetails.java @@ -0,0 +1,29 @@ +package com.example.devSns.authorities; + +import com.example.devSns.entities.Users; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; + +@RequiredArgsConstructor +public class MemberDetails implements UserDetails { + private final Users user; + + @Override + public Collection getAuthorities() { + + } + + @Override + public String getUsername() { + + } + + @Override + public String getPassword() { + return null; + } +} + diff --git a/src/main/java/com/example/devSns/authorities/MemberDetailsService.java b/src/main/java/com/example/devSns/authorities/MemberDetailsService.java new file mode 100644 index 0000000..c6b6c88 --- /dev/null +++ b/src/main/java/com/example/devSns/authorities/MemberDetailsService.java @@ -0,0 +1,19 @@ +package com.example.devSns.authorities; + +import com.example.devSns.entities.Users; +import com.example.devSns.repositories.UserRepository; +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; + +@Service +public class MemberDetailsService implements UserDetailsService { + private UserRepository userRepository; + + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + Users user = userRepository.findByLoginID(username).orElseThrow(); + MemberDetails memberDetails = new MemberDetails(user); + return memberDetails; + } +} diff --git a/src/main/java/com/example/devSns/authorities/Role.java b/src/main/java/com/example/devSns/authorities/Role.java new file mode 100644 index 0000000..ff5c47c --- /dev/null +++ b/src/main/java/com/example/devSns/authorities/Role.java @@ -0,0 +1,6 @@ +package com.example.devSns.authorities; + +public enum Role { + ROLE_USER, + ROLE_ADMIN +} diff --git a/src/main/java/com/example/devSns/config/WebConfig.java b/src/main/java/com/example/devSns/config/WebConfig.java new file mode 100644 index 0000000..e4cf24d --- /dev/null +++ b/src/main/java/com/example/devSns/config/WebConfig.java @@ -0,0 +1,23 @@ +package com.example.devSns.config; + +import com.example.devSns.util.JwtFilter; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +// Interceptor 추가 가능 +@Configuration +@EnableWebSecurity +@RequiredArgsConstructor +public class WebConfig { + + private final JwtFilter jwtFilter; + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/src/main/java/com/example/devSns/controllers/PostController.java b/src/main/java/com/example/devSns/controllers/PostController.java index 588c5b5..f0ee0b3 100644 --- a/src/main/java/com/example/devSns/controllers/PostController.java +++ b/src/main/java/com/example/devSns/controllers/PostController.java @@ -27,8 +27,8 @@ public ResponseEntity> showPost(@PathVariable Long userID) { return new ResponseEntity<>(post, HttpStatus.OK); } - @GetMapping("/show/{content}") - public ResponseEntity> showPost(@PathVariable String content) { + @GetMapping("/search/{content}") + public ResponseEntity> searchPost(@PathVariable String content) { List post = postService.findByContent(content); return new ResponseEntity<>(post, HttpStatus.OK); } diff --git a/src/main/java/com/example/devSns/controllers/UserController.java b/src/main/java/com/example/devSns/controllers/UserController.java new file mode 100644 index 0000000..bb1a6d8 --- /dev/null +++ b/src/main/java/com/example/devSns/controllers/UserController.java @@ -0,0 +1,25 @@ +package com.example.devSns.controllers; + +import com.example.devSns.dto.LoginDTO; +import com.example.devSns.dto.UserDTO; +import com.example.devSns.services.UserService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class UserController { + private final UserService userService; + + @PostMapping + public String signup(@RequestBody UserDTO userInfo) { + + } + + @PostMapping + public String login(@RequestBody LoginDTO loginDTO) { + + } +} diff --git a/src/main/java/com/example/devSns/dto/JwtDTO.java b/src/main/java/com/example/devSns/dto/JwtDTO.java new file mode 100644 index 0000000..b5c4df6 --- /dev/null +++ b/src/main/java/com/example/devSns/dto/JwtDTO.java @@ -0,0 +1,8 @@ +package com.example.devSns.dto; + +import lombok.Builder; + +@Builder +public record JwtDTO( + String token +) {} diff --git a/src/main/java/com/example/devSns/dto/LoginDTO.java b/src/main/java/com/example/devSns/dto/LoginDTO.java new file mode 100644 index 0000000..fd9cd0c --- /dev/null +++ b/src/main/java/com/example/devSns/dto/LoginDTO.java @@ -0,0 +1,6 @@ +package com.example.devSns.dto; + +public record LoginDTO ( + String loginID, + String password +) {} diff --git a/src/main/java/com/example/devSns/dto/UserDTO.java b/src/main/java/com/example/devSns/dto/UserDTO.java new file mode 100644 index 0000000..4de8c85 --- /dev/null +++ b/src/main/java/com/example/devSns/dto/UserDTO.java @@ -0,0 +1,24 @@ +package com.example.devSns.dto; + +import com.example.devSns.entities.Users; + + +import java.time.LocalDate; + +public record UserDTO ( + String username, + String loginID, + String password, + Integer age, + LocalDate birthDay +) { + public static Users dtoToEntity(UserDTO userDTO) { + return Users.builder() + .username(userDTO.username()) + .loginID(userDTO.loginID()) + .password(userDTO.password()) + .birthday(userDTO.birthDay()) + .age(userDTO.age()) + .build(); + } +} diff --git a/src/main/java/com/example/devSns/entities/Users.java b/src/main/java/com/example/devSns/entities/Users.java index a5bc0a8..8c50278 100644 --- a/src/main/java/com/example/devSns/entities/Users.java +++ b/src/main/java/com/example/devSns/entities/Users.java @@ -20,9 +20,14 @@ public class Users { private long id; @NotNull - private String username; + private String loginID; + + @NotNull + private String password; @NotNull + private String username; + private Integer age; private LocalDate birthday; diff --git a/src/main/java/com/example/devSns/repositories/UserRepository.java b/src/main/java/com/example/devSns/repositories/UserRepository.java index 9247cfa..0bf51ef 100644 --- a/src/main/java/com/example/devSns/repositories/UserRepository.java +++ b/src/main/java/com/example/devSns/repositories/UserRepository.java @@ -4,8 +4,10 @@ import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; +import java.util.Optional; public interface UserRepository extends JpaRepository { public Users findById(long userId); public List findByUsernameContaining(String partialUsername); + public Optional findByLoginID(String loginID); } diff --git a/src/main/java/com/example/devSns/services/UserService.java b/src/main/java/com/example/devSns/services/UserService.java new file mode 100644 index 0000000..f6de122 --- /dev/null +++ b/src/main/java/com/example/devSns/services/UserService.java @@ -0,0 +1,39 @@ +package com.example.devSns.services; + +import com.example.devSns.authorities.Role; +import com.example.devSns.dto.JwtDTO; +import com.example.devSns.dto.LoginDTO; +import com.example.devSns.dto.UserDTO; +import com.example.devSns.entities.Users; +import com.example.devSns.repositories.UserRepository; +import com.example.devSns.util.JwtUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class UserService { + private final UserRepository userRepository; + private final JwtUtil jwtUtil; + + public String signUp(UserDTO userDTO) { + Users user = UserDTO.dtoToEntity(userDTO); + userRepository.save(user); + return "회원가입 성공!"; + } + + public JwtDTO login(LoginDTO loginDTO) { + Users findUser = userRepository.findByLoginID(loginDTO.loginID()) + .orElseThrow(() -> new AuthenticationCredentialsNotFoundException("잘못된 아이디 또는 비밀번호입니다.")); + if(!findUser.getPassword().equals(loginDTO.password())) + throw new AuthenticationCredentialsNotFoundException("잘못된 아이디 또는 비밀번호입니다."); + else { + String jwt = jwtUtil.generateToken(findUser.getLoginID(), findUser.getUsername(), Role.ROLE_USER); + JwtDTO jwtDTO = JwtDTO.builder() + .token(jwt) + .build(); + return jwtDTO; + } + } +} diff --git a/src/main/java/com/example/devSns/util/JwtFilter.java b/src/main/java/com/example/devSns/util/JwtFilter.java new file mode 100644 index 0000000..00d6b3a --- /dev/null +++ b/src/main/java/com/example/devSns/util/JwtFilter.java @@ -0,0 +1,42 @@ +package com.example.devSns.util; + +import com.example.devSns.authorities.MemberDetailsService; +import com.example.devSns.authorities.Role; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; + +@Component +@RequiredArgsConstructor +public class JwtFilter extends OncePerRequestFilter { + private final JwtUtil jwtUtil; + private final MemberDetailsService memberDetailsService; + + @Override + protected void doFilterInternal(HttpServletRequest req, HttpServletResponse resp, FilterChain chain) + throws IOException, ServletException { + String authorizationHeader = req.getHeader("Authorization"); + + if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { // Authorization header : 앞에 Bearer 있는지 확인 + String token = authorizationHeader.substring(7); // token 추출 + if (jwtUtil.validateToken(token)) { + String userID = jwtUtil.getUserID(token); + Role userRole = jwtUtil.getRole(token); + + UserDetails userDetail = memberDetailsService.loadUserByUsername(userID); + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + SecurityContextHolder.getContext().setAuthentication(auth); + } + chain.doFilter(req, resp); + } + } +} diff --git a/src/main/java/com/example/devSns/util/JwtUtil.java b/src/main/java/com/example/devSns/util/JwtUtil.java new file mode 100644 index 0000000..d451932 --- /dev/null +++ b/src/main/java/com/example/devSns/util/JwtUtil.java @@ -0,0 +1,68 @@ +package com.example.devSns.util; + +import com.example.devSns.authorities.Role; +import com.example.devSns.dto.UserDTO; +import io.jsonwebtoken.*; +import io.jsonwebtoken.security.Keys; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.security.Key; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +@Component +public class JwtUtil { + @Value("${secretKey}") + private String secretKey; + + public Jws parseToken(String token) { + Key key = Keys.hmacShaKeyFor(secretKey.getBytes()); + + return Jwts.parserBuilder() + .setSigningKey(key) + .build() + .parseClaimsJws(token); + } + + public String generateToken(String loginID, String username, Role role) { + Key key = Keys.hmacShaKeyFor(secretKey.getBytes()); + + Map claims = new HashMap<>(); + + claims.put("loginID", loginID); + claims.put("username", username); + claims.put("role", role); + + String jwtToken = Jwts.builder() + .setHeaderParam("typ", "JWT") + .setHeaderParam("alg", "HS256") + .setClaims(claims) + .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 30)) + .signWith(key, SignatureAlgorithm.HS256) + .compact(); + + return jwtToken; + } + + public boolean validateToken(String token) { + try { + parseToken(token); + return true; + } catch(JwtException e) { + return false; + } + } + + public String getUserID(String token) { + Key key = Keys.hmacShaKeyFor(secretKey.getBytes()); + Claims claims = parseToken(token).getBody(); + return claims.get("loginID", String.class); + } + + public Role getRole(String token) { + Claims claims = parseToken(token).getBody(); + return Role.valueOf(claims.get("role", String.class)); + } +} diff --git a/src/main/java/exceptions/GlobalExceptionHandler.java b/src/main/java/exceptions/GlobalExceptionHandler.java index b1edc11..f2db8be 100644 --- a/src/main/java/exceptions/GlobalExceptionHandler.java +++ b/src/main/java/exceptions/GlobalExceptionHandler.java @@ -32,4 +32,11 @@ public ResponseEntity handleSecurityException(SecurityException e) { new ResponseEntity<>("접근 권한 없음", HttpStatus.FORBIDDEN); return response; } + + @ExceptionHandler + public ResponseEntity handleLoginErrorException(AuthenticationException e) { + ResponseEntity response = + new ResponseEntity<>("잘못된 아이디 또는 비밀번호입니다.", HttpStatus.UNAUTHORIZED); + return response; + } } From 60a42323ae1b6cea5139aa042bb5dd74722ac78d Mon Sep 17 00:00:00 2001 From: scholar-star Date: Thu, 27 Nov 2025 16:17:07 +0900 Subject: [PATCH 22/22] =?UTF-8?q?=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20&?= =?UTF-8?q?=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=A0=95=EC=83=81=EB=8F=99?= =?UTF-8?q?=EC=9E=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devSns/authorities/MemberDetails.java | 7 +++++-- .../com/example/devSns/config/WebConfig.java | 10 +++++++++ .../devSns/controllers/UserController.java | 21 +++++++++++++------ .../java/com/example/devSns/dto/UserDTO.java | 6 +++++- .../com/example/devSns/entities/Users.java | 5 +++++ .../example/devSns/services/UserService.java | 8 ++++++- .../com/example/devSns/util/JwtFilter.java | 2 ++ 7 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/example/devSns/authorities/MemberDetails.java b/src/main/java/com/example/devSns/authorities/MemberDetails.java index 9146a9e..dedcde4 100644 --- a/src/main/java/com/example/devSns/authorities/MemberDetails.java +++ b/src/main/java/com/example/devSns/authorities/MemberDetails.java @@ -5,6 +5,7 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; +import java.util.ArrayList; import java.util.Collection; @RequiredArgsConstructor @@ -13,12 +14,14 @@ public class MemberDetails implements UserDetails { @Override public Collection getAuthorities() { - + Collection authorities = new ArrayList<>(); + authorities.add(() -> user.getRole().toString()); + return authorities; } @Override public String getUsername() { - + return user.getLoginID(); } @Override diff --git a/src/main/java/com/example/devSns/config/WebConfig.java b/src/main/java/com/example/devSns/config/WebConfig.java index e4cf24d..b6a2158 100644 --- a/src/main/java/com/example/devSns/config/WebConfig.java +++ b/src/main/java/com/example/devSns/config/WebConfig.java @@ -4,9 +4,11 @@ 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.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; // Interceptor 추가 가능 @Configuration @@ -20,4 +22,12 @@ public class WebConfig { public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } + + @Bean + SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http.authorizeHttpRequests(authorizeRequests -> + authorizeRequests.requestMatchers("/sns/signup", "/sns/login").permitAll() + .anyRequest().authenticated()).csrf(csrf -> csrf.disable()); + return http.build(); + } } diff --git a/src/main/java/com/example/devSns/controllers/UserController.java b/src/main/java/com/example/devSns/controllers/UserController.java index bb1a6d8..47bfa6e 100644 --- a/src/main/java/com/example/devSns/controllers/UserController.java +++ b/src/main/java/com/example/devSns/controllers/UserController.java @@ -1,25 +1,34 @@ package com.example.devSns.controllers; +import com.example.devSns.dto.JwtDTO; import com.example.devSns.dto.LoginDTO; import com.example.devSns.dto.UserDTO; import com.example.devSns.services.UserService; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController +@RequestMapping("/sns") @RequiredArgsConstructor +@Slf4j public class UserController { private final UserService userService; - @PostMapping - public String signup(@RequestBody UserDTO userInfo) { - + @PostMapping("/signup") + public ResponseEntity signup(@RequestBody UserDTO userInfo) { + String resp = userService.signUp(userInfo); + ResponseEntity response = new ResponseEntity(resp, HttpStatus.OK); + return response; } - @PostMapping - public String login(@RequestBody LoginDTO loginDTO) { - + @PostMapping("/login") + public ResponseEntity login(@RequestBody LoginDTO loginDTO) { + return new ResponseEntity<>(userService.login(loginDTO), HttpStatus.OK); } } diff --git a/src/main/java/com/example/devSns/dto/UserDTO.java b/src/main/java/com/example/devSns/dto/UserDTO.java index 4de8c85..d6bfbea 100644 --- a/src/main/java/com/example/devSns/dto/UserDTO.java +++ b/src/main/java/com/example/devSns/dto/UserDTO.java @@ -1,6 +1,8 @@ package com.example.devSns.dto; import com.example.devSns.entities.Users; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; import java.time.LocalDate; @@ -13,10 +15,12 @@ public record UserDTO ( LocalDate birthDay ) { public static Users dtoToEntity(UserDTO userDTO) { + PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + return Users.builder() .username(userDTO.username()) .loginID(userDTO.loginID()) - .password(userDTO.password()) + .password(passwordEncoder.encode(userDTO.password())) .birthday(userDTO.birthDay()) .age(userDTO.age()) .build(); diff --git a/src/main/java/com/example/devSns/entities/Users.java b/src/main/java/com/example/devSns/entities/Users.java index 8c50278..c489577 100644 --- a/src/main/java/com/example/devSns/entities/Users.java +++ b/src/main/java/com/example/devSns/entities/Users.java @@ -1,5 +1,6 @@ package com.example.devSns.entities; +import com.example.devSns.authorities.Role; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; @@ -31,4 +32,8 @@ public class Users { private Integer age; private LocalDate birthday; + + @Builder.Default + @Enumerated(EnumType.STRING) + private Role role = Role.ROLE_USER; } diff --git a/src/main/java/com/example/devSns/services/UserService.java b/src/main/java/com/example/devSns/services/UserService.java index f6de122..fe50510 100644 --- a/src/main/java/com/example/devSns/services/UserService.java +++ b/src/main/java/com/example/devSns/services/UserService.java @@ -8,15 +8,21 @@ import com.example.devSns.repositories.UserRepository; import com.example.devSns.util.JwtUtil; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @RequiredArgsConstructor @Service +@Slf4j public class UserService { private final UserRepository userRepository; private final JwtUtil jwtUtil; + private final PasswordEncoder passwordEncoder; + @Transactional public String signUp(UserDTO userDTO) { Users user = UserDTO.dtoToEntity(userDTO); userRepository.save(user); @@ -26,7 +32,7 @@ public String signUp(UserDTO userDTO) { public JwtDTO login(LoginDTO loginDTO) { Users findUser = userRepository.findByLoginID(loginDTO.loginID()) .orElseThrow(() -> new AuthenticationCredentialsNotFoundException("잘못된 아이디 또는 비밀번호입니다.")); - if(!findUser.getPassword().equals(loginDTO.password())) + if(!passwordEncoder.matches(loginDTO.password(), findUser.getPassword())) throw new AuthenticationCredentialsNotFoundException("잘못된 아이디 또는 비밀번호입니다."); else { String jwt = jwtUtil.generateToken(findUser.getLoginID(), findUser.getUsername(), Role.ROLE_USER); diff --git a/src/main/java/com/example/devSns/util/JwtFilter.java b/src/main/java/com/example/devSns/util/JwtFilter.java index 00d6b3a..372e61d 100644 --- a/src/main/java/com/example/devSns/util/JwtFilter.java +++ b/src/main/java/com/example/devSns/util/JwtFilter.java @@ -38,5 +38,7 @@ protected void doFilterInternal(HttpServletRequest req, HttpServletResponse resp } chain.doFilter(req, resp); } + + chain.doFilter(req, resp); } }