android Room @Insert(onConflict = OnConflictStrategy.REPLACE)会重新生成 id 吗? 什么情况下会重新生成 id?

wanlion 26天前 12

1 User 类
只有 3 个字段:id, username, password
其中 id 是主键, 并且是自增长

2 dao 类
使用 @Insert 注解如下:
@Insert(onConflict = OnConflictStrategy.REPLACE)
public long saveUser(User user);

3 调用
不管是新增还是修改, 其他地方都是调用该方法:
dao.saveUser(user);

4 问题
然后, 发现一个有趣的现象, 有时候引用 user 时会失效, 查看数据库时发现, 指定 id 的数据已经不存在。

5 为什么会这样?
来自 stackoverflow 的解释:
@Insert(onConflict = OnConflictStrategy.REPLACE) 注解, 如果指定 id 的对象没有保存在数据库中, 就会新增一条数据到数据库。如果指定 id 的对象数据已经保存到数据库中, 就会删除掉原来的数据, 然后新增一条数据。

这样就解释了为什么引用 user 会失效。
原话如下:
A method, annotated with @Insert can return a long. This is the newly generated ID for the inserted row. A method, annotated with @Update can return an int. This is the number of updated rows.
update will try to update all your fields using the value of the primary key in a where clause. If your entity is not persisted in the database yet, the update query will not be able to find a row and will not update anything.
You can use @Insert(onConflict = OnConflictStrategy.REPLACE). This will try to insert the entity and, if there is an existing row that has the same ID value, it will delete it and replace it with the entity you are trying to insert. Be aware that, if you are using auto generated IDs, this means that the the resulting row will have a different ID than the original that was replaced. If you want to preserve the ID, then you have to come up with a custom way to do it.

来源:
https://stackoverflow.com/questions/48519896/room-update-or-insert-if-not-exist-rows-and-return-count-changed-rows

6 疑惑:
但是, 事情总是有但是, 经过测试发现, 修改了 username 或者 password, id 并没有改变。

这是怎么回事? id 的改变有条件呢? 还是版本不同才引起测试结果不同?
哪位 v 友能否解释下?

技术: android Room

最新回复 (2)
  • Cabana 20天前
    引用 2
    传进方法 saveUser 中的 user id 字段有没有值,是是否触发 onConflict 的先决条件。

    另外 insert 和 update 不要混用
  • 楼主 wanlion 20天前
    引用 3
    @Cabana 修改时有值, 而且修改成功!
  • 游客
    4
返回