项目中的 Gradle 配置完整指南)
后端ORM【免费下载链接】sqldelightSQLDelight - Generates typesafe Kotlin APIs from SQL项目地址https://gitcode.com/gh_mirrors/sq/sqldelight点击查看免费下载导读本文聚焦 SQLDelight 在 JVM 场景下的 Gradle 构建配置如何通过sqldelightGradle DSL 显式声明数据库、配置包名、方言、迁移验证与代码生成选项并在此基础上结合当前仓库中的 HSQL 方言实现与 JDBC 驱动源码说明 JVM 数据库如 H2、HSQLDB如何与 SQLDelight 生成的类型安全 Kotlin API 衔接。读完本文你将掌握从零配置一个 JVM HSQL 数据库工程、控制代码生成行为、并利用 schema 依赖与迁移校验保证数据库演进质量的一整套方案。说明docs/jvm_h2/gradle.md与docs/jvm_mysql/gradle.md、docs/jvm_postgresql/gradle.md、docs/jvm_sqlite/gradle.md等 JVM 分支文档共用同一份公共 Gradle 配置文档 docs/common/gradle.md本文内容即基于该公共文档展开并结合仓库源码进行补充。一、为什么需要显式声明数据库Gradle DSL 的作用SQLDelight 插件会在应用 Kotlin/JVM 插件后自动寻找.sq与.sqm文件并生成代码但当项目需要更精细的控制——例如指定方言、多个数据库、schema 依赖或迁移输出目录——就需要通过 Gradle DSL 显式声明数据库。DSL 的顶层入口是sqldelight扩展块其核心结构如下 Kotlinbuild.gradle.ktskotlin sqldelight { databases { create(MyDatabase) { // Database configuration here. } } } Groovybuild.gradlegroovy sqldelight { databases { MyDatabase { // Database configuration here. } } }databases是数据库的容器create(MyDatabase)Kotlin DSL或MyDatabase { }Groovy DSL用于声明一个名为MyDatabase的数据库其生成的数据库类名即MyDatabase。下方的所有数据库级配置项都写在create块内部。二、SQLDelight 扩展级配置linkSqlitelinkSqlite是扩展sqldelight块级别的配置项作用于整个模块。类型PropertyBoolean默认值true该选项仅对native 目标生效用于决定是否自动链接 sqlite。它会为项目编译成动态 framework这是近期 Kotlin Multiplatform 版本的默认行为时添加链接 sqlite 所需的元数据。需要注意对于静态 framework该标志无效导入项目的 Xcode 构建应自行在链接器参数中加入-lsqlite3也可以通过 CocoaPods 插件为项目添加sqlite3pod 依赖或在 podspec 的spec.libraries设置中加入sqlite3例如 Kotlin DSL 写法extraSpecAttributes[libraries] c, sqlite3。由于linkSqlite只影响 native 链接元数据纯 JVM 项目H2/HSQL中通常保持默认值即可无需修改。 Kotlinkotlin linkSqlite.set(true) Groovygroovy linkSqlite true三、数据库级配置项详解3.1packageName生成的数据库类所在包类型PropertyString指定生成的数据库类以及相关查询接口所在的 Kotlin 包名。这是每个数据库必填的核心配置后续在应用代码中通过该包名 import 生成的MyDatabase类。 Kotlinkotlin packageName.set(com.example.db) Groovygroovy packageName com.example.db3.2srcDirs.sq / .sqm 文件的扫描目录类型ConfigurableFileCollection默认值src/[prefix]main/sqldelight其中[prefix]取决于所应用的 Kotlin 插件例如 multiplatform 工程为common即src/commonMain/sqldelight纯 JVM 工程为src/main/sqldelight。srcDirs定义插件搜索.sqschema 与查询定义和.sqm迁移文件的目录集合。除了setFrom(...)赋值方式还提供变体srcDirs(vararg objects: Any)直接传入多个路径 Kotlinkotlin srcDirs.setFrom(src/main/sqldelight) // 或一次传入多个目录 srcDirs(src/main/sqldelight, main/sqldelight) Groovygroovy srcDirs [src/main/sqldelight] // 或一次传入多个目录 srcDirs(src/main/sqldelight, main/sqldelight)仓库中的 JVM 集成测试可以印证这一目录约定例如 HSQL 集成测试工程 integration-hsql/src/main/sqldelight 将Characters.sq、Dog.sq放在src/main/sqldelight下插件按默认规则即可扫描到。3.3schemaOutputDirectory迁移校验的 schema 输出目录类型DirectoryProperty默认值null指定.dbschema 文件当前最新 schema 的导出的存放目录相对于项目根目录。这些文件用于校验迁移链最终得到的数据库与最新 schema 一致。当该值为null时不会创建迁移校验任务。 Kotlinkotlin schemaOutputDirectory.set(file(src/main/sqldelight/databases)) Groovygroovy schemaOutputDirectory file(src/main/sqldelight/databases)3.4dependency模块间 schema 依赖类型Project可选地指定对其他 Gradle 工程的 schema 依赖详见 Schema Dependencies。 Kotlinkotlin dependency(project(:other-project)) Groovygroovy dependency project(:other-project)3.5dialect选择目标 SQL 方言类型String或ProviderMinimalExternalModuleDependency方言通过 Gradle 依赖选择依赖坐标形式为app.cash.sqldelight:{dialect module}:{{ versions.sqldelight }}。方言选择规则Android 项目会根据minSdk自动选择对应的 SQLite 版本其他情况默认使用 SQLite 3.18JVM 数据库H2/HSQL/MySQL/PostgreSQL则需显式指定对应方言。当前仓库 dialects 目录下提供的方言模块数据库方言模块artifactIdHSQLhsql-dialectMySQLmysql-dialectPostgreSQLpostgresql-dialectSQLite 3.18sqlite-3-18-dialectSQLite 3.24sqlite-3-24-dialectSQLite 3.25sqlite-3-25-dialectSQLite 3.30sqlite-3-30-dialectSQLite 3.33sqlite-3-33-dialectSQLite 3.35sqlite-3-35-dialectSQLite 3.37sqlite-3-37-dialectSQLite 3.38sqlite-3-38-dialectSQLite 3.39sqlite-3-39-dialectSQLite 3.44sqlite-3-44-dialect配置示例以 SQLite 3.24 为例其他方言替换 artifactId 即可 Kotlinkotlin dialect(app.cash.sqldelight:sqlite-3-24-dialect:{{ versions.sqldelight }}) Groovygroovy dialect app.cash.sqldelight:sqlite-3-24-dialect:{{ versions.sqldelight }}HSQL 方言的源码印证HsqlDialect.kt 实现了SqlDelightDialect接口其runtimeTypes指向 JDBC 驱动的JdbcCursor与JdbcPreparedStatement并将asyncRuntimeTypes声明为不支持throw UnsupportedOperationException(HSQL does not support an async driver)说明 HSQL 方言当前不支持异步驱动。同时其类型解析由 HsqlTypeResolver.kt 完成例如将TINYINT/SMALLINT/INTEGER/BIGINT映射为对应 HSQL 整数类型、CHARACTER/VARCHAR映射为TEXT、DATE映射为TEXT、BIT/BINARY映射为BLOB等COALESCE、IFNULL、GREATEST、LEAST、MAX、MIN、LENGTH等函数也有专门的类型推断逻辑。3.6verifyMigrations构建期迁移校验类型PropertyBoolean默认值false设为true后迁移.sqm文件中的任何错误都会导致构建失败从而把迁移问题暴露在 CI 阶段而非运行时。 Kotlinkotlin verifyMigrations.set(true) Groovygroovy verifyMigrations true3.7treatNullAsUnknownForEqualityNULL 等值比较语义类型PropertyBoolean默认值false设为true后SQLDelight 在使用IS进行等值比较时不会把可空类型的值替换为等值比较即遵循 SQL 三值逻辑中NULL 视为未知的语义。 Kotlinkotlin treatNullAsUnknownForEquality.set(true) Groovygroovy treatNullAsUnknownForEquality true3.8generateAsync为异步驱动生成挂起查询方法类型PropertyBoolean默认值false设为true后SQLDelight 会为查询生成suspend挂起方法供异步驱动使用。需要注意HSQL 方言在源码中明确不支持异步驱动见上文 HsqlDialect.kt因此 HSQL 场景下应保持false如需异步能力可考虑 MySQL/PostgreSQL 的异步支持方案。 Kotlinkotlin generateAsync.set(true) Groovygroovy generateAsync true3.9deriveSchemaFromMigrations从迁移文件推导 schema类型PropertyBoolean默认值false设为true时数据库 schema 由.sqm迁移文件按顺序应用后推导得出为false时schema 由.sq文件定义。 Kotlinkotlin deriveSchemaFromMigrations.set(true) Groovygroovy deriveSchemaFromMigrations true3.10expandSelectStar展开 SELECT * 投影类型PropertyBoolean默认值true设为true时SQLDelight 会把SELECT *重写为显式列出实际结果列的语句。例如CREATE TABLE hockey_player ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, number INTEGER NOT NULL ); getAll: SELECT * FROM hockey_player;会被重写为SELECT hockey_player.id, hockey_player.name, hockey_player.number FROM hockey_player;这保证了生成结果类的列顺序稳定、投影列显式化。 Kotlinkotlin expandSelectStar.set(true) Groovygroovy expandSelectStar true3.11codegenExcludedColumns从代码生成中排除列类型SetPropertyString默认值空集合该配置接收一组表名.列名大小写必须与 SQLDelight schema 源一致将这些列从生成的模型类和展开后的SELECT *投影中省略。它只影响代码生成不改变 SQL schema 或迁移输出。典型用途在后续 schema 迁移真正删除某列之前先用它提前更新生成的 Kotlin API。约束与注意事项若配置的表或列不存在或某个 model 绑定 insert、SELECT结果列、RETURNING子句显式引用了被排除的列SQLDelight 会使编译失败由于这只是 codegen 层面的排除应用层需自行保证在物理删列之前仍存在的被排除列可以在写入时省略例如使用可空列或默认值如果.sq文件包含CREATE TABLEschema 定义应保留被排除列在 schema 定义中直到物理 schema 迁移真正删除它同时移除对该列的显式查询引用但让 schema 源继续反映当前数据库形态。 Kotlinkotlin codegenExcludedColumns.set(setOf(hockey_player.number)) Groovygroovy codegenExcludedColumns [hockey_player.number]四、Schema 依赖跨模块共享 schemadependency配置用于让当前数据库引入另一个 Gradle 工程的 schema。典型场景是分层模块上层模块ProjectA依赖下层模块ProjectB的数据库 schema 进行编译。 Kotlin kotlin // project-a/build.gradle.ktssqldelight { databases { create(MyDatabase) { packageName.set(com.example.projecta) dependency(project(:ProjectB)) } } } Groovy groovy // project-a/build.gradlesqldelight { databases { MyDatabase { packageName com.example.projecta dependency project(:ProjectB) } } } 此时 SQLDelight 会在ProjectB中查找同名数据库MyDatabase并把它的 schema 纳入编译。为使依赖解析成功ProjectB 必须声明同名数据库但生成到不同包 Kotlin kotlin // project-b/build.gradle.ktssqldelight { databases { // Same database name create(MyDatabase) { package com.example.projectb } } } Groovy groovy // project-b/build.gradlesqldelight { databases { // Same database name MyDatabase { package com.example.projectb } } } 重要限制如果使用了deriveSchemaFromMigrations true那么依赖此模块的每个模块也必须启用该功能以保证迁移推导出的 schema 在各模块间一致。五、JVM 场景实战HSQL 数据库的完整配置与运行5.1 完整 build.gradle.kts 示例将上述配置综合到 JVM HSQL 工程中一个可用的构建脚本如下plugins { kotlin(jvm) id(app.cash.sqldelight) } repositories { mavenCentral() } dependencies { implementation(app.cash.sqldelight:jdbc-driver:{{ versions.sqldelight }}) implementation(org.hsqldb:hsqldb:2.7.2) } sqldelight { databases { create(MyDatabase) { packageName.set(com.example.db) dialect(app.cash.sqldelight:hsql-dialect:{{ versions.sqldelight }}) // 开启迁移校验需要先配置 schema 输出目录 schemaOutputDirectory.set(file(src/main/sqldelight/databases)) verifyMigrations.set(true) } } }要点拆解jdbc-driver依赖提供 JdbcDriver.kt 中的JdbcDriver抽象类与DataSource.asJdbcDriver()扩展hsql-dialect依赖让解析器/代码生成器理解 HSQL 语法与类型org.hsqldb:hsqldb是实际的 JDBC 驱动实现用于建立连接。5.2 在代码中使用生成的数据库与 JDBC 驱动HSQL 是标准 JDBC 数据库SQLDelight 通过JdbcDriver抽象与之衔接。仓库的 HSQL 集成测试 HsqlTest.kt 给出了完整可运行模式val conn DriverManager.getConnection(jdbc:hsqldb:mem:mymemdb;shutdowntrue) val driver object : JdbcDriver() { override fun getConnection() conn override fun closeConnection(connection: Connection) Unit override fun addListener(vararg queryKeys: String, listener: Query.Listener) Unit override fun removeListener(vararg queryKeys: String, listener: Query.Listener) Unit override fun notifyListeners(vararg queryKeys: String) Unit } val database MyDatabase(driver) Before fun before() { MyDatabase.Schema.create(driver) }使用要点通过DriverManager.getConnection(jdbc:hsqldb:mem:mymemdb;shutdowntrue)创建内存库连接匿名子类化JdbcDriver覆写getConnection/closeConnection与监听器方法JDBC 驱动默认不支持查询监听覆写为 No-op 即可MyDatabase(driver)构造数据库实例MyDatabase.Schema.create(driver)负责建表之后即可调用database.dogQueries.insertDog(...)、database.dogQueries.selectDogs().executeAsOne()等类型安全 API。从 JdbcDriver.kt 源码可见底层机制execute/executeQuery通过connectionAndClose()获取连接将 SQL 交给java.sql.PreparedStatement执行JdbcPreparedStatement负责把 Kotlin 类型String/Long/Double/ByteArray/Boolean 等绑定为 JDBC 类型JdbcCursor负责把ResultSet各列读回 Kotlin 类型。此外驱动对事务要求连接默认处于autoCommit truebeginTransaction会显式校验这一点见check(autoCommit)逻辑这也是自定义JdbcDriver.getConnection()时需要注意的约定。5.3 非内存数据库与 DataSource 方式除内存库外也可连接文件型 HSQL 库jdbc:hsqldb:file:/path/to/db或通过javax.sql.DataSource注入连接池此时可直接使用扩展函数import app.cash.sqldelight.driver.jdbc.asJdbcDriver val dataSource: DataSource ... val database MyDatabase(dataSource.asJdbcDriver())asJdbcDriver()在 JdbcDriver.kt 中实现默认把监听器方法实现为 No-op。六、迁移与 schema 管理让数据库演进可控JVM 工程的数据库演进同样遵循 SQLDelight 的迁移体系在srcDirs如src/main/sqldelight中编写1.sqm、2.sqm…… 递增的迁移文件设置schemaOutputDirectory导出最新 schema 的.db文件设置verifyMigrations true使任何迁移错误在构建期直接失败如需以迁移为唯一 schema 来源设置deriveSchemaFromMigrations true此时依赖方也必须同步开启。仓库中integration-hsql之外sqldelight-gradle-plugin/src/test 下还包含大量迁移验证场景如migration-success、migration-failure、migration-gap-failure、migration-squash、schema-output等目录展示了从成功/失败/缺口/压缩迁移到 schema 输出的各种组合可作为配置与预期行为的参考样例。七、常见问题与注意事项HSQL 方言处于实验阶段docs/jvm_h2/index.md明确提示 HSQL 支持正在孵化方言的部分语法仍不完整遇到不支持的语法时可向 sql-psi 反馈。因此生产使用前应充分验证目标 SQL 语句。HSQL 不支持异步驱动HsqlDialect的asyncRuntimeTypes直接抛出UnsupportedOperationException设置generateAsync true无法用于 HSQL。expandSelectStar默认开启如果希望保留SELECT *的原始形态需显式设置expandSelectStar.set(false)。codegenExcludedColumns只影响代码生成它不修改 SQL schema也不会改变迁移输出删列仍需通过.sqm迁移完成且在此之前应用层要保证写入可省略该列。schema 依赖双方包名必须不同dependency(project(:B))要求 B 中同名数据库生成到不同包否则会造成类冲突。deriveSchemaFromMigrations需要全链路开启任一依赖方未开启都会导致 schema 推导不一致。八、小结本文围绕 SQLDelight 的 Gradle DSL完整梳理了扩展级与数据库级的所有配置项包括packageName、srcDirs、dialect、schemaOutputDirectory、verifyMigrations、deriveSchemaFromMigrations、expandSelectStar、codegenExcludedColumns等并结合仓库源码说明了 JVM HSQL 场景下的完整落地路径选择hsql-dialect、接入jdbc-driver、通过JdbcDriver子类化或DataSource.asJdbcDriver()连接 HSQLDB最后配合迁移校验体系保障 schema 演进安全。读者可参考 integration-hsql 测试工程与 docs/jvm_h2 文档目录在真实工程中验证上述配置。赞分享后端ORM【免费下载链接】sqldelightSQLDelight - Generates typesafe Kotlin APIs from SQL项目地址https://gitcode.com/gh_mirrors/sq/sqldelight点击查看免费下载相关推荐SQLDelight 在 JVM 上使用 MySQL从 Gradle 配置到类型安全查询的完整指南SQLDelight 在 JVM 上使用 MySQL从 Gradle 配置到类型安全查询的完整指南 本指南以 SQLDelight 仓库中的 JVM My后端ORMCloudflare Workers 兼容性标志详解完全遵循 WHATWG 标准的新 URL 解析实现Cloudflare Workers 兼容性标志详解完全遵循 WHATWG 标准的新 URL 解析实现 本文聚焦 Cloudflare Workers 运行时后端ORMPLFM_RADAR开源 10.5 GHz 相控阵雷达硬件与固件全链路公开PLFM_RADAR开源 10.5 GHz 相控阵雷达硬件与固件全链路公开 雷达是听得多、摸得少的领域成品系统价格高源码通常不公开。PLFM_RAD后端ORM上一篇MAA 明日方舟自动化助手一键长草新手完整指南下一篇如何把在线视频保存到本地Video-Downloader 快速上手指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考