【问题标题】:SQLDelight convert query return type when using flows使用流时 SQLDelight 转换查询返回类型
【发布时间】:2022-01-29 00:34:56
【问题描述】:

我想在我的应用程序中使用 SQLDelight 作为缓存层和协程扩展,以从我的 SQL 查询中返回一个流,并在本地数据库中的条目发生更改时得到通知。
但是因为 SQLDelight 为存储的实体生成它自己的类并在流中发出它们,所以我无法将存储的类转换为在我的应用程序的其余部分使用的类。

您可以在下面找到我的 FriendEntity SQL 类型和查询函数的摘录,SQLDelight 使用它来生成 FriendEntity 数据类和 kotlin 函数(问题底部的生成输出)

// SQLDelight queries
CREATE TABLE FriendEntity (
        id TEXT NOT NULL PRIMARY KEY,
        username TEXT NOT NULL,
        firstname TEXT NOT NULL,
        lastname TEXT,
        phone TEXT,
        picture TEXT,
        accepted INTEGER AS Boolean DEFAULT 0 NOT NULL

getFriendById:
SELECT * FROM FriendEntity
WHERE id = :id;
);

下面我想创建一个缓存服务,它也发出 flow 但类型为 Friend 而不是 FriendEntity 所以我必须以某种方式将 FriendEntity 类转换为我的 Friend 类,同时仍然返回一个流。
如果不先收集流量,这是否可能?


override fun get(id: String): Flow<Friend>? {
    return try {
        return queries.getFriendById(id = id).asFlow() //returns Flow<Query<FriendEntity>>
    } catch (e: NullPointerException) {
        null
    }
}

data class Friend(
    var profile: Profile,
    var accepted: Boolean
)

data class Profile(
    var id: String,
    var username: String,
    var firstname: String,
    var lastname: String?,
    var phone: String? = null,
    var picture: String? = null,
)

由 SQLDelight 生成:

public fun <T : Any> getFriendById(id: String, mapper: (
    id: String,
    username: String,
    firstname: String,
    lastname: String?,
    phone: String?,
    picture: String?,
    accepted: Boolean
  ) -> T): Query<T>

  public fun getFriendById(id: String): Query<FriendEntity>
public data class FriendEntity(
  public val id: String,
  public val username: String,
  public val firstname: String,
  public val lastname: String?,
  public val phone: String?,
  public val picture: String?,
  public val accepted: Boolean
) {
  public override fun toString(): String = """
  |FriendEntity [
  |  id: $id
  |  username: $username
  |  firstname: $firstname
  |  lastname: $lastname
  |  phone: $phone
  |  picture: $picture
  |  accepted: $accepted
  |]
  """.trimMargin()
}

【问题讨论】:

    标签: kotlin kotlin-coroutines sqldelight kotlinx.coroutines.flow


    【解决方案1】:

    您必须在源集中使用此扩展实现。

    kotlin {
      sourceSets.commonMain.dependencies {
        implementation "com.squareup.sqldelight:coroutines-extensions:1.5.3"
      }
    }
    

    现在你可以得到类似的数据

    val data: Flow<List<//YourDataClass>> = 
      query.selectAll()
        .asFlow()
        .mapToList()
    

    参考:SQLDelight with flow

    【讨论】:

      【解决方案2】:

      我在他们的 Github 讨论中提出了这个问题,并得到了一个不依赖于扩展的创建答案。调用查询时可以使用自定义映射器参数:

      override fun get(id: Long): Flow<Query<Friend>>? {
        return try {
            return queries.getFriendById(
                id = id,
                mapper = { friendId, username, firstname, lastname, phone, picture, accepted ->
                    Friend(
                        Profile(friendId, username, firstname, lastname, phone, picture),
                        accepted
                    )
                }).asFlow()
        } catch (e: NullPointerException) {
            null
        }
      }
      

      抄送:亚历克·斯特朗
      https://github.com/cashapp/sqldelight/discussions/2782

      【讨论】:

        猜你喜欢
        • 2019-08-13
        • 1970-01-01
        • 1970-01-01
        • 2019-08-20
        • 2017-08-25
        • 2011-09-14
        • 2018-04-01
        • 1970-01-01
        • 2019-01-03
        相关资源
        最近更新 更多