Когда вы добавляете в Room только что созданный объект с автоматической генерацией первичного ключа, вновь созданный объект сохраняет свой неопределенный первичный ключ.Это оказывается неудобным, когда вам нужно изменить этот объект и сохранить изменения.
Давайте рассмотрим пример.
Entity Dao
Итак, давайте создадим 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
// …
}
У нас есть следующий Dao:
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");
Предлагаемое решение
Чтобы решить эту проблему, мы могли бы изменить 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?Видите ли вы какие-либо ловушки?