Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AndroidX room database

Iam using room database in kotlin via androidX library. When i download feed and try to save in database, crash occurs showing error sqlite:NOTNULL constraint failed.Json Feed has objects in some tags and also have null data in some tags.

But i did not add any not null properties in database. In another project iam using room database from arch library in java with same feed it actually works.

I tried like this with some seconday constructor

constructor(0, "", "", "", "", listOf<SubMenuApi>, 0)

and also this...

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import androidx.room.TypeConverters

@Entity(tableName = "tableMenu")
data class MenuApi(

        @PrimaryKey(autoGenerate = true) var id: Int = 0,
        @ColumnInfo(name = "title") @SerializedName("Title") var title: String = "",
        @ColumnInfo(name = "TITLE_OF_ACCESS") @SerializedName("TitleofAccess") var titleOfAccess: String = "",
        @ColumnInfo(name = "apexFileName") @SerializedName("AspxFileName") var apexFileName: String = "",
        @ColumnInfo(name = "sectionId") @SerializedName("SectionId") var sectionId: String = "",
        @TypeConverters(MenuConvertors::class) @SerializedName("SubMenu") var subMenuApi: List<SubMenuApi> = listOf<SubMenuApi>(),
        @ColumnInfo(name = "subSecCount") @SerializedName("subsec_count") var subSecCount: Int = 0)

my database class

@Database(entities = [(MenuApi::class),], version = 1, exportSchema = false)
@TypeConverters(MenuConvertors::class)
abstract class AppDatabase : RoomDatabase() {
    abstract fun dbDao(): DbDao
}

menu convertors

class MenuConvertors {

    private val gson = Gson()

    @TypeConverter
    fun stringToList(data: String?): List<SubMenuApi> {
        if (data == null) {
            return emptyList()
        }
        val listType = object : TypeToken<List<SubMenuApi>>() {}.type
        return gson.fromJson(data, listType)
    }

    @TypeConverter
    fun listToString(subMenuApiList: List<SubMenuApi>): String {
        return gson.toJson(subMenuApiList)
    }
}

submenu

data class SubMenuApi(

        @SerializedName("Title") var title: String? = "",
        @SerializedName("TitleofAccess") var titleOfAccess: String? = "",
        @SerializedName("AspxFileName") var apexFileName: String? = "",
        @SerializedName("SectionId") var sectionId: String? = "",
        @SerializedName("URL") var url: String? = "")

my error is

android.database.sqlite.SQLiteConstraintException: NOT NULL constraint failed: tableMenu.apexFileName (code 1299)
    #################################################################
    Error Code : 1299 (SQLITE_CONSTRAINT_NOTNULL)
    Caused By : Abort due to constraint violation.
        (NOT NULL constraint failed: tableMenu.apexFileName (code 1299))
    #################################################################
        at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
        at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:915)
        at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
        at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
        at androidx.sqlite.db.framework.FrameworkSQLiteStatement.executeInsert(FrameworkSQLiteStatement.java:51)
        at androidx.room.EntityInsertionAdapter.insert(EntityInsertionAdapter.java:97)
        at com.thanthi.dtnext.dtnextapplication.database.DbDao_Impl.insertMenuData(DbDao_Impl.java:432)
        at com.thanthi.dtnext.dtnextapplication.viewmodel.MenuViewModel$loadMenuData$1.onResponse(MenuViewModel.kt:53)
        at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:70)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:7325)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

null tag in apexFileName

is there any mistake in my code or bug in androidX.room

like image 247
Karthick Ramanathan Avatar asked Oct 29 '22 08:10

Karthick Ramanathan


2 Answers

Since you are using kotlin, the variables have to be mutable if they are can be null.

Add a ? after the variable types in your entity and that will fix it. Without ? you are basically guaranteeing that it won't be null.

@PrimaryKey(autoGenerate = true) var id: Int? = 0, @ColumnInfo(name = "title")
@SerializedName("Title") var title: String? = "", 
@ColumnInfo(name = "TITLE_OF_ACCESS") @SerializedName("TitleofAccess") var titleOfAccess: String? = "", 
@ColumnInfo(name = "apexFileName") @SerializedName("AspxFileName") var apexFileName: String? = "", 
@ColumnInfo(name = "sectionId") @SerializedName("SectionId") var sectionId: String? = "", 
@TypeConverters(MenuConvertors::class) @SerializedName("SubMenu") var subMenuApi: List<SubMenuApi>? = listOf<SubMenuApi>(), 
@ColumnInfo(name = "subSecCount") @SerializedName("subsec_count") var subSecCount: Int? = 0)
like image 72
Nick Mowen Avatar answered Nov 11 '22 13:11

Nick Mowen


After adding null in string initialization code works correctly.. like this

@ColumnInfo(name = "title") @SerializedName("Title") var title: String? = null

when we initialize variable with empty value, room database marks that column in table as NOT NULL, so when we receive data as null, it goes error.

so when we don't know about the value we have to initialize variable as null in kotlin data class

like image 33
Karthick Ramanathan Avatar answered Nov 11 '22 12:11

Karthick Ramanathan