【问题标题】:Realm is already in a write transaction if I execute two transactions in the same method如果我以相同的方法执行两个事务,则领域已经处于写入事务中
【发布时间】:2019-02-06 07:46:11
【问题描述】:

如果它们超过一定数量,我需要消除领域数据库记录的第一条记录,但我得到了这个异常:

Caused by: java.lang.IllegalStateException: The Realm is already in a write transaction in /Users/cm/Realm/realm-java/realm/realm-library/src/main/cpp/io_realm_internal_OsSharedRealm.cpp line 126
    at io.realm.internal.OsSharedRealm.nativeBeginTransaction(Native Method)
    at io.realm.internal.OsSharedRealm.beginTransaction(OsSharedRealm.java:269)
    at io.realm.BaseRealm.beginTransaction(BaseRealm.java:404)
    at io.realm.Realm.beginTransaction(Realm.java:145)
    at io.realm.Realm.executeTransaction(Realm.java:1491)
    atsavedAddresses(AddressBook.kt:39)````

正如您在下面看到的,我尝试添加commitTransaction,与executeTransactionAsyncexecuteTransaction 一起玩,开始交易等。但是尽管我阅读了几篇这样的帖子并且GitHub 发布了cmets,但没有任何效果,我甚至发现这个post 但太抽象了,无法与我的案例相关

init {

    Realm.init(ProActiveApplication.applicationContext())
}


private val realm = Realm.getDefaultInstance()

val query = realm.where(RecentAddress::class.java).findAll()

fun savedAddresses(name: String, address: String) {
   realm.beginTransaction()
    realm.executeTransactionAsync  {
        val addressToSave = realm.createObject(RecentAddress::class.java)
        addressToSave.name = name
        addressToSave.street = address
        Log.d("ME","-----------------")
        Log.d("ME", " CreateTransaction: ${addressToSave.name} in ${addressToSave.street}")
        Log.d("ME","-----------------")
    }
    realm.commitTransaction()
    realm.close()

    realm.beginTransaction()
    realm.executeTransaction {
        if (query.size > 2) {
            val location = query.get(0)
            Log.d("ME","-----------------")

            Log.d("ME", " This is cancelled: ${query.get(0)}")
            Log.d("ME","-----------------")

            location?.deleteFromRealm()

        } }

编辑

按照建议,我将删除 beginTransaction()commitTransaction,我也改为 executeTransaction 而不是 `executeTransactionAsync()

    fun savedAddresses(name: String, address: String) {
   // realm.beginTransaction()
    realm.executeTransaction {
        val addressToSave = realm.createObject(RecentAddress::class.java)
        addressToSave.name = name
        addressToSave.street = address
        Log.d("ME", "-----------------")
        Log.d("ME", " CreateTransaction: ${addressToSave.name} in ${addressToSave.street}")
        Log.d("ME", "-----------------")
    }
   // realm.commitTransaction()
    realm.close()

    // realm.beginTransaction()
    realm.executeTransaction {
        if (query.size > 2) {
            val location = query.get(0)
            Log.d("ME", "-----------------")

            Log.d("ME", " This is cancelled: ${query.get(0)}")
            Log.d("ME", "-----------------")

            location?.deleteFromRealm()

        }

    }

现在我明白了,就像 Realm 将取消第一个 0 位置,但随后将在 0 位置添加下一条记录而不是列表的末尾

如果我取消第二个块executeTransaction,记录按顺序添加成功,但保留第二个块,事务消除第0行,然后在位置0插入第二条记录,而不是在列表的末尾

【问题讨论】:

    标签: android database kotlin concurrency realm


    【解决方案1】:

    如果您使用executeTransaction,则无需手动编写beginTransaction()commitTransaction(),一切都会为您完成。 所以基本上你 beginTransaction() 然后启动 executeTransaction 块然后你在事务中得到事务,这就是崩溃的原因,你也可以在一个事务中完成所有这些代码。

    【讨论】:

    • 按照您的建议不起作用,因为如果我删除您所说的话。 Realm 将取消数组 0,但随后将在数组零位置插入下一条记录,而不是在 Realm 列表的末尾,这就是为什么我拼命尝试在不同的事务中对它们进行沙箱处理
    • 你的意思是Realm要取消Array 0?
    • 请@Pavel Poley 看看我的编辑。上面我的意思是就像在那之后Realm取消了RealmObject的第0行,然后在这个零位置插入下一条记录,而不是在我期望的n顺序位置(在列表的末尾)
    【解决方案2】:

    如果我正确理解您的问题,您希望消除/删除前两条记录(如果有)并在列表末尾插入新记录。 试试这个

    fun savedAddresses(name: String, address: String) {
       realm.executeTransaction { realm ->
            val addressToSave = realm.createObject(RecentAddress::class.java)
            addressToSave.name = name
            addressToSave.street = address
            //insert the record at the end of the list 
            realm.insert(addressToSave)
        }
        deleteOldRecords()
    }
    
    fun deleteOldRecords() {
        realm.executeTransaction { realm -> 
            val recentAddressList = realm.where(RecentAddress::class.java).findAll()
            if(recentAddressList.size > 2){
                for(i in 0..1) {
                    recentAddressList.deleteFromRealm(i)
                }
            }
        }
    }
    

    如果我理解错了请纠正我。

    【讨论】:

    • 不完全是,我想要一个连续的项目列表,因为我只向用户显示最后 n 个项目,为了不让应用程序数据库太大我想在一个某个时间(在示例 2 中,实际上是 10 个)最旧的记录
    • 现在我在recentAddressList.deleteFromRealm(i) 行得到aused by: java.lang.IllegalStateException: Changing Realm data can only be done from inside a transaction.
    • 我认为这应该可行,我刚刚尝试过。告诉我
    • 我只需要删除一条记录,但这并不重要,问题是一旦被删除,事务就会在 [0] 第一个位置创建,而不是在末尾​​span >
    • 解决了问题是我想将记录保存为最后,这并不容易,所以我在适配器中恢复了列表,现在运行良好
    猜你喜欢
    • 1970-01-01
    • 2018-04-29
    • 2015-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-25
    • 2020-07-17
    相关资源
    最近更新 更多