서버 세팅중에 auto generate 무의식적으로 property 세팅만 해주면 되는거 아닌가? 했는데, 스프링이 제공해주는거다. ㅎㅎ;;
스프링으로 개발을 오래하다보니, 자꾸 스프링 관점으로 생각하는 게 있는 것 같다.
전체적으로 SchemaUtils 를 사용하여 테이블을 생성하는 것은 동일하다.
다만 ktor+exposed 조합으로 사용시 reflection 으로 구현해야 한다.
굳이 reflection 까지 사용하며 auto-generate 를 사용하진 않을 것 같다. prod 환경에서 사용할 것이 아니고, local 서버에서 개발 테스트용으로 사용이 전부이기 때문이다.
@Transactional
override fun run(args: ApplicationArguments?) {
val exposedTables = discoverExposedTables(applicationContext, excludedPackages)
SchemaUtils.create(tables = exposedTables.toTypedArray())}
}
fun discoverExposedTables(applicationContext: ApplicationContext, excludedPackages: List<String>): List<Table> {
val provider = ClassPathScanningCandidateComponentProvider(false)
provider.addIncludeFilter(AssignableTypeFilter(Table::class.java))
excludedPackages.forEach { provider.addExcludeFilter(RegexPatternTypeFilter(Pattern.compile(it.replace(".", "\\.") + ".*"))) }
val packages = AutoConfigurationPackages.get(applicationContext)
val components = packages.map { provider.findCandidateComponents(it) }.flatten()
return components.map { Class.forName(it.beanClassName).kotlin.objectInstance as Table }
}
@Transactional: 트랜잭션 범위 내에서 실행하도록 지정한다. 이 메서드가 실행되면 데이터베이스 트랜잭션이 시작되고, 메서드가 종료될 때 트랜잭션이 커밋되거나 롤백된다.
generate-ddl 여부에 따라 DatabaseInitializer 빈을 등록여부를 결정한다. 만약 해당 빈을 등록하게 되면 DatabaseInitializer 객체가 ApplicationRunner을 구현하고 있기 때문에 스프링 어플리케이션이 실행하는 경우 run() 메서드에서 스키마를 생성하게 된다.
run 함수: 애플리케이션 시작 시 실행되며, Exposed 테이블을 자동으로 발견하고 해당 테이블의 스키마를 생성한다.
discoverExposedTables 함수: Spring의 ClassPathScanningCandidateComponentProvider를 사용하여 지정된 패키지 내의 모든 Exposed 테이블 클래스를 스캔한다. 제외 패키지는 스캔에서 제외된다.
fun discoverExposedTables(packageName: String): List<Table> {
val reflections = Reflections(packageName)
val subclasses = reflections.getSubTypesOf(Table::class.java)
return subclasses.mapNotNull { it.kotlin.objectInstance as? Table }
}
fun Application.module() {
// 데이터베이스 연결 설정...
val exposedTables = discoverExposedTables("your.package.name")
transaction {
SchemaUtils.create(*exposedTables.toTypedArray())
}
// 라우트 및 기타 설정...
}
val allTables = arrayOf(Users, Posts, Comments, ... )
transaction {
SchemaUtils.create(*allTables)
}
개발 단계에서 auto generate를 사용하고 싶지만, reflection 까지는 가기 싫을 때,
요로코롬 list 를 생성하고 스프레드 연산자로 쭉 넣어도 된다.