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