SQLDelight 关系

Posted

技术标签:

【中文标题】SQLDelight 关系【英文标题】:SQLDelight Relationships 【发布时间】:2021-10-08 10:29:35 【问题描述】:

我想用SQLDelight 建模关系,尤其是一对多关系。

我有 2 张桌子:recipeingredient。为简单起见,它们看起来像这样:

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

CREATE TABLE ingredient (
  recipe_id INTEGER NOT NULL,
  name TEXT NOT NULL,
  FOREIGN KEY (recipe_id) REFERENCES recipe(id) ON DELETE CASCADE
);

所以我有一个食谱列表,每个食谱可以包含 0-n 种成分。

我有两个目标:

编写包含所有成分的食谱 阅读包含所有成分的食谱

我很确定第一个只能手动完成,例如插入配方,然后手动插入相关成分。

对于后者,我尝试使用以下语句加入表格:

selectWithIngredients:
SELECT *
FROM recipe
INNER JOIN ingredient ON recipe.id = ingredient.recipe_id
WHERE recipe.id=?;

SQLDelight 为我生成了一个 1:1 的关系文件:

public data class SelectWithIngredients(
  public val id: Long,
  public val name: String,
  public val recipe_id: Long,
  public val name_: String,
)

有没有什么好的方法可以用一个生成的函数来检索数据(配方 + 成分列表)?类似于 Rooms @Embedded@Relation 注释的东西。

【问题讨论】:

【参考方案1】:

不幸的是,SQLDelight 没有那么精致。它所做的只是为查询的每一行提供一个数据类,如果你想做更复杂的逻辑,比如将一个表映射到另一个表的列表,而不是你需要在 kotlin 中自己做。

例如有这样的食谱

data class Recipe(val name: String, val ingredients: List<String>)

你可以用你的选择来做到这一点

val rows: List<SelectWithIngredients> 

rows.groupBy  it.name 
    .map  (recipe, selectRows) -> 
            Recipe(name, selectRows.map  it.name_  
      

【讨论】:

我同意! Kotlin 在这方面做得很好。 如果我理解正确,这是否意味着我必须进行 2 次查询?当然 Kotlin 擅长这一点,但这很可能意味着性能比一个查询更差。 不,您仍然可以使用您唯一的 SELECT 查询。它将返回 SQLDelight 映射到 List 的行列表。您将在每一行中都有一个食谱名称。因此,您只需将其转换为获取 Recipe 或按原样使用。 啊,是的。这应该足够了。谢谢!

以上是关于SQLDelight 关系的主要内容,如果未能解决你的问题,请参考以下文章

与 Room 相比,SQLDelight 性能较慢

如何在 KMM 上为 SQLDelight 编写单元测试

SqlDelight/SQLite 没有正确执行连接?

如何更改 SQLDelight 中表的主键?

SQLDelight:如何动态创建表?

未生成 Sqldelight 数据库架构