“我的会议室”数据库具有以下实体:
@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
对应于SQLite AUTOINCREMENT
。但是,the SQLite documentation清楚地表明,不需要AUTOINCREMENT
(并且在大多数情况下不建议)来自动生成唯一的主键。 AUTOINCREMENT
的目的基本上是为了防止重复使用已使用但已删除的主键。
AUTOINCREMENT关键字强加了额外的CPU,内存,磁盘空间和磁盘I / O开销,如果没有严格要求,应避免 。通常不需要。
在SQLite中,类型为INTEGER PRIMARY KEY的列是ROWID的别名(WITHOUT ROWID表中除外),该别名始终是64位带符号整数。
在INSERT上,如果未明确为ROWID或INTEGER PRIMARY KEY列提供值,则将自动用未使用的整数填充该整数,通常比当前使用的最大ROWID多一个整数。无论是否使用AUTOINCREMENT关键字,都是如此。
如果在INTEGER PRIMARY KEY之后出现AUTOINCREMENT关键字,则会更改自动ROWID分配算法,以防止在数据库的生命周期内重复使用ROWID。换句话说, AUTOINCREMENT的目的是防止重复使用先前删除的行中的ROWID 。
因此,似乎通常不需要或不建议使用@PrimaryKey(autogenerate=true)
。但是仅单独使用@PrimaryKey
根本不会自动生成值。
我如何告诉Room我想要的是'id' INTEGER NOT NULL PRIMARY KEY
?