From 4125b50c46ec90c16362e3cc5e50bf27108489cd Mon Sep 17 00:00:00 2001 From: SungbinYang Date: Sun, 4 Jan 2026 15:25:59 +0900 Subject: [PATCH] chore: add JPA Auditing and BaseEntity configuration --- .../common/entity/BaseDateTimeEntity.kt | 31 +++++++++++++++++++ .../common/entity/BaseEntity.kt | 20 ++++++++++++ .../config/audit/AuditConfig.kt | 16 ++++++++++ .../config/audit/AuditorAwareImpl.kt | 22 +++++++++++++ 4 files changed, 89 insertions(+) create mode 100644 src/main/kotlin/im/grit/infrastructure/common/entity/BaseDateTimeEntity.kt create mode 100644 src/main/kotlin/im/grit/infrastructure/common/entity/BaseEntity.kt create mode 100644 src/main/kotlin/im/grit/infrastructure/config/audit/AuditConfig.kt create mode 100644 src/main/kotlin/im/grit/infrastructure/config/audit/AuditorAwareImpl.kt diff --git a/src/main/kotlin/im/grit/infrastructure/common/entity/BaseDateTimeEntity.kt b/src/main/kotlin/im/grit/infrastructure/common/entity/BaseDateTimeEntity.kt new file mode 100644 index 0000000..d36f136 --- /dev/null +++ b/src/main/kotlin/im/grit/infrastructure/common/entity/BaseDateTimeEntity.kt @@ -0,0 +1,31 @@ +package im.grit.infrastructure.common.entity + +import jakarta.persistence.Column +import jakarta.persistence.EntityListeners +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import jakarta.persistence.MappedSuperclass +import org.springframework.data.annotation.CreatedDate +import org.springframework.data.annotation.LastModifiedDate +import org.springframework.data.jpa.domain.support.AuditingEntityListener +import java.time.LocalDateTime + +@MappedSuperclass +@EntityListeners(AuditingEntityListener::class) +abstract class BaseDateTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + val id: Long = 0L + + @CreatedDate + @Column(nullable = false, updatable = false, comment = "생성 날짜") + var createdAt: LocalDateTime = LocalDateTime.now() + protected set + + @LastModifiedDate + @Column(nullable = false, comment = "최종 수정 날짜") + var updatedAt: LocalDateTime = LocalDateTime.now() + protected set +} diff --git a/src/main/kotlin/im/grit/infrastructure/common/entity/BaseEntity.kt b/src/main/kotlin/im/grit/infrastructure/common/entity/BaseEntity.kt new file mode 100644 index 0000000..a705bda --- /dev/null +++ b/src/main/kotlin/im/grit/infrastructure/common/entity/BaseEntity.kt @@ -0,0 +1,20 @@ +package im.grit.infrastructure.common.entity + +import jakarta.persistence.Column +import jakarta.persistence.MappedSuperclass +import org.springframework.data.annotation.CreatedBy +import org.springframework.data.annotation.LastModifiedBy + +@MappedSuperclass +abstract class BaseEntity : BaseDateTimeEntity() { + + @CreatedBy + @Column(nullable = false, updatable = false, comment = "생성한 사용자") + var createdBy: String = "" + protected set + + @LastModifiedBy + @Column(nullable = false, comment = "최종 수정한 사용자") + var updatedBy: String = "" + protected set +} diff --git a/src/main/kotlin/im/grit/infrastructure/config/audit/AuditConfig.kt b/src/main/kotlin/im/grit/infrastructure/config/audit/AuditConfig.kt new file mode 100644 index 0000000..1b7e788 --- /dev/null +++ b/src/main/kotlin/im/grit/infrastructure/config/audit/AuditConfig.kt @@ -0,0 +1,16 @@ +package im.grit.infrastructure.config.audit + +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.data.domain.AuditorAware +import org.springframework.data.jpa.repository.config.EnableJpaAuditing + +@Configuration +@EnableJpaAuditing +class AuditConfig { + + @Bean + fun auditorAwareProvider(): AuditorAware { + return AuditorAwareImpl() + } +} diff --git a/src/main/kotlin/im/grit/infrastructure/config/audit/AuditorAwareImpl.kt b/src/main/kotlin/im/grit/infrastructure/config/audit/AuditorAwareImpl.kt new file mode 100644 index 0000000..11c896b --- /dev/null +++ b/src/main/kotlin/im/grit/infrastructure/config/audit/AuditorAwareImpl.kt @@ -0,0 +1,22 @@ +package im.grit.infrastructure.config.audit + +import org.springframework.data.domain.AuditorAware +import org.springframework.security.authentication.AnonymousAuthenticationToken +import org.springframework.security.core.context.SecurityContextHolder +import java.util.* + +class AuditorAwareImpl : AuditorAware { + + override fun getCurrentAuditor(): Optional { + val auditor = SecurityContextHolder.getContext().authentication + ?.takeIf { it.isAuthenticated && it !is AnonymousAuthenticationToken } + ?.name + ?: ANONYMOUS + + return Optional.of(auditor) + } + + companion object { + private const val ANONYMOUS = "anonymous" + } +}