Есть ли способ заставить Room сгенерировать первичный ключ с автоматическим генерированием без AUTOINCREMENT? - PullRequest
0 голосов
/ 28 сентября 2018

База данных «Моя комната» имеет следующую сущность:

@Entity
public class SmsMessage {
    @PrimaryKey
    public long id;

    public boolean incoming;
    public String sender;
    public String receiver;
    public String body;
    public long timestamp;
}

Это происходит со следующим RuntimeException при попытке вставить более одного элемента в базу данных:

SQLiteConstraintException: PRIMARY KEY must be unique (code 19)

сгенерированный оператор SQL CREATE TABLE выглядит следующим образом:

CREATE TABLE `SmsMessage` (
    `id`    INTEGER NOT NULL,
    `incoming`  INTEGER NOT NULL,
    `sender`    TEXT,
    `receiver`  TEXT,
    `body`  TEXT,
    `timestamp` INTEGER NOT NULL,
    PRIMARY KEY(`id`)
);

Кажется, это отличается от INTEGER NOT NULL PRIMARY KEY, хотя я не могу найти никакой документации по этому поведению в документации SQLite .

Кажется, мне нужно использовать @PrimaryKey (autogenerate=true), чтобы Room автоматически генерировал значения первичного ключа.Глядя на сгенерированную базу данных при использовании autogenerate=true, генерируется следующий SQL:

CREATE TABLE `SmsMessage` (
    `id`    INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    `incoming`  INTEGER NOT NULL,
    `sender`    TEXT,
    `receiver`  TEXT,
    `body`  TEXT,
    `timestamp` INTEGER NOT NULL
);

Кажется, что autogenerate=true соответствует SQLite AUTOINCREMENT.Тем не менее, документация SQLite совершенно ясно показывает, что AUTOINCREMENT не требуется (и в большинстве случаев не рекомендуется) для автоматической генерации уникальных первичных ключей.Цель AUTOINCREMENT в основном состоит в том, чтобы предотвратить повторное использование использованных, но удаленных первичных ключей.

Ключевое слово AUTOINCREMENT накладывает дополнительные ресурсы ЦП, памяти, дискового пространства и дискового ввода-вывода и следует избегать, если в этом нет особой необходимости .Обычно это не требуется.

В SQLite столбец с типом INTEGER PRIMARY KEY является псевдонимом для ROWID (кроме таблиц WITHOUT ROWID), который всегда представляет собой 64-разрядное целое число со знаком.

На INSERT, если столбцу ROWID или INTEGER PRIMARY KEY явно не дано значение, он будет автоматически заполнен неиспользованным целым числом, обычно на единицу больше, чем самый большой ROWID, используемый в настоящее время.Это верно вне зависимости от того, используется или нет ключевое слово AUTOINCREMENT.

Если ключевое слово AUTOINCREMENT появляется после INTEGER PRIMARY KEY, это изменяет алгоритм автоматического назначения ROWID, чтобы предотвратить повторное использование ROWID в течение срока жизни базы данных.Другими словами, целью AUTOINCREMENT является предотвращение повторного использования ROWID из ранее удаленных строк .

Таким образом, кажется, что использование @PrimaryKey(autogenerate=true) обычно не требуется и не рекомендуется.Но только использование @PrimaryKey не будет автоматически генерировать значения вообще.

Как мне сказать Room, что я хочу 'id' INTEGER NOT NULL PRIMARY KEY?

1 Ответ

0 голосов
/ 28 сентября 2018

На данный момент это невозможно - единственная опция - AUTOINCREMENT.Вы можете пометить запрос существующей функции для получения обновлений о поддержке для этого варианта использования.

...