#android #kotlin #android-room
Вопрос:
Я пытался обновить данные базы данных номеров и получил эту ошибку. Нужно ли мне иметь уникальный идентификатор при попытке обновить элемент? Я попытался найти решение, как устранить эту ошибку, но в основном оно вращается вокруг операции ВСТАВКИ ( операция вставки работает) или решения на другом языке программирования.
Ошибка:
android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: Plant.plant_id (code 1555 SQLITE_CONSTRAINT_PRIMARYKEY)
at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:796)
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:64)
at com.example.plantmanagement.dao.PlantOperations_Impl.insertPlant(PlantOperations_Impl.java:136)
at com.example.plantmanagement.repository.PlantRepository.insertPlant(PlantRepository.kt:17)
at com.example.plantmanagement.viewmodel.PlantViewModel$insertPlant$1.invokeSuspend(PlantViewModel.kt:25)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:342)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:27)
at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:109)
at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:158)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
at kotlinx.coroutines.BuildersKt.launch(Unknown Source:1)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:49)
at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source:1)
at com.example.plantmanagement.viewmodel.PlantViewModel.insertPlant(PlantViewModel.kt:24)
at com.example.plantmanagement.activity.Edit_Plant$onCreate$2.onClick(Edit_Plant.kt:98)
at android.view.View.performClick(View.java:6597)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:992)
at android.view.View.performClickInternal(View.java:6574)
at android.view.View.access$3100(View.java:778)
at android.view.View$PerformClick.run(View.java:25885)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Класс сущностей:
Entity(tableName = "Plant")
data class Plant(
@PrimaryKey(autoGenerate = true) var plant_id:Long,
@ColumnInfo (name="plant_name") var name: String,
//@Embedded var type: Plant_Category,
@ColumnInfo(name= "plant_image", typeAffinity = ColumnInfo.BLOB) var image: ByteArray,
@ColumnInfo(name="plant_type_name") var type:String ="",
@ColumnInfo(name="plant_type_water")var water_time: String ="",
@ColumnInfo(name="plant_type_details")var details: String = "",
)
Класс Dao:
@Dao
interface PlantOperations {
@Query("SELECT * FROM Plant")
fun getAll(): Flow<List<Plant>>
@Insert
fun insertAll(vararg plant: Plant?)
@Insert
fun insertPlant(plant: Plant)
@Query("DELETE FROM Plant WHERE plant_id = :id")
fun delete(id: Long)
@Update(onConflict = OnConflictStrategy.REPLACE)
fun updatePlant(plant: Plant)}
Я также убедился, что не вставляю другой идентификатор.
Я был бы благодарен за помощь.
Ответ №1:
Вы не обновляете запись, а пытаетесь вставить новую запись с тем же значением для первичного ключа. это видно в трассировке стека
at com.example.plantmanagement.repository.PlantRepository.insertPlant(PlantRepository.kt:17)
поэтому, чтобы обновить запись, вам нужно вызвать updatePlant
метод.
Также я не вижу никакой пользы onConflict = OnConflictStrategy.REPLACE
в случае update
, если вы, вероятно, захотите использовать это с вашим insert
методом. поэтому обновите свои insert
методы и update
методы, как
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertPlant(plant: Plant)
@Update
fun updatePlant(plant: Plant)
Комментарии:
1. Но я постараюсь на всякий случай.
2. Похоже, я случайно использовал метод вставки, а не метод обновления. Который я, хотя и использовал метод обновления, но, возможно, случайно отменил код и не увидел код, возвращающийся из метода обновления для вставки . Спасибо, что нашли время указать на это.