Skip to content

Commit 5b99e69

Browse files
committed
feat: post 도메인 추가
1 parent 03cd211 commit 5b99e69

File tree

12 files changed

+439
-0
lines changed

12 files changed

+439
-0
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.back.domain.post.category.entity;
2+
3+
import jakarta.persistence.Column;
4+
import jakarta.persistence.Entity;
5+
import jakarta.persistence.EntityListeners;
6+
import jakarta.persistence.GeneratedValue;
7+
import jakarta.persistence.GenerationType;
8+
import jakarta.persistence.Id;
9+
import jakarta.persistence.Table;
10+
import lombok.AllArgsConstructor;
11+
import lombok.Builder;
12+
import lombok.Getter;
13+
import lombok.NoArgsConstructor;
14+
import lombok.Setter;
15+
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
16+
17+
@Entity
18+
@Getter
19+
@Setter
20+
@Table(name = "category")
21+
@EntityListeners(AuditingEntityListener.class)
22+
@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED)
23+
@AllArgsConstructor
24+
@Builder
25+
public class Category {
26+
// 각 게시글 카테고리을 구분하는 유일한 번호
27+
@Id
28+
@GeneratedValue(strategy = GenerationType.IDENTITY)
29+
@Column(name = "id")
30+
private Long id;
31+
32+
// 카테고리 이름
33+
@Column(name = "name", nullable = false, unique = true, length = 50)
34+
private String name;
35+
36+
// 카테고리 설명
37+
@Column(name = "description", length = 200)
38+
private String description;
39+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.back.domain.post.category.repository;
2+
3+
import com.back.domain.post.category.entity.Category;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
import org.springframework.stereotype.Repository;
6+
7+
@Repository
8+
public interface CategoryRepository extends JpaRepository<Category, Long> {
9+
10+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.back.domain.post.post.controller;
2+
3+
import com.back.domain.post.post.dto.request.PostRequestDto;
4+
import com.back.domain.post.post.dto.response.PostResponseDto;
5+
import com.back.domain.post.post.entity.Post;
6+
import com.back.domain.post.post.service.PostService;
7+
import com.back.global.rsData.RsData;
8+
import java.util.List;
9+
import lombok.RequiredArgsConstructor;
10+
import org.springframework.web.bind.annotation.GetMapping;
11+
import org.springframework.web.bind.annotation.PostMapping;
12+
import org.springframework.web.bind.annotation.RequestBody;
13+
import org.springframework.web.bind.annotation.RequestMapping;
14+
import org.springframework.web.bind.annotation.RestController;
15+
16+
@RestController
17+
@RequestMapping("/api/posts")
18+
@RequiredArgsConstructor
19+
public class PostController {
20+
21+
private final PostService postService;
22+
23+
/**
24+
* 게시글 작성 API
25+
* @param postRequestDto 게시글 작성 요청 DTO
26+
* @return 작성된 게시글 정보
27+
*/
28+
@PostMapping
29+
public RsData<PostResponseDto> createPost(
30+
@RequestBody PostRequestDto postRequestDto
31+
) {
32+
return RsData.successOf(postService.createPost(postRequestDto)); // code=200, message="success"
33+
}
34+
35+
/**
36+
* 게시글 다건 조회 API
37+
* @return 모든 게시글 리스트
38+
*/
39+
@GetMapping
40+
public RsData<List<Post>> getAllPosts() {
41+
List<Post> posts = postService.getAllPosts();
42+
return RsData.successOf(posts); // code=200, message="success"
43+
}
44+
45+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.back.domain.post.post.dto.request;
2+
3+
import java.util.List;
4+
5+
public record PostRequestDto(
6+
Long categoryId,
7+
String title,
8+
String content,
9+
String userNickName,
10+
String imageUrl,
11+
List<String> tags
12+
) {
13+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.back.domain.post.post.dto.response;
2+
3+
import com.back.domain.post.post.entity.Post;
4+
import com.back.domain.post.post.enums.PostStatus;
5+
import java.time.LocalDateTime;
6+
import java.util.List;
7+
8+
public record PostResponseDto(
9+
Long postId,
10+
String categoryName,
11+
String userNickName,
12+
LocalDateTime createdAt,
13+
LocalDateTime updatedAt,
14+
PostStatus status,
15+
String title,
16+
String content,
17+
String imageUrl,
18+
List<String> tags,
19+
Integer likeCount,
20+
Integer commentCount,
21+
Integer viewCount
22+
) {
23+
24+
public PostResponseDto(Post post) {
25+
this(
26+
post.getId(),
27+
post.getCategory().getName(),
28+
post.getUser().getNickname(),
29+
post.getCreatedAt(),
30+
post.getUpdatedAt(),
31+
post.getStatus(),
32+
post.getTitle(),
33+
post.getContent(),
34+
post.getImageUrl(),
35+
post.getPostTags().stream()
36+
.map(postTag -> postTag.getTag().getName())
37+
.toList(),
38+
post.getLikeCount(),
39+
post.getCommentCount(),
40+
post.getViewCount()
41+
);
42+
}
43+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package com.back.domain.post.post.entity;
2+
3+
import com.back.domain.post.category.entity.Category;
4+
import com.back.domain.post.post.enums.PostStatus;
5+
import com.back.domain.user.entity.User;
6+
import jakarta.persistence.CascadeType;
7+
import jakarta.persistence.Column;
8+
import jakarta.persistence.Entity;
9+
import jakarta.persistence.EntityListeners;
10+
import jakarta.persistence.EnumType;
11+
import jakarta.persistence.Enumerated;
12+
import jakarta.persistence.FetchType;
13+
import jakarta.persistence.GeneratedValue;
14+
import jakarta.persistence.GenerationType;
15+
import jakarta.persistence.Id;
16+
import jakarta.persistence.JoinColumn;
17+
import jakarta.persistence.ManyToOne;
18+
import jakarta.persistence.OneToMany;
19+
import jakarta.persistence.Table;
20+
import java.time.LocalDateTime;
21+
import java.util.ArrayList;
22+
import java.util.List;
23+
import lombok.AllArgsConstructor;
24+
import lombok.Builder;
25+
import lombok.Getter;
26+
import lombok.NoArgsConstructor;
27+
import lombok.Setter;
28+
import org.springframework.data.annotation.CreatedDate;
29+
import org.springframework.data.annotation.LastModifiedDate;
30+
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
31+
32+
@Entity
33+
@Getter
34+
@Setter
35+
@Table(name = "post")
36+
@EntityListeners(AuditingEntityListener.class)
37+
@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED)
38+
@AllArgsConstructor
39+
@Builder
40+
public class Post {
41+
42+
// 각 게시글을 구분하는 유일한 번호
43+
@Id
44+
@GeneratedValue(strategy = GenerationType.IDENTITY)
45+
@Column(name = "id")
46+
private Long id;
47+
48+
// 해당 게시글의 카테고리 고유 식별자
49+
@ManyToOne(fetch = FetchType.LAZY)
50+
@JoinColumn(name = "category_id")
51+
private Category category;
52+
53+
// 해당 게시글을 작성한 유저의 고유 식별자
54+
@ManyToOne(fetch = FetchType.LAZY)
55+
@JoinColumn(name = "user_id")
56+
private User user;
57+
58+
// 게시글 작성 날짜
59+
@CreatedDate
60+
private LocalDateTime createdAt;
61+
62+
// 게시글 수정 날짜
63+
@LastModifiedDate
64+
private LocalDateTime updatedAt;
65+
66+
// 게시글 게시 상태 (기본값: 공개)
67+
@Builder.Default
68+
@Enumerated(EnumType.STRING)
69+
@Column(name = "status", nullable = false)
70+
private PostStatus status = PostStatus.PUBLIC;
71+
72+
// 게시글 제목
73+
@Column(name = "title", nullable = false, length = 100)
74+
private String title;
75+
76+
// 게시글 내용
77+
@Column(name = "content", nullable = false, columnDefinition = "TEXT")
78+
private String content;
79+
80+
// 게시글 이미지 URL
81+
@Column(name = "image_url")
82+
private String imageUrl;
83+
84+
@OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true)
85+
private List<PostTag> postTags = new ArrayList<>();
86+
87+
// 게시글 추천 수 (기본값: 0)
88+
@Builder.Default
89+
@Column(name = "like_count", nullable = false)
90+
private Integer likeCount = 0;
91+
92+
// 게시글 댓글 수
93+
@Column(name = "comment_count")
94+
private Integer commentCount;
95+
96+
// 게시글 조회 수
97+
@Column(name = "view_count")
98+
private Integer viewCount;
99+
100+
public void addTag(Tag tag) {
101+
PostTag postTag = PostTag.create(this, tag);
102+
this.postTags.add(postTag);
103+
}
104+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.back.domain.post.post.entity;
2+
3+
import jakarta.persistence.Column;
4+
import jakarta.persistence.Entity;
5+
import jakarta.persistence.EntityListeners;
6+
import jakarta.persistence.FetchType;
7+
import jakarta.persistence.GeneratedValue;
8+
import jakarta.persistence.GenerationType;
9+
import jakarta.persistence.Id;
10+
import jakarta.persistence.JoinColumn;
11+
import jakarta.persistence.ManyToOne;
12+
import jakarta.persistence.Table;
13+
import lombok.AccessLevel;
14+
import lombok.Builder;
15+
import lombok.Getter;
16+
import lombok.NoArgsConstructor;
17+
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
18+
19+
@Entity
20+
@Getter
21+
@Table(name = "post_tag")
22+
@EntityListeners(AuditingEntityListener.class)
23+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
24+
public class PostTag {
25+
26+
@Id
27+
@GeneratedValue(strategy = GenerationType.IDENTITY)
28+
@Column(name = "id")
29+
private Long id;
30+
31+
@ManyToOne(fetch = FetchType.LAZY)
32+
@JoinColumn(name = "post_id")
33+
private Post post;
34+
35+
@ManyToOne(fetch = FetchType.LAZY)
36+
@JoinColumn(name = "tag_id")
37+
private Tag tag;
38+
39+
@Builder
40+
public PostTag(Post post, Tag tag) {
41+
this.post = post;
42+
this.tag = tag;
43+
}
44+
45+
// 정적 팩토리 메서드
46+
public static PostTag create(Post post, Tag tag) {
47+
return PostTag.builder()
48+
.post(post)
49+
.tag(tag)
50+
.build();
51+
}
52+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.back.domain.post.post.entity;
2+
3+
import jakarta.persistence.Column;
4+
import jakarta.persistence.Entity;
5+
import jakarta.persistence.GeneratedValue;
6+
import jakarta.persistence.Id;
7+
import jakarta.persistence.Table;
8+
import lombok.AccessLevel;
9+
import lombok.AllArgsConstructor;
10+
import lombok.Builder;
11+
import lombok.Getter;
12+
import lombok.NoArgsConstructor;
13+
14+
@Entity
15+
@Getter
16+
@Table(name = "tag")
17+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
18+
@AllArgsConstructor
19+
@Builder
20+
public class Tag { // Tag는 Post와 직접적인 관계를 맺지 않습니다.
21+
22+
@Id
23+
@GeneratedValue
24+
@Column(name = "id")
25+
private Long id;
26+
27+
@Column(unique = true, nullable = false)
28+
private String name;
29+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.back.domain.post.post.enums;
2+
3+
import lombok.Getter;
4+
import lombok.RequiredArgsConstructor;
5+
6+
@Getter
7+
@RequiredArgsConstructor
8+
public enum PostStatus {
9+
PUBLIC("공개", "모든 사용자가 볼 수 있는 상태"),
10+
PRIVATE("비공개", "작성자만 볼 수 있는 상태"),
11+
DELETED("삭제됨", "삭제 처리된 게시글 상태");
12+
13+
private final String title;
14+
private final String description;
15+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.back.domain.post.post.repository;
2+
3+
import com.back.domain.post.post.entity.Post;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
import org.springframework.stereotype.Repository;
6+
7+
@Repository
8+
public interface PostRepository extends JpaRepository<Post, Long> {
9+
10+
}

0 commit comments

Comments
 (0)