【问题标题】:Is there any way to make Room generate an autogenerating primary key without AUTOINCREMENT?有没有办法让 Room 在没有 AUTOINCREMENT 的情况下生成自动生成的主键?
【发布时间】:2019-03-03 20:48:00
【问题描述】:

我的房间数据库有以下实体:

@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 不同,尽管我在 the SQLite documentation 中找不到任何有关此行为的文档。

看来我必须使用 @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对应SQLiteAUTOINCREMENT。但是,the SQLite documentation 非常清楚地表明不需要(并且在大多数情况下不推荐)AUTOINCREMENT 来自动生成唯一的主键。 AUTOINCREMENT 的目的基本上是为了防止重复使用已使用但已删除的主键。

AUTOINCREMENT 关键字会带来额外的 CPU、内存、磁盘空间和磁盘 I/O 开销,如果不是严格需要,应该避免。通常不需要。

在 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

【问题讨论】:

    标签: android sqlite android-sqlite android-room


    【解决方案1】:

    目前不可能 - 唯一的选择是 AUTOINCREMENT。您可以在existing feature request 上加注星标以获取有关此用例支持的最新进展。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      • 2010-09-24
      • 2019-12-18
      相关资源
      最近更新 更多