Невозможно обновить с помощью @PrimaryKey (autoGenerate = true) - PullRequest
0 голосов
/ 30 ноября 2018

Я работаю с Room и обнаружил проблему с установкой первичного ключа для автоматического создания,

@ PrimaryKey (autoGenerate = true)

Если я сделаю INSERTи затем выполните операцию UPDATE, сгенерированные ключи для этих операций различаются, и поэтому мои данные не обновляются.

@Entity(tableName = "test_table")
public class TestEntity {

    @PrimaryKey(autoGenerate = true)
    private int uid;

    @ColumnInfo(name = "expiration_date_access_token")
    private String expirationDateAccessToken;


    /**
     * Getter for retrieving primary key
     *
     * @return Primary key
     */
    public int getUid() {
        return uid;
    }

    /**
     * Setter for setting primary key
     *
     * @param uid Primary key
     */
    public void setUid(int uid) {
        this.uid = uid;
    }

    /**
     * Getter for retrieving expiration date of access token
     *
     * @return Expiration date of access token
     */
    public String getExpirationDateAccessToken() {
        return expirationDateAccessToken;
    }

    /**
     * Setter for setting expiration date of access token
     *
     * @param expirationDateAccessToken Expiration date of access token
     */
    public void setExpirationDateAccessToken(String expirationDateAccessToken) {
        this.expirationDateAccessToken = expirationDateAccessToken;
    }
}

Вот пример DAO

@Dao
public interface TestDao {

    @Query("SELECT * FROM test_table")
    List<TestEntity> getAll();

    @Query("DELETE FROM test_table")
    void deleteAll();

    @Insert
    void insert(TestEntity testEntity);

    @Delete
    void delete(TestEntity testEntity);

    @Update
    void update(TestEntity testEntity);
}

Вот моя база данных приложений

@Database(entities = {TestEntity.class}, version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {

    private static final String DATABASE_NAME = "room.test.db";
    private static AppDatabase APP_DATABASE_INSTANCE;

    public abstract TestDao testDao();

    public static AppDatabase getAppdatabase(@NonNull Context context) {
        if (FrameworkUtils.checkIfNull(APP_DATABASE_INSTANCE)) {
            APP_DATABASE_INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                    AppDatabase.class, DATABASE_NAME).build();
        }
        return APP_DATABASE_INSTANCE;
    }

    /**
     * Method is used to destroy database instance
     */
    public static void destroy() {
        APP_DATABASE_INSTANCE = null;
    }
}

Я подключил свои LiveData к своему хранилищу, однако, по упрощенным причинам ниже также выполняет ту же операцию.

Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                // update database tables
               TestEntity testEntity = new TestEntity();
               // if I uncomment setting uid, which is the hardcoded primary key
               // value, the update will happen. If I do not include this, and 
               // just try to update my data, a new primary key is generated and
               // the old data does not get updated.

               // testEntity.setUid(1); 
               testEntity.setExpirationDateAccessToken("12345");
               AppDatabase.getAppdatabase(context).testDao().update(testEntity);

            }
        });

У меня вопрос, что такоешаблон для использования @PrimaryKey (autoGenerate = true) ??Я могу заставить все работать идеально, выполнив следующее жесткое кодирование первичного ключа, но я не думаю, что это требуется.

EDIT

    @PrimaryKey(autoGenerate = true)
    private int uid = 1; <---- works with any hardcoded int value

Ответы [ 2 ]

0 голосов
/ 30 ноября 2018

Вы создаете TestEntity, а затем говорите Room, чтобы сохранить его в базе данных.В этот момент Room назначает ему автоматически сгенерированный первичный ключ.Если затем вы хотите обновить этот конкретный TestEntity, вам нужно передать экземпляр класса TestEntity с тем же идентификатором, который использует база данных (идентификатор автоматически генерируется при первом сохранении объекта вбазы данных, а не когда вы ее создаете).

Следовательно, вы должны знать идентификатор сущности, которую хотите обновить.Как определить, какой идентификатор присвоен ему при первом сохранении?Вместо этого вы можете заставить свой метод @Insert возвращать Long, который будет идентификатором.

@Insert
Long insert(TestEntity testEntity);

Итак, с этим небольшим изменением вы теперь можете узнать, какой идентификатор базы данных назначен недавно сохраненному объекту.Затем вы можете установить этот Long для экземпляра Entity в java, изменить какой-либо другой параметр и вызвать update, и он будет работать, потому что на этот раз они будут иметь одинаковый идентификатор

0 голосов
/ 30 ноября 2018

Мой вопрос такой: каков шаблон использования @PrimaryKey (autoGenerate = true) ??

  • его простое целое число начинается с 0, а затем увеличивается на 1 при получении строкидобавлено.

Должен ли я всегда получать идентификатор, а затем с каждым обновлением передавать его?

  • да.@Update - из документов

Реализация метода обновит свои параметры в базе данных, если они уже существуют (проверено первичными ключами).Если они еще не существуют, эта опция не изменит базу данных.

Должен быть лучший способ.Любые предложения?

  • Это зависит от ваших требований.если я не ошибаюсь, я думаю, что вы пытаетесь сохранить только одну строку в таблице все время.

@ Query ("UPDATE test_table where 1 = 1")

защищенное абстрактное обновление int (TestEntity te);

Альтернативный способ.Но здесь вам нужно установить uid некоторое жестко запрограммированное целое число.Так как вы не храните несколько, вам не нужно ограничение первичного ключа, любая вышеуказанная логика будет работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...