Search code examples
androidkotlinrealm

How can I cancel ongoing realm write transaction before performing a new one?


I am developing an android app in Kotlin that stores and update student data. Each student has a unique ID and is stored as a primary key in the database. I was using SQLite at first but it was taking too much time to read the database when there is a lot of data. So am now trying to use Realm, I heard it's faster. The problem is, when I enter a primary key that is already in use it shows an error. I know it's supposed to happen. But then when I enter another key it says Cannot begin the write transaction: RealmCoreException([5]: The Realm is already in a write transaction). When I try again, the data is saved. But I want to cancel the transaction the exact moment the database encounters an error.

Below is the function to add the students

    fun addStudent(mID: String, mName: String, mSex: Char) {
        realm.writeBlocking {
            this.copyToRealm(Student().apply {
                _id = mID
                name = mName
                sex = mSex
            })
        }
    }

Below is my onClickListener for the SAVE button

        saveStudent.setOnClickListener {
            val id = studentID.text.toString()
            val name = studentName.text.toString().uppercase()
            val sex: Char = studentSex!!

            if (TextUtils.isEmpty(id)){
                studentID.error = "ID cannot be empty"
                studentID.requestFocus()
            }else if (TextUtils.isEmpty(name)){
                studentName.error = "Enter student name"
                studentName.requestFocus()
            }else if (TextUtils.isEmpty(sex.toString())){
                Toast.makeText(context,"Please indicate whether male or female",Toast.LENGTH_SHORT).show()
            }else {
                kotlin.runCatching {
                    dbHelper.addStudent(id, name, sex)
                }.onSuccess{
                    Toast.makeText(context,"$name was added!", Toast.LENGTH_SHORT).show()
                    Log.v("realm","$name was added!")
                    studentID.setText("")
                    studentName.setText("")
                    studentName.requestFocus()
                    getStudents()
                }.onFailure {e ->
                    Toast.makeText(context, "Unable to add student. Please make sure the STUDENT ID is not in use and try again.", Toast.LENGTH_SHORT).show()
                    Log.e("realm", e.message.toString())
                }
            }
        }

I tried realm.close() then Realm.open(config) in the catch block hoping it will solve the problem but to no avail. The error still pop up


Solution

  • I solved it by using try/catch block inside the realm.writeBlocking as shown below

    fun addStudent(mID: String, mName: String, mSex: Char): Boolean {
        var success = false
        realm.writeBlocking {
            try {
                this.copyToRealm(Student().apply {
                    _id = mID
                    name = mName
                    sex = mSex
                })
                Log.v("realm","$mName was added!")
                success = true
            }catch (e: IllegalArgumentException){
                Log.e("realm", e.message.toString())
                success = false
            }
        }
        return success
    }
    

    And the onclickListener for the SAVE button as follows:

                if (dbHelper.addStudent(id, name, sex)){
                    Toast.makeText(context,"$name was added!", Toast.LENGTH_SHORT).show()
                    studentID.setText("")
                    studentName.setText("")
                    studentName.requestFocus()
                    getStudents()
                }else {
                    Toast.makeText(context, "The STUDENT ID you have entered is already in use."
                        , Toast.LENGTH_SHORT)
                        .show()
                }
    

    Thanks.