【问题标题】:Persisting objects with Realm (error: Changing Realm data can only be done from inside a transaction)使用 Realm 持久化对象(错误:更改 Realm 数据只能在事务内部完成)
【发布时间】:2016-09-23 02:42:56
【问题描述】:

我无法让 Realm 正常工作。

RealmConfiguration realmConfig = new RealmConfiguration.Builder(this).build();
Realm.setDefaultConfiguration(realmConfig);
Realm realm = Realm.getDefaultInstance();

MyObjectExtendingRealmObject myObject = new MyObjectExtendingRealmObject("John");
realm.beginTransaction();
realm.copyToRealm(myObject);
realm.commitTransaction();

错误:java.lang.IllegalStateException:更改领域数据只能在事务内部完成

说我疯了,但我不是在事务中进行数据持久化,这正是在文档中所做的吗?在此处查看使用copyToRealm 的示例:https://realm.io/docs/java/latest/#creating-objects

我做错了什么?

编辑:什么,Realm 不支持自动递增主键 ID?对我来说是破坏者。我会留下这个问题,以防它帮助其他人。

编辑:我的班级

public class MyObjectExtendingRealmObject extends RealmObject {
    private String name;

    public MyObjectExtendingRealmObject() {

    }

    public MyObjectExtendingRealmObject(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

【问题讨论】:

  • 自动递增 id 不是 Realm 开箱即用的功能,但 it's not something you cannot implement by hand in 5 minutes 也是
  • 顺便说一句,我的猜测是你的 MyObjectExtendingRealmObject 没有默认的空构造函数,即使它应该
  • @EpicPandaForce 它确实有一个默认的空构造函数

标签: java android database transactions realm


【解决方案1】:

我可以看到这有两个可能的原因:

1.) 您实际上是在多个地方调用 Realm.getDefaultInstance(),因此修补了一个实际上并未设置为事务的 Realm 实例

2.) 你的领域对象上没有默认的空构造函数


这是一些规范的用法示例:

  • UI 线程:

.

Realm realm;

@Override
public void onCreate(Bundle bundle) {
    super.onCreate(bundle);
    realm = Realm.getDefaultInstance();
    realm.executeTransactionAsync(new Realm.Transaction() {
        public void execute(Realm realm) {
            MyObjectExtendingRealmObject myObject = new MyObjectExtendingRealmObject("John");
            realm.insertOrUpdate(myObject); // could be copyToRealmOrUpdate
        }
    });
}

@Override
public void onDestroy() {
    super.onDestroy();
    if(realm != null) { // don't trust old devices
        realm.close();
    }
}
  • 后台线程:

.

Realm realm = null;
try {
   realm = Realm.getDefaultInstance();
   realm.executeTransaction(new Realm.Transaction() {
       @Override
       public void execute(Realm realm) {
            MyObjectExtendingRealmObject myObject = new MyObjectExtendingRealmObject("John");
            realm.insertOrUpdate(myObject); // could be copyToRealmOrUpdate
       }
   });
} finally {
    if(realm != null) {
        realm.close();
    }
}

领域模型:

public class MyObjectExtendingRealmObject extends RealmObject {
   public MyObjectExtendingRealmObject() { // needed
   }

   public MyObjectExtendingRealmObject(String name) {
       this.name = name;
   }

   @PrimaryKey
   private String name;

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }
}

【讨论】:

  • 1.我只在整个应用程序中调用Realm.getDefaultInstance() 一次(现在它只是 MainActivity 我创建一个对象并尝试持久化它)。 2. 我的班级确实有一个默认/空的构造函数。我会把它添加到 OP 中。
  • 在这种情况下,我会很好奇您的确切堆栈跟踪,以及哪一行引发了异常。 Realm 版本 1.2.0,对吧?
  • 这很尴尬。它现在正在工作,我不知道为什么。我也不认为我改变了什么。反正答案是好的,所以我会接受。
  • 在这种情况下,禁用即时运行。它以奇怪的方式修补事物。
  • 这可能就是原因。现在禁用它。在 RealmConfiguration 初始化之后在应用程序的 onCreate() 方法中调用 Realm.getDefaultInstance() 是否是一个糟糕的主意,将其设置为应用程序的全局,之后再也不调用 realm.close() 以避免问题#1你有表态吗?所以现在如果我们想要默认实例,我们调用 MyApp.getRealm() 或其他东西。
【解决方案2】:

我有一个名为 RealmHelper 的助手类,上面是它的方法之一。

 public static void saveObject(RealmObject objectToSave) {

    Realm realm = getRealm();
    realm.beginTransaction();
    realm.copyToRealmOrUpdate(objectToSave);
    realm.commitTransaction();
}

因此,我的代码结构是这样的,任何领域方法或对象都不应该在活动或片段中。

为了克服这个错误,每次我创建具有相同 id 的新对象时,领域都可以覆盖旧对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多