Android Room Kotlin事务双表更新:如何判定操作成败
在Android Room中判断双表更新操作的成败
要判断两张表是否更新成功,核心是利用Room更新语句的返回值(受影响行数),再结合@Transaction的原子性特性实现,具体步骤如下:
1. 利用Room更新语句的返回值判断单表更新状态
Room中带UPDATE的@Query方法会返回受影响的行数:
- 返回值>0:表示有匹配的行被成功更新
- 返回值=0:表示没有找到对应ID的行,更新操作未生效
2. 修改Dao层事务方法,返回整体更新结果
修改你的updateVariantValues方法,让它返回能体现双表更新状态的结果,同时保留@Transaction保证原子性(任一操作失败则整体回滚):
@Transaction suspend fun updateVariantValues(id: Int, is_Notify: Boolean, cart_count: String, product_id: Int): Boolean { // 判断Variants表是否更新成功 val variantUpdateCount = updateVariantTable(id, is_Notify, cart_count, product_id) // 判断CartList表是否更新成功 val cartUpdateCount = updateCartTable(id, cart_count) // 只有两张表都有行被更新,才返回成功 return variantUpdateCount > 0 && cartUpdateCount > 0 } // 原有的两个更新方法保持不变 @Query("UPDATE Variants SET cart_count= :cart_count, is_notify_me= :is_Notify,product_id= :product_id WHERE id = :id") fun updateVariantTable(id: Int, is_Notify:Boolean, cart_count: String?, product_id: Int) : Int @Query("UPDATE CartList SET qty= :qty WHERE id = :id") fun updateCartTable(id: Int, qty: String) : Int
如果需要更细致的状态区分(比如区分未找到行还是数据库异常),可以自定义密封类封装结果:
// 自定义更新结果密封类 sealed class UpdateResult { object Success : UpdateResult() // 两张表都更新成功 object NoRowsAffected : UpdateResult() // 无匹配行,未更新任何数据 data class Error(val e: Exception) : UpdateResult() // 数据库异常,事务回滚 } // 修改Dao层事务方法 @Transaction suspend fun updateVariantValues(id: Int, is_Notify: Boolean, cart_count: String, product_id: Int): UpdateResult { return try { val variantUpdated = updateVariantTable(id, is_Notify, cart_count, product_id) > 0 val cartUpdated = updateCartTable(id, cart_count) > 0 if (variantUpdated && cartUpdated) { UpdateResult.Success } else { UpdateResult.NoRowsAffected } } catch (e: Exception) { // 捕获数据库异常,返回错误结果 UpdateResult.Error(e) } }
3. 在ViewModel层处理更新结果并通知UI
在ViewModel中调用Dao方法,根据返回结果处理业务逻辑,并切换到主线程通知UI:
// 用LiveData传递结果给UI private val _updateResult = MutableLiveData<UpdateResult>() val updateResult: LiveData<UpdateResult> = _updateResult fun updateVariantTableinRoom(id:Int, cart_count:String, is_notify:Boolean, product_id:Int) = viewModelScope.launch(Dispatchers.IO) { val result = productsDao.updateVariantValues(id, is_notify, cart_count, product_id) // 切回主线程更新LiveData withContext(Dispatchers.Main) { _updateResult.value = result } }
在UI层(如Activity/Fragment)观察updateResult,根据不同结果做出反馈:
viewModel.updateResult.observe(this) { result -> when(result) { is UpdateResult.Success -> Toast.makeText(this, "更新成功", Toast.LENGTH_SHORT).show() is UpdateResult.NoRowsAffected -> Toast.makeText(this, "未找到对应数据,更新无效", Toast.LENGTH_SHORT).show() is UpdateResult.Error -> Toast.makeText(this, "更新失败:${result.e.message}", Toast.LENGTH_SHORT).show() } }
关键说明
@Transaction保证了两个更新操作的原子性:只要其中一个操作抛出异常(如数据库连接错误),整个事务会回滚,两张表都不会被修改。- 受影响行数为0的情况(如传入的ID不存在)不属于异常,需要单独判断,这种情况下事务不会回滚,但更新没有实际生效。
内容的提问来源于stack exchange,提问作者SasidharanIOS
相关产品推荐
相关产品推荐

