You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过@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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 22:25:04