Clément Joly
Clément Joly

Reputation: 983

Automatically updating primary key in newly inserted Room Entity

When you add a freshly created object in Room, with auto generation of the primary key, the newly created object keeps it’s undefined primary key. This proves inconvenient when you need to modify this object and persist the changes.

Let’s take an example.

Entity Dao

So, let’s create a User whose id is auto-generated.

@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

    // …
}

We have the following Dao:

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

    @Update
    int update(User user);

    // …
}

We interract through the following Repository:

public class Repository {
    private UserDao userDao;

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

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

    // …
}

Inserting and updating an Entity

So, now if we do this, user will not be updated, because User.id will stay at 0 and Update annotation updates the row only if the primary key already exists.

Repository r = new Repository();
User user = new User("[email protected]");
r.addUser(user);
user.setEmail("[email protected]");

Proposed solution

To tackle this issue, we could change the addUser method of the Repository to update id after insertion. This question gave me the following idea:

public class Repository {
    private UserDao userDao;

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

    // …
}

With this Dao (note that insert returns a long instead of 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);

    // …
}

Would this be an acceptable solution in the Android Jetpack paradigm? Do you see any pitfall?

Upvotes: 3

Views: 1153

Answers (1)

Bills
Bills

Reputation: 798

Your Proposed solution is acceptable, you can get the inserted id from the Room DB then set to your object reference back. So you could perform update and delete operations. The other think you could explorer and use is LiveData on Select query, which will give you update data in callback whenever it will be change in Room DB. But, it depends upon you logic. Example :

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

Upvotes: 1

Related Questions