SQLDelight关系

dip*_*dip 7 android relationship kotlin sqldelight

我想使用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
);
Run Code Online (Sandbox Code Playgroud)

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

我有2个目标:

  • 写一个包含所有成分的食谱
  • 阅读包含所有成分的食谱

我很确定第一个只能手动完成,例如插入食谱,然后手动插入关联的成分。

对于后者,我尝试使用以下语句连接表:

selectWithIngredients:
SELECT *
FROM recipe
INNER JOIN ingredient ON recipe.id = ingredient.recipe_id
WHERE recipe.id=?;
Run Code Online (Sandbox Code Playgroud)

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

public data class SelectWithIngredients(
  public val id: Long,
  public val name: String,
  public val recipe_id: Long,
  public val name_: String,
)
Run Code Online (Sandbox Code Playgroud)

有没有一种好的方法可以使用一个生成的函数来检索数据(食谱+成分列表)?类似于房间 @Embedded@Relation注释的东西。

Ale*_*kin 11

不幸的是,SQLDelight 并不是那么精致。它所做的只是为查询的每一行提供一个数据类,如果您想要执行更复杂的逻辑,例如将一个表映射到其他表的列表,那么您需要自己在 kotlin 中执行此操作。

例如有这样的食谱

data class Recipe(val name: String, val ingredients: List<String>)
Run Code Online (Sandbox Code Playgroud)

您可以使用您的选择来执行此操作

val rows: List<SelectWithIngredients> 

rows.groupBy { it.name }
    .map { (recipe, selectRows) -> 
            Recipe(name, selectRows.map { it.name_ } 
    }  
Run Code Online (Sandbox Code Playgroud)

  • 不,您仍然可以使用唯一的 [SELECT](https://www.db-fiddle.com/f/mg3P3WMNbPnLtTnr39BxNW/4) 查询。它将返回 SQLDelight 映射到 List&lt;SelectWithIngredients&gt; 的行列表。每行都会有一个菜谱名称。因此,您只需要对其进行转换即可获取“Recipe”或按原样使用。 (2认同)