Автоматическое обновление первичного ключа во вновь вставленном объекте комнаты

Когда вы добавляете только что созданный объект в 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? Ты видите какой-нибудь подвох?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
0
894
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

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

Другие вопросы по теме