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 上的外键约束解决了我的问题。