V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wanlion
V2EX  ›  Android

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

  •  
  •   wanlion · 2021-04-12 19:49:00 +08:00 · 8094 次点击
    这是一个创建于 1305 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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 条回复    2021-04-12 23:29:51 +08:00
    Cabana
        1
    Cabana  
       2021-04-12 19:58:09 +08:00 via iPhone
    传进方法 saveUser 中的 user id 字段有没有值,是是否触发 onConflict 的先决条件。

    另外 insert 和 update 不要混用
    wanlion
        2
    wanlion  
    OP
       2021-04-12 23:29:51 +08:00
    @Cabana 修改时有值, 而且修改成功!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5341 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 07:39 · PVG 15:39 · LAX 23:39 · JFK 02:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.