Автоматическое обновление первичного ключа во вновь вставленном номере объекта - PullRequest
1 голос
/ 06 июля 2019

Когда вы добавляете в 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?Видите ли вы какие-либо ловушки?

1 Ответ

1 голос
/ 11 июля 2019

Ваше Предложенное решение является приемлемым, вы можете получить вставленный идентификатор из БД комнаты, а затем вернуть ссылку на свой объект.Таким образом, вы можете выполнять операции обновления и удаления.Другой вариант, который вы могли бы использовать и исследовать, - это LiveData on Select, который даст вам возможность обновлять данные в обратном вызове всякий раз, когда они будут изменены в Room DB.Но это зависит от вашей логики.Пример:

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