实体(Entity)基础定义
Room 中的 Entity 用于描述一张数据库表的映射结构。每个标注 @Entity 的类对应一张表,类的成员变量对应表的列。本章逐一拆解 @Entity 注解的核心属性:表名、主键、字段列名、忽略字段以及索引声明,并通过完整的代码示例串联所有知识点。
@Entity 注解与表名
使用 @Entity 标记一个类为数据库实体。默认情况下表名与类名相同,可以通过 tableName 显式指定,从而隔离 Java 命名与 SQL 命名规范。例如类名 User 可映射为表 users。
| 属性 | 作用 | 示例 |
|---|---|---|
tableName | 自定义表名(建议使用蛇形命名) | @Entity(tableName = "users") |
primaryKeys | 声明复合主键(多个字段组合) | @Entity(primaryKeys = {"firstName", "lastName"}) |
indices | 定义索引/唯一约束 | @Entity(indices = {@Index(...)}) |
ignoredColumns | 忽略继承字段(较少用) | — |
主键定义
使用 @PrimaryKey 标注在字段上。支持以下三种场景:
- 单一自增主键:
@PrimaryKey(autoGenerate = true) - 单一手动主键:
@PrimaryKey(无 autoGenerate) - 复合主键:在
@Entity中通过primaryKeys属性指定
注意:复合主键的字段必须都标注
@NonNull,否则 Room 会在编译时报错。
字段列名映射
默认情况下,Room 按照字段名生成 SQL 列名,camelCase 转为 snake_case。如需精确控制列名,使用 @ColumnInfo(name = "...") 注解。常见场景:
- 数据库已使用不同命名风格,如
user_name - 字段名包含 SQL 关键字,需要转义
- 缩短列名以优化存储
实践建议:始终显式指定
@ColumnInfo 的 name,避免未来重构字段名时导致数据库版本不兼容。
忽略字段
用 @Ignore 标注不需要持久化的字段。这些字段用于临时计算、UI 状态或对象引用,不会被写入数据库表。被忽略的字段可以被 transient 修饰,但 Room 推荐明确使用 @Ignore 提高可读性。
索引声明
在 @Entity 的 indices 属性中声明索引,可提升查询性能。索引支持以下选项:
| 属性 | 说明 | 示例 |
|---|---|---|
value | 索引包含的列名数组 | value = {"lastName", "firstName"} |
unique | 是否为唯一索引(默认 false) | unique = true |
name | 索引名称(可选,自动生成) | name = "idx_name_age" |
要点梳理:索引不是越多越好,写入密集型业务应控制索引数量;唯一索引可以替代
UNIQUE 约束,推荐用于邮箱、身份证等业务唯一字段。
完整实体示例:User
下面展示一个综合实体定义,覆盖表名、自增主键、列名映射、忽略字段和索引声明:
@Entity(
tableName = "users",
indices = {
@Index(value = {"name", "age"}, unique = false),
@Index(value = {"email"}, unique = true)
}
)
public class User {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "user_id")
private long id;
@ColumnInfo(name = "name")
private String name;
@ColumnInfo(name = "age")
private int age;
@ColumnInfo(name = "email")
private String email;
@ColumnInfo(name = "address")
private String address;
@Ignore
private String tempAvatarUrl; // 临时头像 URL,不持久化
// 构造函数、getter/setter 省略…
}
编译时验证:Room 在编译时检查
@Entity 配置是否合法。例如,复合主键的字段不能为 null;自增主键只能是 long 或 int;索引列必须在实体中定义。错误会在 RoomSchemaExporter 报告中清晰展示。
常见错误与避坑
- 自增主键不能是包装类型:
Long/Integer会导致运行时异常,必须用基本类型long/int。 - 忽略字段的构造函数:如果实体有多个构造函数,Room 要求一个构造函数不包含忽略的字段,以便创建对象时直接赋值。
- 复合主键与 @NonNull:复合主键的任何字段都不能为
null,必须在实体中标注@NonNull。 - 索引命名冲突:不同实体不建议使用相同索引名,Room 不会自动加前缀,建议手动命名如
"idx_users_email"。
本章核心总结:掌握实体基础定义是构建 Room 数据层的基石。熟记
@Entity、@PrimaryKey、@ColumnInfo、@Ignore 以及 indices 的语法规则后,即可快速将任意 Java/Kotlin 数据类转换为数据库表。后续章节会在 DAO 和关系映射中反复使用这些定义,请务必亲手敲一遍示例代码并观察生成的 SQL 模式。