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

208 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

从1.0之前的版本升级

如果您仍然使用SQLDelight 0.6, 那么首先升级到0.7, 这样就可以继续使用SupportSQLite工件了

从 0.7 升级Gradle插件到 0.7.1. 这将升级 arch.persistence.db 依赖到 1.1.1, 却不会影响sqldelight的使用.

从 0.7.1 升级Gradle插件到 0.7.2. 这将把运行时的包从com.squareup.sqldelight修改成com.squareup.sqldelight.prerelease, 所以需要在代码中自行修改引用.

从 0.7.2 升级Gradle插件到 0.9.0. 这将升级可传递依赖项和生成的代码, 以使用AndroidX, 这是SQLDelight的一项要求. 这应该在你升级自己的项目到AndroidX的同时完成, 并且不能各自独立完成, 因为SQLDelight会生成引用了android support/AndroidX的代码.

要不然 在升级到 0.9.9之前, 从 0.7.2 升级Gradle插件到 0.9.0. 这将升级到AndroidX, 却没有修改 sqldelight的包名成com.squareup.sqldelight.prerelease

假定在 SQLDelight 0.9, 有这个User.sq文件:

CREATE TABLE user (
  id INTEGER NOT NULL PRIMARY KEY,
  name TEXT NOT NULL
);

insertDefaultData:
INSERT INTO user
VALUES (1, 'Alec');

users:
SELECT *
FROM user;

names:
SELECT name
FROM user;

insertUser:
INSERT INTO user
VALUES (?, ?);

这将生成UserModel类, 且该类有检索的方法. 

从build目录下复制*Model.java文件并粘贴到src/main/java目录下. 

从 0.9 升级Gradle插件到 1.0.0-rc4. 注意此时构建会失败, 因为模型代码有引用到旧SQLDelight运行时的未定义代码(比如SqlDelightStatement).要添回这个引用的话, 需要添加implementation com.squareup.sqldelight:runtime:0.9.0.

此时构建应该正在工作了, 但是.sq文件的修改并不会反射进*Model.java文件. 如果此时事件并没有正确工作的话, 请提交issue!

修改SupportSQLiteOpenHelper.Callback来调用现在生成的Database, 它将持有为SQLDelight 1.0生成的代码, 开始:

//Before
@Override void onCreate(SupportSQLiteDatabase db) {
  db.execSql(UserModel.CREATE_TABLE);
  db.execSql(UserModel.INSERTDEFAULTDATA);
  // Other create table/initialization
}

在SQLDelight 1.0, .sq文件中所有未标识的语句(包括CREATE语句)将会在onCreate期间运行, 所以我们能够从上面的代码中移除insertDefaultData标识:

User.sq

...

--insertDefaultData:
INSERT INTO user
VALUES (1, 'Alec');

...

现在你的SupportSQLiteOpenHelper.Callback应该在create中调用Database

@Override void onCreate(SupportSQLiteDatabase db) {
  SqlDriver driver = AndroidSqliteDriver(db)
  Database.Schema.create(driver)
}

如果你把迁移放入.sqm的话, 你也能做相同的操作, 但这不是升级的必要部分.

这时候事件应该依然工作正常.

后来在代码添加来创建Database, 作为图谱/单例模型/whevs的一部分:

@Provides @Singleton static SupportSQLiteOpenHelper provideDatabaseHelper(
    @App Context context) {
  SupportSQLiteOpenHelper.Configuration config =  SupportSQLiteOpenHelper.Configuration.builder(context)
      .name(DATABASE_NAME)
      .callback(new MyDatabaseCallback())
      .build();
  return new FrameworkSQLiteOpenHelperFactory().create(config);
}

@Provides @Singleton static Database provideDatabase(
    SupportSQLiteOpenHelper helper) {
  return new Database(new AndroidSqliteDriver(helper));
}

如果你也在用SQL Brite, 请确保创建BriteDatabase的时候, 要使用跟创建Database时用的SupportSQLiteOpenHelper相同.

事件应该依然在工作.

接下来假设你正在使用SQL Brite从数据库获取响应式回调, 但是只使用SQLDelight的升级应该是相似的.

可变检索能够通过使用Database单独转化:

之前:

private val insertUser: UserModel.InsertUser by lazy {
  UserModel.InsertUser(datbaseOpenHelper.writableDatabase)
}

insertUser.bind(2, "Jake")
insertUser.executeInsert()

之后:

database.userQueries.insertUser(2, "Jake")

你不再需要"Factory"类型执行检索, 所需要的只是检索包裹器.

之前:

val query = User.FACTORY.users()
val usersObservable = briteDatabase.createQuery(query.tables, query.statement, query.args)
  .mapToList(User.FACTORY.usersMapper()::map)

之后:

val usersObservable = database.userQueries.users()
  .asObservable(Schedulers.io()) // The scheduler to run the query on.
  .mapToList()

如果你依然想要使用自定义类型, 请将自定义类型以参数的形式传递给检索.

val myUsersObservable = database.userQueries.users(::MyUser)
  .asObservable(Schedulers.io())
  .mapToList()

一旦你不再引用UserModel.java, 一定要删除整个类. 为每一个*Model.java文件重复这个操作直到升级完成!