【发布时间】:2021-05-31 21:05:29
【问题描述】:
我在 Room 数据库中有下表:
@Entity(tableName = "goals")
class SavingsGoalWrapper(
@PrimaryKey val primaryKey: String = "primaryKey",
@SerializedName("savingsGoals")
val wrapper: List<SavingsGoal>
)
@Parcelize
data class SavingsGoal(
@SerializedName("goalImageURL")
val imageUrl: String,
val targetAmount: Float?,
val currentBalance: Float,
val name: String,
val id: Int
) : Parcelable
这是我从 db 获取数据的方式:
override fun getSavingsGoals(): Observable<SavingsGoalWrapper> =
Observable.create { subscriber ->
val goals = goalsDao.getGoals()
if (goals == null) {
subscriber.onError(NoDataException())
} else {
subscriber.onNext(goals)
}
}
这是我的道课:
@Dao
interface GoalsDao {
@Query("SELECT * FROM Goals") fun getGoals(): SavingsGoalWrapper?
}
当我运行应用程序时,我收到以下异常:
2021-06-01 01:28:36.051 25286-25286/com.sample.android.qapital E/BaseViewModel$sendRequest: android.database.sqlite.SQLiteConstraintException: NOT NULL constraint failed: goals.primaryKey (code 1299 SQLITE_CONSTRAINT_NOTNULL)
at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:938)
at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:790)
at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:88)
at androidx.sqlite.db.framework.FrameworkSQLiteStatement.executeInsert(FrameworkSQLiteStatement.java:51)
at androidx.room.EntityInsertionAdapter.insert(EntityInsertionAdapter.java:64)
at com.sample.android.qapital.data.source.local.GoalsDao_Impl$2.call(GoalsDao_Impl.java:60)
at com.sample.android.qapital.data.source.local.GoalsDao_Impl$2.call(GoalsDao_Impl.java:55)
at io.reactivex.internal.operators.completable.CompletableFromCallable.subscribeActual(CompletableFromCallable.java:36)
at io.reactivex.Completable.subscribe(Completable.java:2309)
at io.reactivex.internal.operators.mixed.CompletableAndThenObservable.subscribeActual(CompletableAndThenObservable.java:45)
at io.reactivex.Observable.subscribe(Observable.java:12267)
at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.subscribeInner(ObservableFlatMap.java:165)
at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.onNext(ObservableFlatMap.java:139)
at retrofit2.adapter.rxjava2.BodyObservable$BodyObserver.onNext(BodyObservable.java:51)
at retrofit2.adapter.rxjava2.BodyObservable$BodyObserver.onNext(BodyObservable.java:37)
at retrofit2.adapter.rxjava2.CallEnqueueObservable$CallCallback.onResponse(CallEnqueueObservable.java:60)
at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:129)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:206)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
正如你在上面看到的那样:NOT NULL constraint failed: goals.primaryKey (code 1299 SQLITE_CONSTRAINT_NOTNULL)
我该如何解决这个问题?
【问题讨论】:
-
您的问题在于insert 而不是查询。您的主键有一个默认值。主键必须是唯一的。
-
或者,服务器是否有可能为多个实例返回相同的 SavingsGoal.id?
-
我通过创建包装域类和数据库模型包装类解决了这个问题。在存储库中,我使用了两个名为 asDomainModel() 和 asDatabaseModel() 的扩展函数将 db 项转换为域,反之亦然。结果插入方法按您在评论中提到的预期工作。请分享您的答案,我标记为已接受。谢谢@MidasLefko。
标签: android sql android-room