如何将数据插入多对多关系表并检索最后一个 ID 在该方法接受两个参数的情况下?

How to Insert data to Many to many relationship tables and retrieving last id In cases where the method accepts two parameters?

当输入只有一个参数时,Room return 插入的 id

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

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

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

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


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
) 

How can i retrieve the ID when method looks like this

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

中获得结果 ID

但是,对于基本交叉 reference/mapping table,您很少会使用 rowid 列(即返回值)。

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

    • 当您使用INTEGER PRIMARY KEY定义列时,该列是rowid列的别名。在房间 @PrimaryKey 中,对于 Long 或 Int,有或没有 autoGenerate = true/false(没有 = false)等于 INTEGER PRIMARY KEY 或者如果 autoGenerate = true 等于 INTEGER PRIMARY KEY AUTOINCREMENT.

How do you handle many-to-many relationship Insert?

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

所以除了你的 DrinkFavouriteAndDrinksCrossRef 实体。

DrinkFavourite 和 Item 的实体是

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

数据class饮料( @PrimaryKey var itemId : 长?, 变种项目名称:字符串 )

The Dao 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 个实体中的每一个插入一个 Entity/row 和多个 Entity/row。

下面利用道中定义的3多插入插入3Drink、4DrinkFavourite再插入12DrinkFavouriteAndDrinksCrossRef(3Drink * 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 个排列。

除了根据插入的 Entity/Object 进行插入之外,我不相信您可以有效地使用 @Insert 进行其他操作。要根据其他值进行更复杂的插入,您可以使用 @Query 和 suitable 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 都有这三种饮料