【问题标题】:How to insert entities with a one to many relationship in Room如何在 Room 中插入具有一对多关系的实体
【发布时间】:2021-04-21 21:33:20
【问题描述】:

我正在使用 Room 构建数据库,但我不知道如何将具有关系的新元素(在我的例子中是一对多)插入到数据库中。没有任何解决方案谈论过插入(他们只谈论查询数据)。

这是 DAO:

@Dao
abstract class ShoppingListsDao {

    @Insert
    abstract suspend fun addNewShoppingList(newShoppingList: ShoppingList)

    @Insert
    abstract suspend fun addNewItem(newItem: Item)

     // This is how I thought it would work but it didn't
     @Insert
     @Transaction
     abstract suspend fun addNewShoppingListWithItems(newShoppingListWithItems: ShoppingListWithItems)
}

这是我的实体:

@Entity
class ShoppingList(
        @PrimaryKey(autoGenerate = true)
        val listID: Int,
        val ListName: String
)

@Entity(foreignKeys = [ForeignKey(
        entity = ShoppingList::class,
        parentColumns = ["listID"],
        childColumns = ["parentListID"]
)])
class Item(
        @PrimaryKey(autoGenerate = true)
        var itemID: Int,
        val name: String,
        val quantity: Int,
        val parentListID: Int
)

【问题讨论】:

  • 你应该正常插入它们。不需要做任何额外的事情。
  • 你能解释一下吗?
  • 我的意思是我要确保每个Item都有正确的parentListID,这样我才能得到每个Shopping list对应的Items。
  • 您应该运行一个事务,首先插入ShoppingList,然后插入所有Item 实体。发布的答案几乎是您想要的,您遇到的问题与此问题无关,并且有大量有关插入实体列表的官方文档。
  • 是的,如果你能让事情变得更清楚更好理解,请发布答案。因为我很难理解这个操作......在此先感谢您的帮助。

标签: android kotlin android-room android-jetpack


【解决方案1】:

据我所知,没有一种方法可以让您直接插入复合实体(如ShoppingListWithItems)。您只需将各个实体插入到他们的表中即可。

在您的示例中,您可能希望为您的 ShoppingList 实体定义一个插入方法,该方法返回生成的主键(以便您可以将其用于您的其他项目),并为您的 Item 实体定义一个插入方法,该方法可以插入它们的完整列表。

@Insert
suspend fun addNewShoppingList(newShoppingList: ShoppingList): Long
@Insert
suspend fun addNewItems(newItems: List<Item>)

然后您可以运行事务以将它们批量插入。

@Transaction
suspend fun addNewShoppingListWithItems(shoppingList: ShoppingList, items: List<Item>) {

    val listId = addNewShoppingList(shoppingList)
    
    items.forEach { it.parentListId = listId }
    addNewItems(items)
}

【讨论】:

    【解决方案2】:

    这是了解一对多关系的好资源-> https://developer.android.com/training/data-storage/room/relationships#one-to-many

    您可以为“ShoppingListWithItems”创建一个嵌入式对象(更多关于嵌入式对象 - https://developer.android.com/training/data-storage/room/relationships#nested-objects):

    data class ShoppingListWithItems(
        @Embedded val shoppingList: ShoppingList,
        @Relation(parentColumn = "listID", entityColumn = "parentListID") val itemList: List<Item>
    )
    

    要将它们存储在数据库中,您可以简单地使用事务:

    @Transaction
    suspend fun createTransaction(shoppingList: ShoppingList, itemList: List<Item>) {
        addNewShoppingList(shoppingList)
        addNewItem(*itemList) // or create an alternate to accept the list itself.
    }
    

    检索“ShoppingListWithItems”实例:

    @Query("SELECT * from ShoppingList where listID =:id")
    suspend fun getShoppingListWithItemsById(id: String): List<ShoppingListWithItems>
    

    【讨论】:

    • 但是“addNewItem()”只接受一个项目,当我创建这个方法时:@Insert abstract suspend fun addNewItem(items: List) 这个错误在我构建应用程序时显示:任务 ':app:kaptDebugKotlin' 执行失败。 > 执行 org.jetbrains.kotlin.gradle.internal.KaptExecution 时发生故障 > java.lang.reflect.InvocationTargetException(无错误消息) * 尝试:使用 --stacktrace 选项运行以获取堆栈跟踪。使用 --info 或 --debug 选项运行以获得更多日志输出。运行 --scan 以获得完整的见解。
    • 您可以尝试将其创建为@Insert abstract suspend fun addNewItem(vararg items: Item)
    • 另外,如果你愿意,定义一个冲突策略
    猜你喜欢
    • 2020-05-27
    • 2020-01-26
    • 1970-01-01
    • 2011-07-21
    • 2017-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-23
    相关资源
    最近更新 更多