Android Room:如何在不使用 "autoGenerate = true" 的情况下自动生成主 ID(避免 SQLite 关键字 AUTOINCREMENT)?
Android Room: How to auto generate primary id, without using "autoGenerate = true" (To avoid SQLite keyword AUTOINCREMENT)?
背景
最近,我了解到不鼓励在 SQLite 中使用 AUTOINCREMENT
。
https://www.sqlite.org/autoinc.html
关键字AUTOINCREMENT
实际上是令人困惑的。 as,真正的意思是自动生成id的算法方法。
即使我们不使用关键字 AUTOINCREMENT
,并且在插入时不提供 id
,id 仍然会自动生成。
例如,
DROP TABLE cities;
CREATE TABLE cities (
id INTEGER NOT NULL PRIMARY KEY,
name TEXT NOT NULL
);
INSERT INTO cities (name)
VALUES( 'San Jose');
INSERT INTO cities (name)
VALUES( 'New York');
即使没有AUTOINCREMENT
关键字
也会生成下面的table
id name
========
1 San Jose
2 New York
我想在 Android 房间
中实现相同的行为
而不是使用以下(将应用 SQLite AUTOINCREMENT
)
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
private long id;
我在我的实体中使用class
@PrimaryKey
@ColumnInfo(name = "id")
private long id;
但是,我注意到我需要显式地为id
分配一个非零正值,只有插入才会成功。
如果id
的值为0或-1,则插入不会成功
我希望我们不需要手动分配 id,即使不使用 Room autoGenerate = true
。
但是,这似乎没有按预期工作。我可以知道为什么会这样吗?
您不需要在 Android 房间中达到同样的效果。在 SQLite 中,类型为 INTEGER PRIMARY KEY
的列是 ROWID 的别名,除非您指定 WITHOUT ROWID
.
因此,除非另有说明,否则您的 id
将收到一个未使用的整数。
不推荐 AUTOINCREMENT
关键字的原因是,除非它是 PRIMARY KEY
,否则不太可能需要接受 CPU、内存使用、磁盘方面的成本space 和 I/O 开销。但是,使用 PRIMARY KEY
实际上是个好主意。请注意,您共享的页面从未声称您不应该使用 PRIMARY KEY
,它只是不鼓励使用 AUTOINCREMENT
关键字。
I expect we need not to assign id manually, even without using Room autoGenerate = true.
不需要使用autogenerate = true,并且具有相同的生成值。你可以使用(另一种方式稍后展示):-
@PrimaryKey
@ColumnInfo(name = "id")
private Long id; /* or private Long = null; */
注意使用 Long 对象而不是 long 原语。然后将 id 设置为 null 以生成要生成的值或具有合适的构造函数。
Room 看到空值,在 PRIMARY KEY 和 a non-primitive 整数类型的情况下,并从生成的 SQL 中省略该列。 =18=]
作为基于您的架构的示例,请考虑:-
@Entity
class Cities {
@PrimaryKey
private Long id;
private String name;
@Ignore
public Cities(String name) {
this.name = name;
}
@Ignore
public Cities(Long id, String name) {
this.id = id;
this.name = name;
}
public Cities(){}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
使用方便的@Insert 例如:-
@Dao
interface CitiesDao {
@Insert
long insert(Cities city);
}
或者,您可以使用 @Query 来使用适合的 INSERT SQL。例如以下将插入一行,仅给出名称和生成的 ID。 :-
@Query("INSERT INTO cities (name) VALUES(:name)")
long insert(String name);
- 重要的因素是包括没有 id 列的特定列。
使用上述(2 种方法)的示例:-
citiesdao.insert(new Cities("San Jose"));
citiesdao.insert(new Cities("New York"));
citiesdao.insert(new Cities(100L,"San Francisco"));
citiesdao.insert(new Cities("Nevada"));
citiesdao.insert("Dallas");
- 您可能不想使用带有特定 ID 的第三个插入(或者可以使用
onConflict = IGNORE
)。
以上结果(通过 App Inspection):-
背景
最近,我了解到不鼓励在 SQLite 中使用 AUTOINCREMENT
。
https://www.sqlite.org/autoinc.html
关键字AUTOINCREMENT
实际上是令人困惑的。 as,真正的意思是自动生成id的算法方法。
即使我们不使用关键字 AUTOINCREMENT
,并且在插入时不提供 id
,id 仍然会自动生成。
例如,
DROP TABLE cities;
CREATE TABLE cities (
id INTEGER NOT NULL PRIMARY KEY,
name TEXT NOT NULL
);
INSERT INTO cities (name)
VALUES( 'San Jose');
INSERT INTO cities (name)
VALUES( 'New York');
即使没有AUTOINCREMENT
关键字
id name
========
1 San Jose
2 New York
我想在 Android 房间
中实现相同的行为而不是使用以下(将应用 SQLite AUTOINCREMENT
)
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
private long id;
我在我的实体中使用class
@PrimaryKey
@ColumnInfo(name = "id")
private long id;
但是,我注意到我需要显式地为id
分配一个非零正值,只有插入才会成功。
如果id
的值为0或-1,则插入不会成功
我希望我们不需要手动分配 id,即使不使用 Room autoGenerate = true
。
但是,这似乎没有按预期工作。我可以知道为什么会这样吗?
您不需要在 Android 房间中达到同样的效果。在 SQLite 中,类型为 INTEGER PRIMARY KEY
的列是 ROWID 的别名,除非您指定 WITHOUT ROWID
.
因此,除非另有说明,否则您的 id
将收到一个未使用的整数。
不推荐 AUTOINCREMENT
关键字的原因是,除非它是 PRIMARY KEY
,否则不太可能需要接受 CPU、内存使用、磁盘方面的成本space 和 I/O 开销。但是,使用 PRIMARY KEY
实际上是个好主意。请注意,您共享的页面从未声称您不应该使用 PRIMARY KEY
,它只是不鼓励使用 AUTOINCREMENT
关键字。
I expect we need not to assign id manually, even without using Room autoGenerate = true.
不需要使用autogenerate = true,并且具有相同的生成值。你可以使用(另一种方式稍后展示):-
@PrimaryKey
@ColumnInfo(name = "id")
private Long id; /* or private Long = null; */
注意使用 Long 对象而不是 long 原语。然后将 id 设置为 null 以生成要生成的值或具有合适的构造函数。
Room 看到空值,在 PRIMARY KEY 和 a non-primitive 整数类型的情况下,并从生成的 SQL 中省略该列。 =18=]
作为基于您的架构的示例,请考虑:-
@Entity
class Cities {
@PrimaryKey
private Long id;
private String name;
@Ignore
public Cities(String name) {
this.name = name;
}
@Ignore
public Cities(Long id, String name) {
this.id = id;
this.name = name;
}
public Cities(){}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
使用方便的@Insert 例如:-
@Dao
interface CitiesDao {
@Insert
long insert(Cities city);
}
或者,您可以使用 @Query 来使用适合的 INSERT SQL。例如以下将插入一行,仅给出名称和生成的 ID。 :-
@Query("INSERT INTO cities (name) VALUES(:name)")
long insert(String name);
- 重要的因素是包括没有 id 列的特定列。
使用上述(2 种方法)的示例:-
citiesdao.insert(new Cities("San Jose"));
citiesdao.insert(new Cities("New York"));
citiesdao.insert(new Cities(100L,"San Francisco"));
citiesdao.insert(new Cities("Nevada"));
citiesdao.insert("Dallas");
- 您可能不想使用带有特定 ID 的第三个插入(或者可以使用
onConflict = IGNORE
)。
以上结果(通过 App Inspection):-