여기서 작성했던 멀티 데이터 소스말고,, 일반 jpa 설정을 위해 필요한 클래스를 알아보자
@ConfigurationPropertiesScan
@SpringBootApplication(
scanBasePackages = ["kr.co.도메인디렉토리 등등", "kr.co.참고할디렉토리 등등", "kr.co.apexsoft.gradnet2.api"]
)
class ApiApplication
fun main(args: Array<String>) {
runApplication<ApiApplication>(*args)
}
스프링 이니셜라이저로 생성 한 프로젝트에 필수로 생성되는 어플리케이션 클래스에 basePacakage를 기재 해 주자. 내 경우 도메인이나 기타 라이브러리가 들어있는 domain, lib모듈의 위치를 기재했다.
위치는 어느곳에 작성해도 상관 없는데, api 모듈의 config 디렉토리에 생성했다.
/**
* JPA 설정 클래스
* 2개의 빈은 디비 테이블에 createdAt, createdBy 등 audit 정보를 자동으로 저장하는데 사용
*/
@Configuration
@EntityScan(basePackages = ["kr.co.~.domain"])
@EnableJpaRepositories(basePackages = ["kr.co.~.domain"])
@EnableJpaAuditing(dateTimeProviderRef = "auditingDateTimeProvider")
class JpaConfig {
@Bean
fun auditingDateTimeProvider() = DateTimeProvider {
Optional.of(LocalDateTime.now())
}
@Bean
fun auditorAwareProvider() = AuditorAware {
val authentication = SecurityContextHolder.getContext().authentication
if (authentication == null) {
Optional.empty()
} else when (val principal: Any = authentication.principal) {
is String -> Optional.of(principal)
is AuthUser -> Optional.of(principal.userId)
else -> Optional.empty()
}
}
}
@EntityScan
어노테이션 부분에는 읽어올 엔터티들이 들어있는 위치를, @EnableJpaRepositories
에는 Repo를 읽어올 위치를 적어준다. 보통 엔터티 클래스와 Repo는 함께 있기 때문에 동일한 디렉토리를 기재 해 주었다.
@EnableJpaAuditing
는 Spring Audit
기능을 사용하기 위해 필요한 어노테이션인데, DB에 createdAt, lastModified 등 모든 테이블에 공통으로 들어갈 속성을 정의하고자 할 때 사용한다.
@MappedSuperclass
@EntityListeners(AuditingEntityListener::class)
abstract class AbstractEntity : Serializable {
@CreatedDate
@Column(name = "CREATED_DATE", updatable = false, columnDefinition = "DATETIME")
protected lateinit var createdTime: LocalDateTime
@Column(name = "CREATED_BY", updatable = false)
@CreatedBy
protected var createdBy: String? = null
@LastModifiedDate
@Column(name = "LAST_MODIFIED_DATE", columnDefinition = "DATETIME")
protected lateinit var lastModifiedTime: LocalDateTime
@Column(name = "LAST_MODIFIED_BY", updatable = true)
@LastModifiedBy
protected var lastModifiedBy: String? = null
}
도메인 모듈에 AbstractEntity라는 이름으로 추상 클래스를 작성 해 주었다.
@Entity
@Table(name = "USER")
class User(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "oid")
val oid: Long? = null, //pk
@Column(name = "USER_ID")
val userId: String,
@Column(name = "PASSWORD")
private var password: String,
@Column(name = "ROLES")
@Convert(converter = RoleEnumToListConvert::class)
private var roles: List<Role>,
) : AbstractEntity() {
enum class RoleType (
val id: Long
) {
ROLE_USER(100),
ROLE_SYS_ADMIN(200),
ROLE_SCHL_ADMIN(210),
ROLE_SET_ADMIN(220),
ROLE_STLM_ADMIN(230),
ROLE_TIME_INDEPENDENT(300)
}
}
User클래스를 예로 가져왔는데, AbstractEntity를 상속받으면 자동생성 컬럼이 User 테이블에 적용된다.
다른 모든 엔터티 클래스에도 적용할 수 있다.