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
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)
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With