首页 > 解决方案 > 自动更新新插入的房间实体中的主键

问题描述

当您在 Room 中添加新创建的对象时,主键会自动生成,新创建的对象会保持未定义的主键。当您需要修改此对象并保留更改时,这会带来不便。

让我们举个例子。

实体道

所以,让我们创建一个自动生成的对象Userid

@Entity()
public class User {
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id")
    private int id;

    @ColumnInfo(name = "email")
    private String email;

    public User(String email) {
        this.email = email;
    }

    // Other methods, especially getter and setter for each field

    // …
}

我们有以下道:

public class UserDao {
    @Insert
    void insert(User user);

    @Update
    int update(User user);

    // …
}

我们通过以下存储库进行交互:

public class Repository {
    private UserDao userDao;

    public void addUser(User user) {
        userDao.insert(user);
    }

    public void update(User user) {
        userDao.update(user);
    }

    // …
}

插入和更新实体

所以,现在如果我们这样做,user将不会被更新,因为User.id将保持在 0 并且Update注释仅在主键已经存在时才更新行

Repository r = new Repository();
User user = new User("me@my.email");
r.addUser(user);
user.setEmail("new@user.email");

建议的解决方案

为了解决这个问题,我们可以改变插入后更新 id 的addUser方法。这个问题给了我以下想法:Repository

public class Repository {
    private UserDao userDao;

    public void addUser(User user) {
        long rowid = userDao.insert(user);
        user.setId(userDao.getIdFromRowid(rowid));
    }

    // …
}

使用这个 Dao(注意insert返回 along而不是void):

public class UserDao {
    @Insert
    long insert(User user);

    @Update
    int update(User user);

    @Query("SELECT id FROM user WHERE ROWID = :rowid")
    int getIdFromRowid(long rowid);

    // …
}

这会是 Android Jetpack 范例中可接受的解决方案吗?你看到什么陷阱了吗?

标签: javaandroidandroid-roomandroid-jetpack

解决方案


您提出的解决方案是可以接受的,您可以从 Room DB 获取插入的 id,然后将其设置回您的对象引用。所以你可以执行更新和删除操作。另一个认为您可以探索和使用的是 LiveData on Select 查询,它会在 Room DB 中发生更改时为您提供回调中的更新数据。但是,这取决于您的逻辑。例子 :

@Query("SELECT * from test_tbl")
 LiveData<List<Model>> getTestData();  

推荐阅读