【问题标题】:java.lang.IllegalStateException: Nested transactions are not allowed. Use commitTransaction() after each beginTransaction()java.lang.IllegalStateException:不允许嵌套事务。在每个 beginTransaction() 之后使用 commitTransaction()
【发布时间】:2016-11-30 08:09:24
【问题描述】:
public RealmList<CategoriesDto> getListOfCategories(String type){

    final RealmList<CategoriesDto> listOfCategories = new RealmList<>();

    final CategoriesDto  categoriesDto = realm.where(CategoriesDto.class).equalTo("identifier", type).findFirst();

    if (categoriesDto != null) {

        realm.beginTransaction();
            RealmResults<CategoriesDto> categories = realm.where(CategoriesDto.class).equalTo("parentId", categoriesDto.getCategoryId()).findAll();
            for (int i = 0; i < categories.size(); i++) {
                listOfCategories.add(categories.get(i));
            }
        //  realm.commitTransaction();
    }

    return listOfCategories;
}

我在一个方法中查询领域两次,并收到此错误,我在每次查询后都尝试了realm.beginTransaction()realm.commitTransaction()

还有一件事:这个查询只从领域数据库中读取数据。

在数据库中写入数据我们一般使用commit来持久化数据。

我也尝试过realm.commitTransaction(),但我遇到了同样的错误。

【问题讨论】:

  • 我对领域一无所知。在读取查询之前真的需要调用 beginTransaction() 吗?
  • 是的,如果你没有调用那么应用程序也会崩溃并且错误是“你需要调用 reaml.beginTransactio()”
  • 您是否尝试在 for 循环中添加 beginTransactioncommitTransaction
  • @Sagar 我们正在查询 forloop 之外的领域,为什么我们可以在 foorloop 中 beginTransaction() 和 commitTransaction() ,如果我取消评论 reaml.commitTransaction() 那么这个错误来了“更改 Realm 数据只能在事务内部完成。”
  • 为什么你甚至需要RealmList?为什么不使用RealmResults?它也是List。这确实取决于您的用例,并且对于这么多的代码,我只能说您没有按预期使用 Realm。

标签: android realm


【解决方案1】:

如果在持久化时您拥有所有类别的 DTOS:

public class CategoriesDto extends RealmObject {
    @PrimaryKey
    private String categoryId;

    @Index
    private String identifier;

    @Index
    private String parentId;

    private CategoriesDto parent;

    //getters, setters
}

然后你就可以了

realm.executeTransaction(new Realm.Transaction() {
    @Override
    public void execute(Realm realm) {
        realm.insertOrUpdate(dtos);
        RealmResults<CategoriesDto> children = realm.where(CategoriesDto.class)
                                                    .isNotNull("parentId")
                                                    .isNull("parent")
                                                    .findAll();
        for(CategoriesDto category : children) {
            CategoriesDto parent = realm.where(CategoriesDto.class).equalTo("categoryId", category.getParentId()).findFirst();
            category.setParent(category);
        }
        realm.insertOrUpdate(children);
    }
});

那你就可以了

public RealmResults<CategoriesDto> getListOfCategories(String type) { 
    return realm.where(CategoriesDto.class)
                .equalTo("identifier", type)
                .equalTo("parent.categoryId", categoriesDto.getCategoryId())
                .findAll();
}

但在您的情况下,您只需要不打开交易,并使用copyFromRealm()。不过,在这种情况下,我不确定您为什么要使用 RealmList&lt;T&gt;

【讨论】:

    【解决方案2】:

    经过多方尝试终于得到答案

    当我通过应用 for 循环添加领域对象时 而不是我使用领域方法copyFromRealm(), 下面是一段代码

    listOfCategories.addAll(realm.copyFromRealm(categories));
    

    因此我认为没有必要应用提交和开始事务,因为我们只执行读取操作。

    【讨论】:

    • 接受您自己的答案,这样它可以帮助其他用户并使未回答的队列更加清晰。
    【解决方案3】:

    我在使用一些 RealmObjects 更新和循环数组时遇到了同样的问题。

    我在交易条件之前添加了这个

    if(realm.isInTransaction()){
        realm.commitTransaction();
    }
    

    希望这会有所帮助。

    【讨论】:

    • 感谢您的帮助我已将我的领域查询行放入您给定的条件 if(realm.isInTransaction()){ realm.beginTransaction(); RealmResults categories = realm.where(CategoriesDto.class).equalTo("parentId", categoriesDto.getCategoryId()).findAll(); for (int i = 0; i
    • 您的条件必须低于我的回答。错误是说您有一个开放的领域交易。我的条件关闭了该待处理的交易。然后你打开一个新的。
    • 问题是我试图通过将 realmObjects 添加到 listOfCategories 来设置从查询中获得的 realmList 到 myAdapter ,但是领域说,如果它在事务中和之后,则不能使用该引用通过使用您的条件也关闭该交易,我遇到了同样的错误。所以你必须使用“copyFromRealm”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-21
    • 1970-01-01
    • 1970-01-01
    • 2014-08-31
    • 2018-01-14
    • 1970-01-01
    相关资源
    最近更新 更多