有没有一种方法可以使Room生成一个自动生成的主键,而不使用AUTOINCREMENT?

4

我的 Room 数据库有以下实体:

@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 文档 明确指出,为了自动生成唯一的主键,不需要(在大多数情况下也不建议)使用 AUTOINCREMENTAUTOINCREMENT 的目的基本上是防止重复使用已删除的主键。

“AUTOINCREMENT”关键字会增加额外的CPU、内存、磁盘空间和磁盘I/O开销,如果不是必需的话应该避免使用。通常情况下是不需要的。
在SQLite中,类型为INTEGER PRIMARY KEY的列是ROWID的别名(除了WITHOUT ROWID表之外),它始终是一个64位有符号整数。
在INSERT操作中,如果ROWID或INTEGER PRIMARY KEY列没有显式地赋值,则会自动填充一个未使用的整数,通常是当前已使用的最大ROWID加1。无论是否使用AUTOINCREMENT关键字,这都是正确的。
如果AUTOINCREMENT关键字出现在INTEGER PRIMARY KEY之后,那么它将更改自动ROWID分配算法,以防止在数据库的生命周期内重用ROWID。换句话说,“AUTOINCREMENT”的目的是防止从先前删除的行中重新使用ROWID。
因此,似乎通常不需要也不建议使用“@PrimaryKey(autogenerate=true)”。但只使用“@PrimaryKey”是不会自动生成值的。
我如何告诉Room我想要的是“'id' INTEGER NOT NULL PRIMARY KEY”?
1个回答

4

目前这是不可能的 - 唯一的选项是 AUTOINCREMENT。您可以为现有功能请求加星以获取有关此用例支持的更新。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接