【问题标题】:prevent greenDAO inserting duplicate entry防止greenDAO插入重复条目
【发布时间】:2017-09-04 12:02:54
【问题描述】:

我有一个活动,一旦活动开始,它将解析 json 数据并使用 greenDAO 更新数据库。它的更新代码是这样的:

exampleDao.insertOrReplace(exampleObj);

但是当activity返回并恢复时,它会一直插入导致重复的数据输入,不同的主键但相同的数据,如何防止重复数据输入?

非常感谢

【问题讨论】:

  • 请发布您的真实架构(最少要插入/更新的实体)。这个问题很重要。

标签: android duplicates greendao


【解决方案1】:

由于您没有提供有关数据模型的架构或类似信息,因此此答案只是猜测!

您可能正在使用自动递增的主键。

这意味着您的主键可能未包含在您的 JSON 数据中,导致主键属性为空。

这告诉 greendao 这是一个新条目,greendao 将插入一个带有新主键的新条目。

尝试先读取对象,然后调用insertOrReplace:

Example oldObj;
try {
    // Try to find the Example-Object if it is already existing.
    oldObj = exampleDao.queryBuilder().where(someCondition).unique();
} catch (Exception ex) {
    oldObj = null;
}
if (oldObj == null) {
    oldObj = new Example();
}
// update oldObj with the data from JSON
exampleDao.insertOrReplace(oldObj);

【讨论】:

  • 感谢 Alexs 的及时帮助,最后我发现在 for 循环 insertOrReplace(daoObj) 期间,我忘记创建新的 DAOobj for(int i = 0; i
  • @user3662946 欢迎您。如果我的回答解决了你的问题,请采纳。
【解决方案2】:

使一列(来自 your_Id 的其他列)唯一,并将其​​用作真正的主键。

【讨论】:

  • 实际上,虽然 id 是由 DAO 默认创建的,但似乎没有必要将列设置为唯一?我发现我的错误,我忘记在 for 循环期间创建新的 obj 以将列表对象插入或替换到数据库。谢谢
  • 很好的解决方案。简单而优雅。 DAO 不支持字符串作为主键,这是我的情况,所以我简单地将 .unique() 添加到架构中并完美运行。 product.addStringProperty("objectId").unique();
  • @Laranjeiro 在尝试添加具有相同唯一值的值时系统会抛出错误吗?还是覆盖现有的?
【解决方案3】:

@Hiep 的解决方案是正确的,但并不完全正确:不需要更改表的主键。

事实上,在所有实体字段上添加 @Unique 注释就足够了,这些字段应该为方程式进行比较,GreenDao 将处理其余部分:如果您使用 insertOrReplace 插入的实体在所有唯一字段上都相等一些已经存储的实体,那么旧实体将被删除并添加新实体。

请注意,这个“交换”实际上是一个更新,但“更新”实体的行 ID(主键)会有所不同(因此该方法称为insertOrReplace)。

所以,给定以下实体:

@Entity
public static class TestEntity {

    @Id(autoincrement = true)
    private Long id;

    @Unique @NotNull private String code;

    @NotNull private String description;

    // constructor and getters/setters here
}

以下测试通过(您可以使用 Robolectric 运行):

@Test
public void insertOrReplace_nullRowIdSameUniqueField_existingEntryReplaced() {
    // Arrange
    TestEntity testEntity = new TestEntity(null, "code", "old description");
    mDaoSession.getTestEntityDao().insert(testEntity);

    assertThat(mDaoSession.getTestEntityDao().loadAll().size(), is(1)); // assert insertion succeeded

    // Act
    TestEntity testEntityOther = new TestEntity(null, "code", "new description");
    mDaoSession.getTestEntityDao().insertOrReplace(testEntityOther);

    // Assert
    List<TestEntity> testEntityList = mDaoSession.getTestEntityDao().loadAll();

    assertThat(testEntityList.size(), is(1)); // number of entities did not change
    assertEquals(testEntityList.get(0).getCode(), "code"); // same code
    assertEquals(testEntityList.get(0).getDescription(), "new description"); // updated description
}

【讨论】:

    【解决方案4】:

    确保您的实体设置了主键属性 (!= null)。

    【讨论】:

    • 感谢您的回复,但我发现我的错误是在 insertOrReplace 时忘记在循环中创建新的 DaoObj。
    猜你喜欢
    • 2015-08-07
    • 1970-01-01
    • 1970-01-01
    • 2016-02-19
    • 2012-08-30
    • 1970-01-01
    • 1970-01-01
    • 2015-11-29
    • 2012-08-02
    相关资源
    最近更新 更多