如何通过@DatabaseEnum注解自动配置jOOQ的Enum forcedType?
自动识别标注@DatabaseEnum的枚举类并添加到jOOQ的forcedType配置
我现在在Gradle的jOOQ配置里手动定义枚举类型的forcedType,希望实现当枚举类标注自定义的@DatabaseEnum注解时,自动将其添加为forcedType。下面是当前的Gradle jOOQ配置代码、@DatabaseEnum注解定义及对应的枚举类代码,请问有没有可行的实现方式?
当前Gradle jOOQ配置
jooq { version.set(Versions.jooq) edition.set(OSS) configurations { create("main") { jooqConfiguration.apply { logging = Logging.INFO generator.apply { name = "org.jooq.codegen.KotlinGenerator" database.apply { name = "com.example.generator.StandalonePostgreSQLDatabase" inputSchema = "public" excludes = "flyway_schema_history" forcedTypes.addAll( listOf( ForcedType().apply { isEnumConverter = true includeTypes = "day_of_week" userType = "com.example.api.enums.DayOfWeek" } ) ) } generate.apply { isDeprecated = false isRecords = true isImmutablePojos = true isFluentSetters = true } target.apply { packageName = "com.example.api" directory = "build/generated/jooq" } strategy.name = "com.example.common.JPrefixGeneratorStrategy" } } } } }
@DatabaseEnum注解定义与枚举类
@Retention(AnnotationRetention.RUNTIME) annotation class DatabaseEnum(val includeType: String) @DatabaseEnum(includeType = "day_of_week") enum class DayOfWeek { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }
实现方案
可以通过Gradle的类扫描机制,在配置阶段自动识别带有@DatabaseEnum注解的枚举类,动态构建jOOQ的forcedTypes列表,无需手动逐个添加。
步骤1:添加类扫描函数
在Gradle脚本中添加一个函数,用于扫描指定包下所有带有@DatabaseEnum注解的枚举类:
// 扫描指定包下带有@DatabaseEnum注解的枚举类 fun findDatabaseEnums(packageName: String): List<Pair<String, String>> { val classLoader = Thread.currentThread().contextClassLoader val packagePath = packageName.replace('.', '/') val resources = classLoader.getResources(packagePath) ?: return emptyList() val enums = mutableListOf<Pair<String, String>>() while (resources.hasMoreElements()) { val resource = resources.nextElement() if (resource.protocol == "file") { val dir = File(resource.toURI()) dir.walkTopDown().forEach { file -> if (file.isFile && file.extension == "class") { val className = packageName + "." + file.nameWithoutExtension try { val clazz = Class.forName(className) if (clazz.isEnum) { val annotation = clazz.getAnnotation(DatabaseEnum::class.java) annotation?.let { enums.add(it.includeType to className) } } } catch (e: ClassNotFoundException) { // 忽略加载失败的类 } } } } } return enums }
步骤2:修改jOOQ配置动态生成forcedTypes
替换原有的forcedTypes.addAll代码块,改用扫描到的枚举类生成配置:
// 枚举类所在的包路径,根据实际情况调整 val targetEnumPackage = "com.example.api.enums" val databaseEnums = findDatabaseEnums(targetEnumPackage) forcedTypes.addAll( databaseEnums.map { (includeType, userType) -> ForcedType().apply { isEnumConverter = true this.includeTypes = includeType this.userType = userType } } )
步骤3:调整任务依赖
由于扫描需要依赖编译后的类文件,需要确保jOOQ代码生成任务在枚举类编译完成后执行:
tasks.named("jooqGenerateMain") { dependsOn(tasks.named("compileKotlin")) }
完整修改后的Gradle配置示例
// 扫描指定包下带有@DatabaseEnum注解的枚举类 fun findDatabaseEnums(packageName: String): List<Pair<String, String>> { val classLoader = Thread.currentThread().contextClassLoader val packagePath = packageName.replace('.', '/') val resources = classLoader.getResources(packagePath) ?: return emptyList() val enums = mutableListOf<Pair<String, String>>() while (resources.hasMoreElements()) { val resource = resources.nextElement() if (resource.protocol == "file") { val dir = File(resource.toURI()) dir.walkTopDown().forEach { file -> if (file.isFile && file.extension == "class") { val className = packageName + "." + file.nameWithoutExtension try { val clazz = Class.forName(className) if (clazz.isEnum) { val annotation = clazz.getAnnotation(DatabaseEnum::class.java) annotation?.let { enums.add(it.includeType to className) } } } catch (e: ClassNotFoundException) { // 忽略加载失败的类 } } } } } return enums } jooq { version.set(Versions.jooq) edition.set(OSS) configurations { create("main") { jooqConfiguration.apply { logging = Logging.INFO generator.apply { name = "org.jooq.codegen.KotlinGenerator" database.apply { name = "com.example.generator.StandalonePostgreSQLDatabase" inputSchema = "public" excludes = "flyway_schema_history" // 动态生成forcedTypes val targetEnumPackage = "com.example.api.enums" val databaseEnums = findDatabaseEnums(targetEnumPackage) forcedTypes.addAll( databaseEnums.map { (includeType, userType) -> ForcedType().apply { isEnumConverter = true this.includeTypes = includeType this.userType = userType } } ) } generate.apply { isDeprecated = false isRecords = true isImmutablePojos = true isFluentSetters = true } target.apply { packageName = "com.example.api" directory = "build/generated/jooq" } strategy.name = "com.example.common.JPrefixGeneratorStrategy" } } } } } // 确保jOOQ代码生成依赖于枚举类编译 tasks.named("jooqGenerateMain") { dependsOn(tasks.named("compileKotlin")) }
内容的提问来源于stack exchange,提问作者Jay Ahn
相关产品推荐
相关产品推荐

