likes
comments
collection
share

SQLDelight for Android - 从SQL语句中生成Kotlin代码 - 1

作者站长头像
站长
· 阅读数 64

概览

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 for Android - 从SQL语句中生成Kotlin代码 - 1


SQLDelight支持多种方言和平台:

SQLite

MySQL (JVM)

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
评论
请登录