Room Dao Returns 插入 ID 但数据库中缺少数据
Room Dao Returns Insert IDs but Data is Missing from Database
使用 Dao 在我的房间数据库中保存对象列表时
@Insert()
fun saveCharmRankMaterialCosts(materialCosts: List<CharmRankCraftingCost>) : List<Long>
这在我的存储库 class 中用于保存 API 调用的结果:
val charmRankCosts = CharmRankCraftingCost.fromJsonCraftingCost(
charmRankId.toInt(),
jsonCharmRank.crafting
)
// save crafting/upgrade costs for the rank
val results = charmDao.saveCharmRankMaterialCosts(charmRankCosts)
Log.d("CharmRepository", "Saved charm material costs: ${results.toString()}");
assert(!results.contains(-1))
当 运行 此代码时,返回插入 ID,并且永远不会触发断言(即没有插入失败)。
但是当我检查设备上的数据库时,table 中缺少大多数假定插入的 ID。我对这里发生的事情感到很困惑。我已经调试了这个问题好几个小时,但未能成功解决这个问题。有什么明显的我想念的吗?
正如我从评论中了解到的,您在插入之前进行了删除。问题是碰巧插入在删除之前完成,因为您在单独的线程中执行它们。您需要做的是在一次交易中同时执行这两项操作。使用@Transaction 注解在 DAO class 中创建一个方法(确保你的 dao 是一个抽象的 class 这样你就可以实现这个方法的主体):
@Dao
public abstract class YourDao{
@Insert(onConflict = OnConflictStrategy.IGNORE)
public abstract List<Long> insertData(List<Data> list);
@Query("DELETE FROM your_table")
public abstract void deleteData();
@Transaction
public void insertAndDeleteInTransaction(List<Data> list) {
// Anything inside this method runs in a single transaction.
deleteData();
insertData(list);
}
}
阅读 代码的 Kotlin 版本。
问题似乎与外键约束有关。我有一个包含多个相关数据对象的 CharmRank
数据 class。见下文:
/**
* Copyright Paul, 2020
* Part of the MHW Database project.
*
* Licensed under the MIT License
*/
@Entity(tableName = "charm_ranks")
data class CharmRank(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "charm_rank_id")
var id: Int = 0,
@ColumnInfo(name = "charm_id")
var charmId : Int,
@ColumnInfo(name = "charm_rank_level")
var level: Int = 0, // 3
@ColumnInfo(name = "charm_rank_rarity")
var rarity: Int = 0, // 6
@ColumnInfo(name = "charm_rank_name")
var name: String = "",
@ColumnInfo(name = "craftable")
var craftable: Boolean
)
每个魅力等级都有相关的技能和物品来制作所述等级。这些对象只是关系对象,因为它们包含 CharmRank
的 ID 和技能对象的 SkillRank
,或者 CharmRank
的 ID 和 Item
对象。
data class CharmRankSkill(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "charm_rank_skill_id")
var id: Int,
var charmRankId : Int,
var skillRankId: Int
)
data class CharmRankCraftingCost(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "charm_rank_crafting_cost_id")
var id: Int,
@ColumnInfo(name = "charm_rank_id")
var charmRankId: Int,
@ColumnInfo(name = "charm_rank_crafting_cost_item_quantity")
val quantity: Int,
val itemId: Int
)
最初在CharmRankCraftingCost
中,我在Item
对象和CharmRank
对象上有一个外键约束。下面是 Item
对象的外键约束:
ForeignKey(
entity = Item::class,
parentColumns = ["item_id"],
childColumns = ["itemId"],
onDelete = ForeignKey.CASCADE
)
Item
数据对象具有远程数据源提供的 ID,因此当我将项目插入其各自的 table 时,冲突解决方案设置为 Replace
。在将关系项目保存到 CharmRanks
的数据库的过程中,我还必须在保存 CharmRankCraftingCosts
之前保存 Item
个对象。似乎发生的事情是,当插入 Item
对象时,有时项目会被替换,这会触发外键的级联操作,从而导致我刚刚保存的 CharmRankCraftingCosts
项目CharmRank
因级联效应待删除。
删除 Item
table 上的外键约束解决了我的问题。
使用 Dao 在我的房间数据库中保存对象列表时
@Insert()
fun saveCharmRankMaterialCosts(materialCosts: List<CharmRankCraftingCost>) : List<Long>
这在我的存储库 class 中用于保存 API 调用的结果:
val charmRankCosts = CharmRankCraftingCost.fromJsonCraftingCost(
charmRankId.toInt(),
jsonCharmRank.crafting
)
// save crafting/upgrade costs for the rank
val results = charmDao.saveCharmRankMaterialCosts(charmRankCosts)
Log.d("CharmRepository", "Saved charm material costs: ${results.toString()}");
assert(!results.contains(-1))
当 运行 此代码时,返回插入 ID,并且永远不会触发断言(即没有插入失败)。
但是当我检查设备上的数据库时,table 中缺少大多数假定插入的 ID。我对这里发生的事情感到很困惑。我已经调试了这个问题好几个小时,但未能成功解决这个问题。有什么明显的我想念的吗?
正如我从评论中了解到的,您在插入之前进行了删除。问题是碰巧插入在删除之前完成,因为您在单独的线程中执行它们。您需要做的是在一次交易中同时执行这两项操作。使用@Transaction 注解在 DAO class 中创建一个方法(确保你的 dao 是一个抽象的 class 这样你就可以实现这个方法的主体):
@Dao
public abstract class YourDao{
@Insert(onConflict = OnConflictStrategy.IGNORE)
public abstract List<Long> insertData(List<Data> list);
@Query("DELETE FROM your_table")
public abstract void deleteData();
@Transaction
public void insertAndDeleteInTransaction(List<Data> list) {
// Anything inside this method runs in a single transaction.
deleteData();
insertData(list);
}
}
阅读
问题似乎与外键约束有关。我有一个包含多个相关数据对象的 CharmRank
数据 class。见下文:
/**
* Copyright Paul, 2020
* Part of the MHW Database project.
*
* Licensed under the MIT License
*/
@Entity(tableName = "charm_ranks")
data class CharmRank(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "charm_rank_id")
var id: Int = 0,
@ColumnInfo(name = "charm_id")
var charmId : Int,
@ColumnInfo(name = "charm_rank_level")
var level: Int = 0, // 3
@ColumnInfo(name = "charm_rank_rarity")
var rarity: Int = 0, // 6
@ColumnInfo(name = "charm_rank_name")
var name: String = "",
@ColumnInfo(name = "craftable")
var craftable: Boolean
)
每个魅力等级都有相关的技能和物品来制作所述等级。这些对象只是关系对象,因为它们包含 CharmRank
的 ID 和技能对象的 SkillRank
,或者 CharmRank
的 ID 和 Item
对象。
data class CharmRankSkill(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "charm_rank_skill_id")
var id: Int,
var charmRankId : Int,
var skillRankId: Int
)
data class CharmRankCraftingCost(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "charm_rank_crafting_cost_id")
var id: Int,
@ColumnInfo(name = "charm_rank_id")
var charmRankId: Int,
@ColumnInfo(name = "charm_rank_crafting_cost_item_quantity")
val quantity: Int,
val itemId: Int
)
最初在CharmRankCraftingCost
中,我在Item
对象和CharmRank
对象上有一个外键约束。下面是 Item
对象的外键约束:
ForeignKey(
entity = Item::class,
parentColumns = ["item_id"],
childColumns = ["itemId"],
onDelete = ForeignKey.CASCADE
)
Item
数据对象具有远程数据源提供的 ID,因此当我将项目插入其各自的 table 时,冲突解决方案设置为 Replace
。在将关系项目保存到 CharmRanks
的数据库的过程中,我还必须在保存 CharmRankCraftingCosts
之前保存 Item
个对象。似乎发生的事情是,当插入 Item
对象时,有时项目会被替换,这会触发外键的级联操作,从而导致我刚刚保存的 CharmRankCraftingCosts
项目CharmRank
因级联效应待删除。
删除 Item
table 上的外键约束解决了我的问题。