android - 如何将数据插入多对多关系表并检索最后一个 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
)
解决方案
当方法看起来像这样时,我如何检索 ID
当您插入多行时,您会在Array<Long>
但是,对于基本的交叉引用/映射表,您很少会使用rowid列(这是返回的值)。
即使列是隐式定义的,也会返回rowid 。除了很少使用的 WITHOUT ROWID 表之外,所有表都有一个名为rowid的隐藏列。
- 用于
INTEGER PRIMARY KEY
定义列时,该列是rowid列的别名。在房间 @PrimaryKey 中,对于 Long 或 Int,有或没有autoGenerate = true/false
(无 = false)等于INTEGER PRIMARY KEY
或 ifautoGenerate = true
toINTEGER 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 Drink
s、4 DrinkFavourite
s,然后插入 12 DrinkFavouriteAndDrinksCrossRef
s (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 都有所有三种饮料
推荐阅读
- mysql - 将 3 个 yii2 查询组合在一起时面临的问题
- wordpress - 任何脚本的 wp_enqueue_script() wordpress 问题
- python-3.x - 如何限制对heroku应用程序(标准域)的访问?
- graphql - 将项目添加到列表时,乐观响应不起作用
- typescript - typescript 从子类调用的构造函数参数推断类型
- c++ - 将 make 文件与具有多个目录的项目一起使用
- asp.net-mvc - 为复杂对象构建 UI
- node.js - 数据已添加到数据库,但邮递员返回空白。我错过了什么?
- azure-devops - 看不到邮递员测试结果 azure devops
- mongodb - 如何在 .htaccess WordPress 中添加以下安全标头