Skip to content
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

[1단계 - 엔티티 매핑] 디투 미션 제출합니다 #61

Open
wants to merge 31 commits into
base: shb03323
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
4cf81f7
feat: properties 설정
shb03323 Jul 6, 2023
75a7bad
feat: jpa config
shb03323 Jul 6, 2023
83ae245
feat: createdAt, updatedAt 객체 생성
shb03323 Jul 6, 2023
b120040
feat: 테이블 엔티티 생성
shb03323 Jul 6, 2023
dfdcc30
refactor: 레포지토리 패키지 분리
shb03323 Jul 6, 2023
22ae0f7
refactor: 설정파일을 yml로 변경
shb03323 Jul 6, 2023
becfbb7
test: User update 메서드 테스트 코드 작성
shb03323 Jul 7, 2023
e97691e
test: 질문과 답변에 대한 테스트 코드 작성
shb03323 Jul 7, 2023
6b9960a
refactor: 생성일자, 수정일자 entity 명 변경
shb03323 Jul 11, 2023
a5a37c3
refactor: equals and hashcode 재정의
shb03323 Jul 11, 2023
94b5d1d
refactor: 연관관계 매핑 수정
shb03323 Jul 11, 2023
e63ad95
refactor: application.properties 삭제
shb03323 Jul 11, 2023
e7b59be
test: 사용자 id 조회 테스트 작성
shb03323 Jul 11, 2023
c2322de
test: 삭제되지 않은 질문 조회 테스트 작성
shb03323 Jul 11, 2023
857df74
test: 삭제되지 않은 질문중에서 식별자로 조회 테스트 작성
shb03323 Jul 11, 2023
6aa5168
chore: 테스트 설정 파일에 sql 로깅 추가
shb03323 Jul 11, 2023
ea2793e
refactor: question 엔티티의 작성자를 변경하지 못하도록 설정
shb03323 Jul 11, 2023
112e461
refactor: 엔티티에 필요없는 세터 제거
shb03323 Jul 11, 2023
7f7ca56
test: repository fixture 파일 생성
shb03323 Jul 11, 2023
510c055
test: 삭제되지 않은 답변 중에서 질문을 식별자로 조회하는 테스트 작성
shb03323 Jul 11, 2023
a6f69f4
test: 질문 식별자로 삭제되지 않은 답변 조회 테스트 작성
shb03323 Jul 12, 2023
672844c
refactor: repository 테스트 패키지 구조 변경
shb03323 Jul 12, 2023
3ff066e
feat: Question equals & hashcode 재정의
shb03323 Jul 12, 2023
6a829f3
test: Question 테스트 변수명 수정
shb03323 Jul 12, 2023
fa203a4
test: Answer 엔티티 테스트 사용하지 않는 변수 제거
shb03323 Jul 12, 2023
099dda3
test: 답변의 식별자로 답변을 검색할 때, 삭제된 경우 검색 안되는 테스트 작성
shb03323 Jul 12, 2023
b5af277
test: 레포지터리 Fixture 작성
shb03323 Jul 12, 2023
19a9bea
test: Answer 레포지터리 테스트 Fixture 적용
shb03323 Jul 12, 2023
0b0de7d
refactor: 레포지토리 test 패키지 구조 변경
shb03323 Jul 12, 2023
9b8e2af
refactor: entity 외래키 제약 조건 이름 설정
shb03323 Jul 17, 2023
32ca40f
test: 모든 data jpa test를 RepositoryTestConfig 상속하도록 함
shb03323 Jul 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/main/java/qna/config/JpaConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package qna.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@Configuration(proxyBeanMethods = false)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

proxyBeanMethods = false 설정을 추가하신 이유가 궁금해요~

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 궁금해요!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. CGLIB의 기능을 추가적으로 이용할 것이 없습니다.
  2. 굳이 proxy로 감싸지 않아서 성능상의 이점을 챙길 수 있습니다.
  3. 스프링 공식 문서는 수동 컨피규레이션에 proxyBeanMethods = false를 주로 사용하고 있습니다.

@EnableJpaAuditing
public class JpaConfig {
}
63 changes: 34 additions & 29 deletions src/main/java/qna/domain/Answer.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,36 @@
import qna.NotFoundException;
import qna.UnAuthorizedException;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.ForeignKey;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import java.util.Objects;

public class Answer {
@Entity
public class Answer extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long writerId;
private Long questionId;
@ManyToOne
@JoinColumn(name = "writer_id", foreignKey = @ForeignKey(name = "fk_answer_writer"))
private User writer;
@ManyToOne
@JoinColumn(name = "question_id", foreignKey = @ForeignKey(name = "fk_answer_to_question"))
private Question question;
@Lob
private String contents;
@Column
private boolean deleted = false;

protected Answer() {}

public Answer(User writer, Question question, String contents) {
this(null, writer, question, contents);
}
Expand All @@ -27,51 +48,35 @@ public Answer(Long id, User writer, Question question, String contents) {
throw new NotFoundException();
}

this.writerId = writer.getId();
this.questionId = question.getId();
this.writer = writer;
this.question = question;
this.contents = contents;
}

public boolean isOwner(User writer) {
return this.writerId.equals(writer.getId());
return this.writer.equals(writer);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User객체의 equals 를 활용하셨군요!
writer가 갖고있는 어떤 필드를 기준으로 동일한지 판단하는지 궁금합니다~

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

꼼꼼하지 못했습니다. id 필드를 기준으로 equals & hashcode 를 넣었습니다.

}

public void toQuestion(Question question) {
this.questionId = question.getId();
this.question = question;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public Long getWriterId() {
return writerId;
}

public void setWriterId(Long writerId) {
this.writerId = writerId;
}

public Long getQuestionId() {
return questionId;
public User getWriter() {
return writer;
}

public void setQuestionId(Long questionId) {
this.questionId = questionId;
public Question getQuestion() {
return question;
}

public String getContents() {
return contents;
}

public void setContents(String contents) {
this.contents = contents;
}

public boolean isDeleted() {
return deleted;
}
Expand All @@ -84,8 +89,8 @@ public void setDeleted(boolean deleted) {
public String toString() {
return "Answer{" +
"id=" + id +
", writerId=" + writerId +
", questionId=" + questionId +
", writer.id=" + writer.getId() +
", question.id=" + question.getId() +
", contents='" + contents + '\'' +
", deleted=" + deleted +
'}';
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/qna/domain/BaseEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package qna.domain;

import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {

@CreatedDate
@Column(updatable = false)
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;

public LocalDateTime getCreatedAt() {
return createdAt;
}

public LocalDateTime getUpdatedAt() {
return updatedAt;
}
}
39 changes: 30 additions & 9 deletions src/main/java/qna/domain/DeleteHistory.java
Original file line number Diff line number Diff line change
@@ -1,36 +1,57 @@
package qna.domain;

import org.springframework.data.annotation.CreatedDate;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.ForeignKey;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import java.time.LocalDateTime;
import java.util.Objects;

@Entity
public class DeleteHistory {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Enumerated(EnumType.STRING)
private ContentType contentType;
@Column
private Long contentId;
private Long deletedById;
@ManyToOne
@JoinColumn(name = "deleted_by_id", foreignKey = @ForeignKey(name = "fk_delete_history_to_user"))
private User deletedBy;
@CreatedDate
private LocalDateTime createDate = LocalDateTime.now();

public DeleteHistory(ContentType contentType, Long contentId, Long deletedById, LocalDateTime createDate) {
public DeleteHistory(ContentType contentType, Long contentId, User deletedBy, LocalDateTime createDate) {
this.contentType = contentType;
this.contentId = contentId;
this.deletedById = deletedById;
this.deletedBy = deletedBy;
this.createDate = createDate;
}

protected DeleteHistory() {
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DeleteHistory that = (DeleteHistory) o;
return Objects.equals(id, that.id) &&
contentType == that.contentType &&
Objects.equals(contentId, that.contentId) &&
Objects.equals(deletedById, that.deletedById);
return Objects.equals(id, that.id);
}

@Override
public int hashCode() {
return Objects.hash(id, contentType, contentId, deletedById);
return Objects.hash(id);
}

@Override
Expand All @@ -39,7 +60,7 @@ public String toString() {
"id=" + id +
", contentType=" + contentType +
", contentId=" + contentId +
", deletedById=" + deletedById +
", deletedBy.Id=" + deletedBy.getId() +
", createDate=" + createDate +
'}';
}
Expand Down
77 changes: 53 additions & 24 deletions src/main/java/qna/domain/Question.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,39 @@
package qna.domain;

public class Question {
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.ForeignKey;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Entity
public class Question extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 100, nullable = false)
private String title;
@Lob
private String contents;
private Long writerId;
private boolean deleted = false;
@ManyToOne
@JoinColumn(name = "writer_id", updatable = false, foreignKey = @ForeignKey(name = "fk_question_writer"))
private User writer;
@Column(nullable = false)
private boolean deleted;
@OneToMany(mappedBy = "question")
private List<Answer> answers = new ArrayList<>();

protected Question() {
}

public Question(String title, String contents) {
this(null, title, contents);
Expand All @@ -18,12 +46,12 @@ public Question(Long id, String title, String contents) {
}

public Question writeBy(User writer) {
this.writerId = writer.getId();
this.writer = writer;
return this;
}

public boolean isOwner(User writer) {
return this.writerId.equals(writer.getId());
return this.writer.equals(writer);
}

public void addAnswer(Answer answer) {
Expand All @@ -34,32 +62,16 @@ public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getContents() {
return contents;
}

public void setContents(String contents) {
this.contents = contents;
}

public Long getWriterId() {
return writerId;
}

public void setWriterId(Long writerId) {
this.writerId = writerId;
public User getWriter() {
return writer;
}

public boolean isDeleted() {
Expand All @@ -70,13 +82,30 @@ public void setDeleted(boolean deleted) {
this.deleted = deleted;
}

public List<Answer> getAnswers() {
return answers;
}

@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (!(o instanceof Question)) return false;
Question question = (Question) o;
return Objects.equals(id, question.id);
}

@Override
public int hashCode() {
return Objects.hash(id);
}

@Override
public String toString() {
return "Question{" +
"id=" + id +
", title='" + title + '\'' +
", contents='" + contents + '\'' +
", writerId=" + writerId +
", writer.id=" + writer.getId() +
", deleted=" + deleted +
'}';
}
Expand Down
Loading