AndroidX房间数据库

4
我正在使用AndroidX库中的Kotlin Room数据库。当我下载信息源并尝试保存到数据库时,会发生崩溃,显示错误sqlite:NOTNULL约束失败。Json Feed在某些标签中有对象,并且在某些标签中也有空数据。
但是我没有在数据库中添加任何非空属性。在另一个Java项目中,我使用了来自arch库的Room数据库并使用相同的信息源,它实际上可以正常工作。
我尝试过像这样使用一些辅助构造函数。
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)

我的数据库类

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

菜单转换器
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)
    }
}

子菜单
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? = "")

我的错误是:
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)

在 apexFileName 中出现了 null 标签

我的代码有错误还是 androidX.room 存在 bug?

3个回答

1
在字符串初始化中添加null后,代码可以正常工作.. 就像这样。
@ColumnInfo(name = "title") @SerializedName("Title") var title: String? = null

当我们用空值初始化变量时,Room数据库会将表中的该列标记为NOT NULL,因此当我们接收到null数据时,就会出错。
因此,当我们不知道变量的值时,必须在Kotlin数据类中将其初始化为null。

1

由于您正在使用Kotlin,如果变量可以为null,则必须是可变的。

在实体中的变量类型后面添加?即可解决此问题。如果没有?,则基本上保证它不会为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)

当我尝试这个时,出现了java.lang.IllegalArgumentException错误:参数被指定为非空但却为空:方法kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull,参数subMenuApiList。 位于com.thanthi.dtnext.dtnextapplication.database.MenuConvertors.listToString(MenuConvertors.kt)。 - Karthick Ramanathan

0

创建后更改了数据库结构吗? => 卸载应用并重新构建

此外,您应该设置exportSchema = true,这样您才能看到生成的模式实际上是什么样子。


以下是有关编程的内容,请将其翻译成中文。然后,请发布模式。 - Tobias

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接