-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[댓글 기능] 제이 미션 제출합니다. #107
[댓글 기능] 제이 미션 제출합니다. #107
Changes from all commits
dd87430
a2287b4
940525c
5430d29
1f9ef73
8dced8c
9a3475c
8731d42
66751cd
8901bf4
07ebbc1
f2e700e
1961b76
f44d9ff
8ef6ba5
dc2a199
087e5e0
15e570a
47ae91d
6e9726b
c2ea962
e6f5579
3e2bd3e
63235c6
924cee2
7c83e30
bb280ba
e00061f
614121c
8d0188b
7a76891
2553842
c2f89df
dbe40f5
8985502
e537451
c48f2f6
e2fec3b
6f21dfa
0ed6e1b
615e6fd
0e6e088
5447551
cefea32
b4d7ea5
e42ed91
b90115e
9f8190b
59eaeb7
95ae854
09b41c6
840253b
49fbaa5
52a6d6c
f4537c5
ed42da0
cabf579
ccb502d
8eb91d1
cc93b1a
5304a84
0c28a01
b4ef0a2
85ff44c
c915849
fc5aa5c
ed0e739
e743f49
411388d
6be9e90
c1b252e
8454227
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,21 +7,20 @@ | |
import techcourse.myblog.service.dto.UserRequest; | ||
|
||
@Component | ||
public class AppRunner implements ApplicationRunner { | ||
public class Runner implements ApplicationRunner { | ||
private UserService userService; | ||
|
||
public AppRunner(UserService userService) { | ||
public Runner(UserService userService) { | ||
this.userService = userService; | ||
} | ||
|
||
@Override | ||
public void run(ApplicationArguments args) { | ||
public void run(ApplicationArguments args) throws Exception { | ||
UserRequest userRequest = new UserRequest(); | ||
userRequest.setName("CU"); | ||
userRequest.setEmail("[email protected]"); | ||
userRequest.setPassword("PassWord!1"); | ||
userRequest.setReconfirmPassword("PassWord!1"); | ||
|
||
userRequest.setPassword("Password!1"); | ||
userRequest.setReconfirmPassword("Password!1"); | ||
userService.saveUser(userRequest); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package techcourse.myblog.domain; | ||
|
||
import org.hibernate.annotations.OnDelete; | ||
import org.hibernate.annotations.OnDeleteAction; | ||
import org.springframework.data.jpa.domain.support.AuditingEntityListener; | ||
import techcourse.myblog.domain.common.ContentsAudit; | ||
|
||
import javax.persistence.*; | ||
|
||
@Entity | ||
@EntityListeners(value = AuditingEntityListener.class) | ||
public class Comment extends ContentsAudit { | ||
@Lob | ||
@Column(nullable = false) | ||
private String contents; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 현재 구조에서는 contents는 varchar(255)로 세팅될텐데요. 더 긴 문자열을 받을 수 있도록 데이터타입을 바꿔주는 것은 어떨까요 |
||
|
||
@ManyToOne | ||
@JoinColumn(foreignKey = @ForeignKey(name = "FK_comment_to_user"), nullable = false) | ||
@OnDelete(action = OnDeleteAction.CASCADE) | ||
private User commenter; | ||
|
||
@ManyToOne | ||
@JoinColumn(foreignKey = @ForeignKey(name = "FK_comment_to_article"), nullable = false) | ||
@OnDelete(action = OnDeleteAction.CASCADE) | ||
private Article article; | ||
|
||
private Comment() { | ||
} | ||
|
||
public Comment(String contents, Article article, User user) { | ||
checkContents(contents); | ||
this.contents = contents; | ||
this.article = article; | ||
this.commenter = user; | ||
} | ||
|
||
private void checkContents(String contents) { | ||
if (contents == null) { | ||
throw new IllegalArgumentException("본문이 없습니다"); | ||
} | ||
} | ||
|
||
public Long getId() { | ||
return id; | ||
} | ||
|
||
public String getContents() { | ||
return contents; | ||
} | ||
|
||
public User getCommenter() { | ||
return commenter; | ||
} | ||
|
||
public Article getArticle() { | ||
return article; | ||
} | ||
|
||
public Comment updateContents(String contents) { | ||
this.contents = contents; | ||
return this; | ||
} | ||
|
||
public boolean isCommentor(User commenter) { | ||
return this.commenter.equals(commenter); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package techcourse.myblog.domain; | ||
|
||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
import java.util.List; | ||
import java.util.Optional; | ||
|
||
public interface CommentRepository extends JpaRepository<Comment, Long> { | ||
List<Comment> findByArticle(Article article); | ||
|
||
Optional<Comment> findByCommenterAndId(User commenter, Long id); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,7 @@ | ||
package techcourse.myblog.domain; | ||
|
||
import javax.persistence.Entity; | ||
import javax.persistence.GeneratedValue; | ||
import javax.persistence.GenerationType; | ||
import javax.persistence.Id; | ||
import javax.persistence.*; | ||
import java.util.Objects; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
|
@@ -16,8 +14,13 @@ public class User { | |
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@Column(nullable = false, length = 50) | ||
private String name; | ||
|
||
@Column(nullable = false) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. java bean validator를 사용하여 email 등 포맷의 유효성 검증을 할 수 있어요 |
||
private String email; | ||
|
||
@Column(nullable = false) | ||
private String password; | ||
|
||
private User() { | ||
|
@@ -46,8 +49,8 @@ public void changeName(String name) { | |
this.name = name; | ||
} | ||
|
||
public boolean matchPassword(String password) { | ||
return this.password.equals(password); | ||
public boolean matchEmail(User user) { | ||
return this.email.equals(user.email); | ||
} | ||
|
||
public Long getId() { | ||
|
@@ -65,4 +68,17 @@ public String getEmail() { | |
public String getPassword() { | ||
return password; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
User user = (User) o; | ||
return Objects.equals(id, user.id); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(id); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package techcourse.myblog.domain.common; | ||
|
||
import org.springframework.data.annotation.CreatedDate; | ||
import org.springframework.data.annotation.LastModifiedDate; | ||
import org.springframework.data.jpa.domain.support.AuditingEntityListener; | ||
|
||
import javax.persistence.*; | ||
import java.time.LocalDateTime; | ||
|
||
@MappedSuperclass | ||
@EntityListeners(value = AuditingEntityListener.class) | ||
public abstract class ContentsAudit { | ||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
protected Long id; | ||
|
||
@CreatedDate | ||
private LocalDateTime createdDate; | ||
|
||
@LastModifiedDate | ||
private LocalDateTime lastModifiedDate; | ||
|
||
public Long getId() { | ||
return id; | ||
} | ||
|
||
public LocalDateTime getCreatedDate() { | ||
return createdDate; | ||
} | ||
|
||
public LocalDateTime getLastModifiedDate() { | ||
return lastModifiedDate; | ||
} | ||
|
||
public void setId(Long id) { | ||
this.id = id; | ||
} | ||
|
||
public void setCreatedDate(LocalDateTime createdDate) { | ||
this.createdDate = createdDate; | ||
} | ||
|
||
public void setLastModifiedDate(LocalDateTime lastModifiedDate) { | ||
this.lastModifiedDate = lastModifiedDate; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,18 @@ | ||
package techcourse.myblog.service; | ||
|
||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.PageRequest; | ||
import org.springframework.data.domain.Sort; | ||
import org.springframework.stereotype.Service; | ||
import techcourse.myblog.domain.Article; | ||
import techcourse.myblog.domain.ArticleRepository; | ||
import techcourse.myblog.domain.User; | ||
import techcourse.myblog.service.dto.ArticleRequest; | ||
import techcourse.myblog.service.exception.InvalidAuthorException; | ||
import techcourse.myblog.service.exception.NoArticleException; | ||
import techcourse.myblog.service.exception.ResourceNotFoundException; | ||
|
||
import javax.transaction.Transactional; | ||
import java.util.List; | ||
|
||
@Service | ||
public class ArticleService { | ||
|
@@ -17,29 +22,54 @@ public ArticleService(ArticleRepository articleRepository) { | |
this.articleRepository = articleRepository; | ||
} | ||
|
||
public List<Article> findAll() { | ||
return articleRepository.findAll(); | ||
public Page<Article> findAll(int page) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
return articleRepository.findAll( | ||
PageRequest.of(page - 1, 10, Sort.by("id").descending())); | ||
} | ||
|
||
public Article save(ArticleRequest articleRequest) { | ||
Article article = new Article(articleRequest.getTitle(), | ||
articleRequest.getCoverUrl(), articleRequest.getContents()); | ||
public Article save(ArticleRequest articleRequest, User user) { | ||
Article article = createArticle(articleRequest); | ||
article.setAuthor(user); | ||
return articleRepository.save(article); | ||
} | ||
|
||
private Article createArticle(ArticleRequest articleRequest) { | ||
try { | ||
return new Article(articleRequest.getTitle(), articleRequest.getCoverUrl(), articleRequest.getContents()); | ||
} catch (Exception e) { | ||
throw new ResourceNotFoundException(e.getMessage()); | ||
} | ||
} | ||
|
||
public Article findById(long articleId) { | ||
return articleRepository.findById(articleId) | ||
.orElseThrow(() -> new NoArticleException("게시글이 존재하지 않습니다")); | ||
} | ||
|
||
public Article findByIdWithUser(long articleId, User user) { | ||
Article article = articleRepository.findById(articleId) | ||
.orElseThrow(() -> new NoArticleException("게시글이 존재하지 않습니다")); | ||
checkAuthor(user, article); | ||
return article; | ||
} | ||
|
||
@Transactional | ||
public Article editArticle(ArticleRequest articleRequest, long articleId) { | ||
public Article editArticle(ArticleRequest articleRequest, long articleId, User user) { | ||
Article article = articleRepository.findById(articleId).orElseThrow(IllegalArgumentException::new); | ||
checkAuthor(user, article); | ||
article.updateArticle(new Article(articleRequest.getTitle(), articleRequest.getCoverUrl(), articleRequest.getContents())); | ||
return article; | ||
} | ||
|
||
public void deleteById(long articleId) { | ||
private void checkAuthor(User user, Article article) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
if (!article.isAuthor(user)) { | ||
throw new InvalidAuthorException("작성자가 아닙니다"); | ||
} | ||
} | ||
|
||
public void deleteById(long articleId, User user) { | ||
Article article = articleRepository.findById(articleId).orElseThrow(IllegalArgumentException::new); | ||
checkAuthor(user, article); | ||
articleRepository.deleteById(articleId); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오! ApplicationRunner를 사용하셨군요!
이 외에도 스프링 구동되는 시점에 Component를 주입하는 여러가지 방법들이 있으니 참고하세요
https://yuien.tistory.com/entry/스프링-시작시점에서-프로그램-동작할-수-있게-하는-방법