-
Notifications
You must be signed in to change notification settings - Fork 5
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
[BE] createdAt 설정을 위한 BaseEntity 적용 #700
Changes from all commits
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 |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package server.haengdong.config; | ||
|
||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.data.jpa.repository.config.EnableJpaAuditing; | ||
|
||
@Configuration | ||
@EnableJpaAuditing | ||
public class JpaConfig { | ||
} | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package server.haengdong.domain; | ||
|
||
import jakarta.persistence.Column; | ||
import jakarta.persistence.EntityListeners; | ||
import jakarta.persistence.MappedSuperclass; | ||
import java.time.Instant; | ||
import lombok.Getter; | ||
import org.springframework.data.annotation.CreatedDate; | ||
import org.springframework.data.annotation.LastModifiedDate; | ||
import org.springframework.data.jpa.domain.support.AuditingEntityListener; | ||
|
||
@Getter | ||
@EntityListeners(AuditingEntityListener.class) | ||
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. EntityListeners는 어떻게 동작하나요? 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.
@Entity
@EntityListeners(UserListener.class)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// getters and setters
}
public class UserListener {
@PrePersist
public void prePersist(User user) {
// 엔티티가 저장되기 전에 호출되는 메서드
System.out.println("User is about to be persisted: " + user.getName());
}
@PreUpdate
public void preUpdate(User user) {
// 엔티티가 업데이트되기 전에 호출되는 메서드
System.out.println("User is about to be updated: " + user.getName());
}
...
}
위 코드에서는 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. 오! |
||
@MappedSuperclass | ||
public abstract class BaseEntity { | ||
|
||
@Column(updatable = false) | ||
@CreatedDate | ||
private Instant createdAt; | ||
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. Instant는 무엇을 의미하나요? 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.
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. UTC 기반 시간이라 지역과 상관없이 적용할 수 있겠군요! 👍 행동대장의 글로벌화를 기원합니다. |
||
|
||
@LastModifiedDate | ||
private Instant updatedAt; | ||
} |
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.
이 class는 어떤 용도인가요?
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.
먼저
@EnableJpaAuditing
애너테이션은 Spring Data Jpa 엔티티의 생성 및 수정 시간을 자동으로 관리하기 위한 감사 기능을 활성화하는 애너테이션 입니다.@CreatedDate
로 엔티티의 생성 날짜 및 시간을 자동으로 설정합니다.@LastModifiedDate
로 엔티티의 수정 날짜 및 시간을 자동으로 업데이트 합니다. 이 애너테이션은AuditingHandler
및 관련 빈들을 애플리케이션 컨텍스트에 등록하며, JPA 메타 모델을 필요로 합니다.@EnableJpaAuditing
애너테이션이@SpringBootApplication
애너테이션이 붙어있는HaengdongApplication
클래스에 붙여도 동작합니다. 그렇다면 왜@EnableJpaAuditing
애너테이션을 별도의JpaConfig
클래스에 분리하여 붙였을까요?그 이유는
@SpringBootTest
,@WebMvcTest
애너테이션을 사용하는 테스트에서@SpringBootApplication
애너테이션을 통해 컴포넌트 스캔하여 컨텍스트를 설정하기 때문입니다.@SpringBootApplication
애너테이션은@ComponentScan
을 포함하고 있어서 해당 패키지를 포함한 하위 패키지에서@Component
,@Controller
,@Service
,@Repository
가 붙어있는 클래스들을 빈으로 등록합니다.@EnableJpaAuditing
애너테이션은 내부적으로@Import(JpaAuditingRegistrar.class)
를 사용합니다. 이@Import
애너테이션은 지정된 클래스를 Spring의ApplicationContext
에 등록하도록 지시합니다.JpaAuditingRegistrar
클래스는 JPA 감사 기능을 설정하는 데 필요한 빈을 등록하는 역할을 합니다. 이 클래스는@Configuration
애너테이션을 통해 Spring의 설정 클래스로 인식됩니다.@EnableJpaAuditing
이 사용된 클래스가 컴포넌트 스캔의 범위 내에 있으면, Spring Boot는 이 애너테이션을 감지하고JpaAuditingRegistrar
를 통해 JPA 감사 기능을 설정합니다. 이 과정에서JpaAuditingHandler
,AuditorAware
,DateTimeProvider
와 같은 관련 빈들이 생성됩니다.문제는
@WebMvcTest
기반 테스트의 경우@SpringBootApplication
애너테이션이 붙어있는 클래스를 통해 컨텍스트를 생성하는데,@EnableJpaAuditing
애너테이션이 존재하는 경우JpaAuditingHandler
빈이 생성되고, 이 빈은 JPA 메타모델에 의존합니다. 하지만@WebMvcTest
기반 테스트는 Service, Repository와 같은 다른 계층의 빈들은 로드하지 않고 웹 관련 빈들만 로드하기 때문에 JPA 엔티티, Repository 등이 로드되지 않아서 메타 모델이 비어있기 때문에JPA metamodel must not be empty
에러가 발생합니다.@WebMvcTest
기반의 테스트를 실행하여@SpringBootApplication
가 붙어있는 클래스를 찾고 해당 클래스를 기반으로 웹 관련 빈들만 컴포넌트 스캔하여 컨텍스트를 생성하는데, 이전처럼@SpringBootApplication
과 함께 두어@EnableJpaAuditing
애너테이션을 스캔하지 않도록JpaConfig
클래스로 분리하여JpaAuditingHandler
빈이 생성될 때 JPA 메타 모델을 의존할 수 없어서 발생하는 문제를 막을 수 있습니다.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.
자세한 설명 감사합니다 👍
@WebMvcTest
에서 빈 주입이 안되는 오류를 막기 위함이었군요. 처음 알았네요!