@Builder
public Post(String title, String content, String author) {
this.title = title;
this.content = content;
this.author = author;
this.createdAt = LocalDateTime.now(); // 직접 설정
this.updatedAt = LocalDateTime.now(); // 직접 설정
}
public void update(String title, String content) {
this.title = title;
this.content = content;
this.updatedAt = LocalDateTime.now(); // 직접 설정
}
모든 Entity에서 LocalDateTime.now()를 직접 호출합니다. Comment Entity에도, 나중에 User Entity에도 같은 코드가 반복됩니다. 실수로 빠뜨리면 null이 들어갑니다.
// PostService에서 직접 Builder 호출
Post post = Post.builder()
.title(request.getTitle())
.content(request.getContent())
.author(request.getAuthor())
.build();
// PostListResponse에서 from() 메서드
PostListResponse.from(post);
// PostDetailResponse에서도 from() 메서드
PostDetailResponse.from(post);
Request DTO → Entity 변환은 서비스에서 직접 하고, Entity → Response DTO 변환은 DTO의 from()에서 합니다. 일관성이 없습니다.
// PostService.getPost()
Post post = postRepository.findById(id)
.orElseThrow(() -> new RuntimeException("게시글을 찾을 수 없습니다: " + id));
// PostService.updatePost()
Post post = postRepository.findById(id)
.orElseThrow(() -> new RuntimeException("게시글을 찾을 수 없습니다: " + id));
// PostService.deletePost()
Post post = postRepository.findById(id)
.orElseThrow(() -> new RuntimeException("게시글을 찾을 수 없습니다: " + id));
같은 조회 + 예외 처리 코드가 3번 반복됩니다.
이번 수업에서 이 문제들을 전부 해결합니다.
JPA Auditing을 쓰면 createdAt, updatedAt을 자동으로 관리해줍니다. LocalDateTime.now()를 직접 호출할 필요가 없습니다.
메인 클래스에 @EnableJpaAuditing을 추가합니다:
@SpringBootApplication
@EnableJpaAuditing // 추가
public class BoardApplication {
public static void main(String[] args) {
SpringApplication.run(BoardApplication.class, args);
}
}
모든 Entity가 상속할 공통 Entity를 만듭니다:
package com.myname.board.entity;
import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import java.time.LocalDateTime;
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;
}