实体(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 报告中清晰展示。
实体定义元素关系图 User 类 @Entity(tableName="users") @PrimaryKey(autoGenerate=true) @ColumnInfo(name="user_id") 将 id 映射为 user_id 列 @Ignore tempAvatarUrl 不持久化 @Entity(indices = { @Index(value={"name","age"}), @Index(value={"email"}, unique) }) 说明:每个节点都是 @Entity 注解的组成部分,通过箭头体现配置层级关系。 Room 编译时校验所有配置的合法性,确保生成的表结构与实体定义一致。

常见错误与避坑

  • 自增主键不能是包装类型:Long/Integer 会导致运行时异常,必须用基本类型 long/int。
  • 忽略字段的构造函数:如果实体有多个构造函数,Room 要求一个构造函数不包含忽略的字段,以便创建对象时直接赋值。
  • 复合主键与 @NonNull:复合主键的任何字段都不能为 null,必须在实体中标注 @NonNull。
  • 索引命名冲突:不同实体不建议使用相同索引名,Room 不会自动加前缀,建议手动命名如 "idx_users_email"。
本章核心总结:掌握实体基础定义是构建 Room 数据层的基石。熟记 @Entity、@PrimaryKey、@ColumnInfo、@Ignore 以及 indices 的语法规则后,即可快速将任意 Java/Kotlin 数据类转换为数据库表。后续章节会在 DAO 和关系映射中反复使用这些定义,请务必亲手敲一遍示例代码并观察生成的 SQL 模式。