Когда вы добавляете только что созданный объект в Room, с автоматической генерацией первичный ключ, вновь созданный объект сохраняет свой неопределенный первичный ключ. Этот оказывается неудобным, когда вам нужно изменить этот объект и сохранить изменения.
Возьмем пример.
Итак, давайте создадим User, id которого генерируется автоматически.
@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("[email protected]");
r.addUser(user);
user.setEmail("[email protected]");
Чтобы решить эту проблему, мы могли бы изменить метод addUser для Repository для обновления идентификатора после вставки.
Этот вопрос натолкнул меня на следующую мысль:
public class Repository {
private UserDao userDao;
public void addUser(User user) {
long rowid = userDao.insert(user);
user.setId(userDao.getIdFromRowid(rowid));
}
// …
}
С этим Дао (обратите внимание, что insert возвращает long вместо 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? Ты видите какой-нибудь подвох?




Предлагаемое вами решение приемлемо, вы можете получить вставленный идентификатор из БД комнаты, а затем снова установить ссылку на свой объект. Таким образом, вы можете выполнять операции обновления и удаления. Другая мысль, которую вы могли бы исследовать и использовать, - это запрос LiveData on Select, который будет обновлять данные в обратном вызове всякий раз, когда они будут изменяться в БД комнаты. Но это зависит от вашей логики. Пример :
@Query("SELECT * from test_tbl")
LiveData<List<Model>> getTestData();