일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- spring
- Hibernate
- 프로그래머스
- 코딩테스트
- JPA
- PDF병합
- querydsl
- 제작기
- 스프링부트 쇼핑몰 프로젝트
- 알고리즘
- VB
- GitFlow
- DOCS
- spring jpa
- 값 타입
- 연관관계
- responsepart
- springboot
- 반복문 탈출
- Git
- Visual Basic
- 멋쟁이사자처럼
- 체인호출
- 테킷
- 커밋 컨벤션
- orm
- break-label
- Java
- 부트캠프
- PDFBOX
Archives
- Today
- Total
섭섭한 개발일지
QueryDSL JPA 1:N 관계에서 N의 조건 추가 본문
프로젝트에서 데이터의 삭제를 물리적 삭제가 아닌 논리적 삭제로 처리를 하고 있다.
그렇기에 데이터를 조회할 때 해당 데이터의 삭제일자 값을 통해 삭제 여부를 확인하는데 1:N 관계의 entity에서 고민이 생겼다.
문의내역에는 답변이 존재하는데 이는 1:N 관계이고 엔티티는 아래와 같이 생겼다.
public class Question extends BaseEntity {
@Comment("문의사항 작성자")
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id", columnDefinition = "BIGINT", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
private Member member;
@Comment("문의사항 제목")
@Column(name = "title", columnDefinition = "VARCHAR(200)")
private String title;
@Comment("문의사항 내용")
@Column(name = "content", columnDefinition = "MEDIUMTEXT")
private String content;
@Comment("답변 여부")
@Column(name = "status", columnDefinition = "VARCHAR(20)")
@Convert(converter = QuestionStatusConverter.class)
private QuestionStatus status;
@Builder.Default
@OneToMany(fetch = FetchType.LAZY, mappedBy = "question")
private List<Answer> answers = new ArrayList<>();
public void addMember(Member member) {
this.member = member;
member.getQuestions().add(this);
}
public void updateQuestion(String title, String content) {
this.title = title;
this.content = content;
}
public void updateStatus(QuestionStatus status) {
this.status = status;
}
}
public class Answer extends BaseEntity {
@Comment("문의사항 답변 작성자")
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id", columnDefinition = "BIGINT", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
private Member member;
@Comment("답변이 속한 문의사항")
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "question_id", columnDefinition = "BIGINT", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
private Question question;
@Comment("답변 내용")
@Column(name = "content", columnDefinition = "MEDIUMTEXT")
private String content;
public void addQuestion(Question question) {
this.question = question;
this.question.updateStatus(QuestionStatus.COMPLETE);
question.getAnswers().add(this);
}
public void updateContent(String updateContent) {
this.content = updateContent;
}
}
Answer은 직접 조회하는게 아닌 대게 Question 을 통해서 조회가 되는데
쉽게 생각한다면 아래와 같이 쿼리메서드를 통해서 처리를 할 수 있을거다.
Optional<Question> findByIdAndDeletedAtIsNullAndAnswersDeletedAtIsNull(Long id);
하지만 이는 JPA 쿼리메서드 규칙을 위반한 것으로 동작이 되지 않는다.
JPQL을 작성해도 되지만 이것 또한 프로젝트에서 최대한 QueryDSL JPA 를 활용하기로 하여 아래와 같이 작성을 하였다.
@Override
public Optional<Question> findQuestion(Long id) {
BooleanExpression conditions =
question.id.eq(id)
.and(question.deletedAt.isNull())
.and(answer.deletedAt.isNull());
return Optional.of(jpaQueryFactory
.selectFrom(question)
.leftJoin(question.answers, answer).fetchJoin()
.where(conditions)
.fetchFirst());
}
나는 where에서 사용을 하는 조건 절을 BooleanExpression 을 통해서 미리 생성을 하고 최대한 queryFactory를 보기 쉽게 가져가는 것이 가독성에 좋다고 생각하여 이러한 선택을 했다.
'프로그래밍 > JPA' 카테고리의 다른 글
QueryDSL JPA로 생성된지 일정시간이 지난 데이터 가져오기 (0) | 2024.03.21 |
---|---|
프록시 객체의 클래스 타입 비교 문제 (0) | 2024.03.19 |
JPA에서 CDATA 사용하기 (0) | 2023.05.03 |
[필기용] 자바 ORM 표준 JPA 프로그래밍 Ch09 (0) | 2023.02.28 |
[필기용] 자바 ORM 표준 JPA 프로그래밍 Ch08 (0) | 2023.02.14 |
Comments