AndroidX房间数据库
AndroidX room database
我正在通过 androidX 库在 kotlin 中使用房间数据库。当我下载 Feed 并尝试保存在数据库中时,发生崩溃并显示错误 sqlite:NOTNULL constraint failed.Json Feed 在某些标签中有对象并且在某些标签中也有空数据。
但我没有在数据库中添加任何非空属性。在另一个项目中,我使用 java 中 arch 库中的房间数据库和相同的提要,它确实有效。
我用一些二级构造函数试过这样
constructor(0, "", "", "", "", listOf<SubMenuApi>, 0)
还有这个...
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)
我的数据库class
@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.onResponse(MenuViewModel.kt:53)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.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 中的空标记
我的代码有没有错误或androidX.room
中的错误
创建后是否更改了数据库方案? => 卸载应用程序并重建
您还应该设置 exportSchema = true
以便您实际看到生成的架构是什么样子。
由于您使用的是 kotlin,如果变量可以为 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)
在字符串初始化代码中添加 null 后工作正常..像这样
@ColumnInfo(name = "title") @SerializedName("Title") var title: String? = null
当我们用空值初始化变量时,room 数据库将 table 中的该列标记为 NOT NULL,因此当我们接收到数据为 null 时,它会出错。
所以当我们不知道这个值时,我们必须在 kotlin 数据中将变量初始化为 null class
我正在通过 androidX 库在 kotlin 中使用房间数据库。当我下载 Feed 并尝试保存在数据库中时,发生崩溃并显示错误 sqlite:NOTNULL constraint failed.Json Feed 在某些标签中有对象并且在某些标签中也有空数据。
但我没有在数据库中添加任何非空属性。在另一个项目中,我使用 java 中 arch 库中的房间数据库和相同的提要,它确实有效。
我用一些二级构造函数试过这样
constructor(0, "", "", "", "", listOf<SubMenuApi>, 0)
还有这个...
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)
我的数据库class
@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.onResponse(MenuViewModel.kt:53)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.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 中的空标记
我的代码有没有错误或androidX.room
中的错误创建后是否更改了数据库方案? => 卸载应用程序并重建
您还应该设置 exportSchema = true
以便您实际看到生成的架构是什么样子。
由于您使用的是 kotlin,如果变量可以为 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)
在字符串初始化代码中添加 null 后工作正常..像这样
@ColumnInfo(name = "title") @SerializedName("Title") var title: String? = null
当我们用空值初始化变量时,room 数据库将 table 中的该列标记为 NOT NULL,因此当我们接收到数据为 null 时,它会出错。
所以当我们不知道这个值时,我们必须在 kotlin 数据中将变量初始化为 null class