跳到主要内容

DDL 编译器

Jimmer DDL 编译器是基于编译期的实体建表 SQL 生成工具。它既可以作为 Kotlin KSP 处理器运行,也可以作为 Java 注解处理器运行,读取 Jimmer 实体元数据,并输出特定方言的 SQL 文件,例如 Flyway migration。

当希望数据库结构 SQL 和运行时查询、保存所使用的实体模型保持一致时,可以使用它。生产环境中,尤其是在允许破坏性变更时,仍应先审查生成的 SQL 再执行。

Kotlin 项目的 KSP 配置

Kotlin 项目应使用 KSP 处理器。请配置和当前 Kotlin 版本匹配的 KSP 插件版本。

plugins {
kotlin("jvm")
id("com.google.devtools.ksp") version "<ksp-version>"
}

dependencies {
implementation("org.babyfish.jimmer:jimmer-sql-kotlin:<jimmer-version>")
ksp("org.babyfish.jimmer:jimmer-ksp:<jimmer-version>")
ksp("org.babyfish.jimmer:jimmer-ddl-compiler:<jimmer-version>")
}

ksp {
arg("jimmerDdl.enabled", "true")
arg("jimmerDdl.databaseType", "postgresql")
arg("jimmerDdl.outputFormat", "flyway")
arg("jimmerDdl.outputDir", "$projectDir/build/generated/jimmer-ddl/main/resources/db/migration")
arg("jimmerDdl.version", "1001")
arg("jimmerDdl.description", "jimmer_auto_ddl_generated")
}

如果希望生成的 SQL 和快照文件作为应用资源一起打包,需要把 generated resources 目录加入 main resources:

sourceSets {
main {
resources.srcDir("$buildDir/generated/jimmer-ddl/main/resources")
}
}

Java 项目的 APT 配置

Java 项目应通过 annotationProcessor 使用注解处理器,并通过 -A... 编译参数传递配置:

dependencies {
implementation("org.babyfish.jimmer:jimmer-sql:<jimmer-version>")
annotationProcessor("org.babyfish.jimmer:jimmer-apt:<jimmer-version>")
annotationProcessor("org.babyfish.jimmer:jimmer-ddl-compiler:<jimmer-version>")
}

tasks.withType<JavaCompile>().configureEach {
options.compilerArgs.add("-AjimmerDdl.enabled=true")
options.compilerArgs.add("-AjimmerDdl.databaseType=postgresql")
}

完整的 Gradle Java 配置示例:

plugins {
java
}

dependencies {
implementation("org.babyfish.jimmer:jimmer-sql:<jimmer-version>")
annotationProcessor("org.babyfish.jimmer:jimmer-apt:<jimmer-version>")
annotationProcessor("org.babyfish.jimmer:jimmer-ddl-compiler:<jimmer-version>")
}

tasks.withType<JavaCompile>().configureEach {
options.compilerArgs.addAll(
listOf(
"-AjimmerDdl.enabled=true",
"-AjimmerDdl.databaseType=postgresql",
"-AjimmerDdl.outputFormat=flyway",
"-AjimmerDdl.outputDir=$projectDir/build/generated/jimmer-ddl/main/resources/db/migration",
"-AjimmerDdl.version=1001",
"-AjimmerDdl.description=jimmer_auto_ddl_generated",
"-AjimmerDdl.compareDatabase=false",
)
)
}

sourceSets {
main {
resources.srcDir("$buildDir/generated/jimmer-ddl/main/resources")
}
}

Maven Java 项目可以配置 maven-compiler-plugin

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.babyfish.jimmer</groupId>
<artifactId>jimmer-apt</artifactId>
<version>${jimmer.version}</version>
</path>
<path>
<groupId>org.babyfish.jimmer</groupId>
<artifactId>jimmer-ddl-compiler</artifactId>
<version>${jimmer.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<arg>-AjimmerDdl.enabled=true</arg>
<arg>-AjimmerDdl.databaseType=postgresql</arg>
<arg>-AjimmerDdl.outputFormat=flyway</arg>
<arg>-AjimmerDdl.outputDir=${project.build.directory}/generated/jimmer-ddl/main/resources/db/migration</arg>
<arg>-AjimmerDdl.version=1001</arg>
<arg>-AjimmerDdl.description=jimmer_auto_ddl_generated</arg>
<arg>-AjimmerDdl.compareDatabase=false</arg>
</compilerArgs>
</configuration>
</plugin>

输出文件

默认输出目录为:

build/generated/jimmer-ddl/main/resources/db/migration

jimmerDdl.outputFormatflyway 时,编译器会写出类似这样的文件:

V1001__jimmer_auto_ddl_generated.sql

当它为 plain 时,编译器会写出:

jimmer_auto_ddl_generated.sql

数据库比对和离线生成

如果存在 JDBC 配置,并且启用了 jimmerDdl.compareDatabase,编译器会读取当前数据库结构,并和实体推导出的目标结构做 diff,生成增量 SQL。

如果数据库无法读取,或者没有可用的 JDBC URL,则会回退为离线生成。离线生成会使用下面介绍的快照文件,在多次构建之间生成增量 SQL。

快照模型

编译器会在 generated resources 下写出快照:

build/generated/jimmer-ddl/main/resources/.jimmer-ddl/entity-table-snapshot.properties

快照记录实体到表名的映射以及表结构哈希。后续构建时,编译器可以比较上一次快照和当前实体模型,从而输出增量 SQL;也可以识别由 @Table(name = ...) 变化导致的表重命名。

配置项

配置项默认值说明
jimmerDdl.enabledtrue是否启用生成。
jimmerDdl.profiles逗号分隔的 profile 名称。每个 profile 可以通过 jimmerDdl.profile.<name>.<option> 覆盖配置。
jimmerDdl.databaseTypeauto方言代码,例如 postgresqlmysqlh2sqlitesqlserveroracledmkingbasetaosauto 会在可用时从 JDBC URL 推断。
jimmerDdl.outputFormatflywayflyway 写出 V<version>__<description>.sqlplain 写出 <description>.sql
jimmerDdl.outputDirbuild/generated/jimmer-ddl/main/resources/db/migration生成 SQL 的输出目录。
jimmerDdl.version1001Flyway 版本前缀。
jimmerDdl.descriptionjimmer_auto_ddl_generated输出文件描述。
jimmerDdl.includePackages可选的包名前缀白名单,逗号分隔。
jimmerDdl.excludePackages可选的包名前缀黑名单,逗号分隔。
jimmerDdl.includeForeignKeystrue在方言支持时生成外键语句。
jimmerDdl.includeIndexestrue生成索引语句。
jimmerDdl.includeCommentstrue生成注释语句。
jimmerDdl.includeSequencestrue生成序列语句。
jimmerDdl.includeManyToManyTablestrue生成多对多中间表。
jimmerDdl.compareDatabasetrue在可用时读取数据库并生成 diff SQL。
jimmerDdl.nullabilityRepairOnlyfalse将较高风险的离线结构变更规划限制为可空性修复。
jimmerDdl.sourceFingerprint可选源码指纹,会写入快照。
jimmerDdl.jdbcUrl数据库比对使用的显式 JDBC URL。
jimmerDdl.jdbcUsernameJDBC 用户名。
jimmerDdl.jdbcPasswordJDBC 密码。
jimmerDdl.jdbcSchemaJDBC schema 名称。
jimmerDdl.jdbcDriverJDBC 驱动类名。
jimmerDdl.springResourcePath可选 Spring 资源路径,用于发现数据源配置。
jimmerDdl.springProfilelocal读取 YAML 数据源配置时使用的 Spring profile。

多 Profile

Profile 可以让一次编译为多个数据库目标或输出目录生成 SQL:

ksp {
arg("jimmerDdl.profiles", "postgres,mysql")

arg("jimmerDdl.profile.postgres.databaseType", "postgresql")
arg("jimmerDdl.profile.postgres.outputDir", "$projectDir/build/generated/jimmer-ddl/postgres/db/migration")

arg("jimmerDdl.profile.mysql.databaseType", "mysql")
arg("jimmerDdl.profile.mysql.outputDir", "$projectDir/build/generated/jimmer-ddl/mysql/db/migration")
}