SQLDelight for Android - 从SQL语句中生成Kotlin代码 - 1
概览
SQLDelight从SQL语句中生成类型安全的Kotlin API. SQLDelight在编译期检测schema, 语句和合并, 并且提供了一些IDE特性, 比如自动补全和重构, 这使得书写和维护SQL更加容易.
SQLDelight能够理解业已存在的SQL schema.
CREATE TABLE hockey_player (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
number INTEGER NOT NULL
);
SQLDelight为所有示踪SQL语句生成类型安全的代码.
SQLDelight支持多种方言和平台:
SQLite
PostgreSQL (JVM) (Experimental)
HSQL/H2 (JVM) (Experimental)
快照
开发版本快照(包括IDE插件zip文件)在Sonatype快照
仓库可以查看到.
// settings.gradle.kts
pluginManagement {
repositories {
gradlePluginPortal()
maven(url = "https://oss.sonatype.org/content/repositories/snapshots")
}
}
// build.gradle.kts
plugins {
id("com.squareup.sqldelight") version "SNAPSHOT-VERSION"
}
repositories {
maven(url = "https://oss.sonatype.org/content/repositories/snapshots")
}
快速开始
首先, 在工程根build.gradle
文件应用Gradle插件.
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.squareup.sqldelight:gradle-plugin:1.5.3'
}
}
然后, 在项目的模块build.gradle
文件中应用Gradle插件.
apply plugin: 'com.squareup.sqldelight'
在src/main/sqldelight
目录下将SQL语句放入.sq
文件下. 通常这个SQL文件的首次语句会创建表.
-- src/main/sqldelight/com/example/sqldelight/hockey/data/Player.sq
CREATE TABLE hockeyPlayer (
player_number INTEGER NOT NULL,
full_name TEXT NOT NULL
);
CREATE INDEX hockeyPlayer_full_name ON hockeyPlayer(full_name);
INSERT INTO hockeyPlayer (player_number, full_name)
VALUES (15, 'Ryan Getzlaf');
从这个文件中, SQLDelight会生成Database
Kotlin类, 并关联了Schema
对象, 这个对象用来创建数据库并在其上运行SQL语句. 这么做需要驱动, SQLDelight提供了该驱动的实现:
dependencies {
implementation "com.squareup.sqldelight:android-driver:1.5.3"
}
val driver: SqlDriver = AndroidSqliteDriver(Database.Schema, context, "test.db")
推荐在Android Studio中使用文件目录的"Project"视图而非"Android"视图, 这是为了更好地查找和编辑SQLDelight文件.
.sq
文件内的SQL语句可以添加标签以生成运行时可用的类型安全的函数.
selectAll:
SELECT *
FROM hockeyPlayer;
insert:
INSERT INTO hockeyPlayer(player_number, full_name)
VALUES (?, ?);
insertFullPlayerObject:
INSERT INTO hockeyPlayer(player_number, full_name)
VALUES ?;
拥有标签语句在内的文件会为匹配.sq
文件名的语句生成检索文件 - 将上面的sql放入Player.sq
生成PlayerQueries.kt
. 要引用PlayerQueries
就需要包裹上面创建的驱动:
// In reality the database and driver above should be created a single time
// and passed around using your favourite dependency injection/service
// locator/singleton pattern.
val database = Database(driver)
val playerQueries: PlayerQueries = database.playerQueries
println(playerQueries.selectAll().executeAsList())
// Prints [HockeyPlayer(15, "Ryan Getzlaf")]
playerQueries.insert(player_number = 10, full_name = "Corey Perry")
println(playerQueries.selectAll().executeAsList())
// Prints [HockeyPlayer(15, "Ryan Getzlaf"), HockeyPlayer(10, "Corey Perry")]
val player = HockeyPlayer(10, "Ronald McDonald")
playerQueries.insertFullPlayerObject(player)
就是这样了!.
扩展
RxJava
要观察一个检索, 需要依赖于RxJava扩展构件并使用它提供的扩展方法:
dependencies {
implementation "com.squareup.sqldelight:rxjava3-extensions:1.5.3"
}
val players: Observable<List<HockeyPlayer>> =
playerQueries.selectAll()
.asObservable()
.mapToList()
注意: 对于RxJava 2, 使用rxjava2-extensions
作为构件名.
协程
Flow
要将检索用作Flow来消费, 需要依赖于协程扩展构件并使用它提供的扩展方法:
dependencies {
implementation "com.squareup.sqldelight:coroutines-extensions-jvm:1.5.3"
}
val players: Flow<List<HockeyPlayer>> =
playerQueries.selectAll()
.asFlow()
.mapToList()
该流发出了检索结果, 并且每一次数据库为该检索发生变更的时候都会发出新的结果.
转载自:https://juejin.cn/post/7145643584258539550