Android Room实体自动生成主键后获取更新ID的问题
解决Room实体插入后无法获取正确自动生成主键ID的问题
你的问题核心在于:你创建的Alarm对象初始id是0,Room在插入数据库时会自动生成主键,但不会主动把这个生成的ID同步回你原来的对象,所以后续调用setAlarm相关方法时,拿到的还是初始的0值。下面是具体的解决步骤:
1. 修正Dao的插入方法,让它返回生成的主键ID
首先确保你的AlarmDao接口中,插入方法返回Long类型(Room自动生成的主键默认是long型,和你实体里的Int类型兼容):
@Dao interface AlarmDao { // 插入后返回自动生成的主键ID @Insert suspend fun insertAlarm(alarm: Alarm): Long }
2. 插入后将返回的ID赋值回你的Alarm对象
当你调用Dao的插入方法时,把返回的ID赋值给你创建的Alarm实例,这样后续调用方法时就能拿到正确的ID了:
// 示例:在Repository或ViewModel中执行插入(注意要在协程中调用挂起函数) viewModelScope.launch { val yourAlarm = Alarm( alarmHour = 7, alarmMin = 30, isAM = true, days = arrayListOf(Calendar.MONDAY, Calendar.TUESDAY), isOn = true, label = "上班闹钟" // 这里不需要传id,用默认的0即可 ) // 执行插入并获取生成的ID val insertedId = alarmDao.insertAlarm(yourAlarm) // 将ID赋值回对象 yourAlarm.id = insertedId.toInt() // 现在调用setAlarmSchOnOff就能拿到正确的ID了 yourAlarm.setAlarmSchOnOff(true, requireActivity()) }
3. 额外修正代码中的笔误
你在setAlarmScheduleOff方法里有个错误:
Log.d("ALARM OFF", Integer.toString(alarmId))
这里的alarmId是未定义的变量,应该改成id,否则会编译报错:
Log.d("ALARM OFF", Integer.toString(id))
为什么会出现这个问题?
Room的@PrimaryKey(autoGenerate = true)注解只是告诉数据库在插入时自动生成主键,但不会自动修改你传入的实体对象的id字段。你创建对象时id的默认值是0,这个值只是本地对象的初始状态,只有当你把Dao返回的生成ID赋值回去后,对象的id才会和数据库中的记录对应。
如果是更新操作,@Update方法会根据实体的id来匹配数据库中的记录,所以更新前要确保对象的id已经是数据库中存在的正确值,@Update方法会返回更新的行数,你可以通过这个行数判断更新是否成功。
内容的提问来源于stack exchange,提问作者Andrea Liureta
相关产品推荐
相关产品推荐

