首页 > 解决方案 > 如何将数据插入多对多关系表并检索最后一个 id 在方法接受两个参数的情况下?

问题描述

当输入只有一个参数时,Room 会返回插入的 id

  @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertWithDrinks(item: DrinkFavourite): Long 

当方法看起来像这样时,我如何检索 ID

 @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertWithDrinks(item: DrinkFavourite, List<Drink>)

或者更确切地说,您如何处理多对多关系插入?我有这样的关系和交叉引用表


data class DrinkFavouritesWithDrinks(
    @Embedded
    val item: DrinkFavourite,
    @Relation(
        parentColumn = "item_id",
        entityColumn = "drink_id",
        associateBy = Junction(DrinkFavouriteAndDrinksCrossRef::class)
    )
    val drinks: List<Drink> = emptyList()
)

我的交叉参考

@Entity(
    primaryKeys = ["item_id", "drink_id"]
)
data class DrinkFavouriteAndDrinksCrossRef(
    @ColumnInfo(name = "item_id")
    val itemId: Long,
    @ColumnInfo(name = "drink_id")
    val drinkId: Int
) 

标签: androidmany-to-manyandroid-roomdao

解决方案


当方法看起来像这样时,我如何检索 ID

当您插入多行时,您会在Array<Long>

但是,对于基本的交叉引用/映射表,您很少会使用rowid列(这是返回的值)。

  • 即使列是隐式定义的,也会返回rowid 。除了很少使用的 WITHOUT ROWID 表之外,所有表都有一个名为rowid的隐藏列。

    • 用于INTEGER PRIMARY KEY定义列时,该列是rowid列的别名。在房间 @PrimaryKey 中,对于 Long 或 Int,有或没有autoGenerate = true/false(无 = false)等于INTEGER PRIMARY KEY或 if autoGenerate = trueto INTEGER PRIMARY KEY AUTOINCREMENT

你如何处理多对多关系插入?

这是一个示例,基于可用代码,并创建了其他代码。

所以除了你的 DrinkFavouriteAndDrinksCrossRef 实体。

DrinkFavourite 和 Item 的实体是

@Entity
 data class DrinkFavourite(
    @PrimaryKey
    val drink_id: Int? = null,
    val drink_name: String = ""
)
@Entity

数据类 Drink(@PrimaryKey var itemId :Long?, var itemName: String )

AllDao是:-

@Dao
interface AllDao {

    @Insert
    fun insertDrinkFavourite(drinkFavourite: DrinkFavourite) :Long

    @Insert
    fun insertManyDrinkFavourite(drinkFavourites: List<DrinkFavourite>) :Array<Long>

    @Insert
    fun insertItem(drink: Drink) :Long

    @Insert
    fun insertManyItems(drinks: List<Drink>) :Array<Long>

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    fun insertDrinkFavouriteAndDrinksCrossRef(drinkFavouriteAndDrinksCrossRef: DrinkFavouriteAndDrinksCrossRef) :Long

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    fun insertManyDrinkFavouriteAndDrinksCrossRef(drinkFavouriteAndDrinksCrossRefs: List<DrinkFavouriteAndDrinksCrossRef>) :Array<Long>
}
  • 这适合为 3 个实体中的每一个插入单个实体/行和许多实体/行。

下面利用 Dao 中定义的 3 many 插入插入 3 Drinks、4 DrinkFavourites,然后插入 12 DrinkFavouriteAndDrinksCrossRefs (3 Drink* 4 DrinkFavorite) 排列,即所有可能的排列,可以根据插入的 id 进行交叉引用。

class MainActivity : AppCompatActivity() {

    lateinit var database: Database

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        database = Room.databaseBuilder(this, Database::class.java, "drinksdb")
            .allowMainThreadQueries()
            .build()
        //val firsItemtid = database.allDao().insertItem( Item(0,"X"))
        val manyItemIds = database.allDao().insertManyItems(
            listOf(
                Drink(null,"A"),
                Drink(null,"B"),
                Drink(null,"C")
            )
        )
        val manyDrinkFavouriteIds = database.allDao().insertManyDrinkFavourite(
            listOf(
                DrinkFavourite(null,"DrinkA"),
                DrinkFavourite(null,"DrinkB"),
                DrinkFavourite(null,"DrinkC"),
                DrinkFavourite(null,"DrinkD")
            )
        )

        var xrefcombos = ArrayList<DrinkFavouriteAndDrinksCrossRef>()
        for(itemId: Long in manyItemIds) {
            for (dfId: Long in manyDrinkFavouriteIds) {
                xrefcombos.add( DrinkFavouriteAndDrinksCrossRef(itemId,dfId.toInt()))
            }
        }
        val drinkFavouriteAndDrinksCrossRefIdList = database.allDao().insertManyDrinkFavouriteAndDrinksCrossRef(xrefcombos)
        for (dfadcrId in drinkFavouriteAndDrinksCrossRefIdList) {
            Log.d("DRKFAVDRNKXREF","Id = " + dfadcrId)
        }
    }
}

输出是: -

2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 1
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 2
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 3
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 4
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 5
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 6
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 7
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 8
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 9
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 10
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 11
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 12

即添加了 12 个排列。

我不相信您可以@Insert根据插入的实体/对象有效地用于插入以外的操作。要根据其他值进行更复杂的插入,您可以使用@Query合适的 SQL。

额外的

关于 :-

data class DrinkFavouritesWithDrinks(
    @Embedded
    val item: DrinkFavourite,
    @Relation(
        parentColumn = "item_id",
        entityColumn = "drink_id",
        associateBy = Junction(DrinkFavouriteAndDrinksCrossRef::class)
    )

我相信这应该是:-

data class DrinkFavouriteWithDrinks (

    @Embedded
    val drinkFavourite: DrinkFavourite,
    @Relation(
        entity =  Drink::class,
        entityColumn = "itemId",
        parentColumn = "drink_id",
        associateBy = Junction(
            DrinkFavouriteAndDrinksCrossRef::class,entityColumn = "item_id",parentColumn = "drink_id"))
    val drinks: List<Drink> = emptyList()
    )
  • 您可以获得每个 DrinkFavourite 的所有饮品,因此单数而不是复数是一个更好的名称。
  • 关联需要知道要关联的列。

您可以使用 Dao 方法,例如:-

@Query("SELECT * FROM drinkfavourite")
fun getAllDrinkFavouritesWithDrinks() :List<DrinkFavouriteWithDrinks>

在上面的 MainActivity 中添加以下内容:-

    val drinkFavouriteWithDrinksList = database.allDao().getAllDrinkFavouritesWithDrinks()
    var sb = StringBuilder()
    for (dfwd: DrinkFavouriteWithDrinks in drinkFavouriteWithDrinksList) {
        sb.clear().append("DrinkFavourite = ").append(dfwd.drinkFavourite)
        for (d: Drink in dfwd.drinks) {
            sb.append("\n\tDrink = ").append(d.itemName)
        }
        Log.d("DRINKFAVINFO", sb.toString())
    }

结果是 :-

2020-01-17 11:39:52.762 D/DRINKFAVINFO: DrinkFavourite = DrinkFavourite(drink_id=1, drinkFavouriteName=DrinkA)
      Drink = A
      Drink = B
      Drink = C
2020-01-17 11:39:52.763 D/DRINKFAVINFO: DrinkFavourite = DrinkFavourite(drink_id=2, drinkFavouriteName=DrinkB)
      Drink = A
      Drink = B
      Drink = C
2020-01-17 11:39:52.763 D/DRINKFAVINFO: DrinkFavourite = DrinkFavourite(drink_id=3, drinkFavouriteName=DrinkC)
      Drink = A
      Drink = B
      Drink = C
2020-01-17 11:39:52.763 D/DRINKFAVINFO: DrinkFavourite = DrinkFavourite(drink_id=4, drinkFavouriteName=DrinkD)
      Drink = A
      Drink = B
      Drink = C
  • 不是最好的例子,因为每个 DrinkFavourite 都有所有三种饮料

推荐阅读