美文网首页
(二)使用Room实体定义数据

(二)使用Room实体定义数据

作者: 鹿小纯0831 | 来源:发表于2018-10-30 16:12 被阅读12次

    使用Room持久性库时,可以将相关字段集定义为实体。 对于每个实体,在关联的Database对象中创建一个表来保存项目。
    默认情况下,Room会为实体中定义的每个字段创建一列。 如果实体具有您不想保留的字段,则可以使用@Ignore对其进行注释。 您必须通过Database类中的entities数组引用实体类。
    以下代码段显示了如何定义实体:

    @Entity
    public class User {
        @PrimaryKey
        public int id;
    
        public String firstName;
        public String lastName;
    
        @Ignore
        Bitmap picture;
    }
    

    为了持久一个参数,Room必须能够访问它。 您可以将字段设为公开,也可以为其提供getter和setter。 如果使用getter和setter方法,请记住它们基于Room中的JavaBeans约定。

    注意:实体可以有一个空构造函数(如果相应的DAO类可以访问每个持久化字段),或者一个构造函数,其参数包含与实体中字段匹配的类型和名称。 Room也可以使用完整或部分构造函数,例如只接收某些字段的构造函数。

    一、使用主键

    每个实体必须至少定义一个字段作为主键。 即使只有一个字段,您仍然需要使用@PrimaryKey注释来注释该字段。 此外,如果您希望Room为实体分配自动ID,您可以设置@PrimaryKey的autoGenerate属性。 如果实体具有复合主键,则可以使用@Entity批注的primaryKeys属性,如以下代码段所示:

    @Entity(primaryKeys = {"firstName", "lastName"})
    public class User {
        public String firstName;
        public String lastName;
    
        @Ignore
        Bitmap picture;
    }
    

    默认情况下,Room使用类名作为数据库表名。 如果希望表具有不同的名称,请设置@Entity批注的tableName属性,如以下代码段所示:

    @Entity(tableName = "users")
    public class User {
        ...
    }
    

    警告:SQLite中的表名称不区分大小写。

    与tableName属性类似,Room使用字段名称作为数据库中的列名称。 如果希望列具有不同的名称,请将@ColumnInfo注释添加到字段中,如以下代码段所示:

    @Entity(tableName = "users")
    public class User {
        @PrimaryKey
        public int id;
    
        @ColumnInfo(name = "first_name")
        public String firstName;
    
        @ColumnInfo(name = "last_name")
        public String lastName;
    
        @Ignore
        Bitmap picture;
    }
    

    二、注释索引和唯一性

    根据您访问数据的方式,您可能希望索引数据库中的某些字段以加快查询速度。 要向实体添加索引,请在@Entity批注中包含indices属性,列出要包含在索引或复合索引中的列的名称。 以下代码段演示了此批注过程:

    @Entity(indices = {@Index("name"),
            @Index(value = {"last_name", "address"})})
    public class User {
        @PrimaryKey
        public int id;
    
        public String firstName;
        public String address;
    
        @ColumnInfo(name = "last_name")
        public String lastName;
    
        @Ignore
        Bitmap picture;
    }
    

    有时,数据库中的某些字段或字段组必须是唯一的。 您可以通过将@Index批注的unique属性设置为true来强制实施此唯一性属性。 以下代码示例可防止表具有两行,这些行包含firstName和lastName列的相同值集:

    @Entity(indices = {@Index(value = {"first_name", "last_name"},
            unique = true)})
    public class User {
        @PrimaryKey
        public int id;
    
        @ColumnInfo(name = "first_name")
        public String firstName;
    
        @ColumnInfo(name = "last_name")
        public String lastName;
    
        @Ignore
        Bitmap picture;
    }
    

    三、定义对象之间的关系

    由于SQLite是关系数据库,因此您可以指定对象之间的关系。 尽管大多数对象关系映射库允许实体对象相互引用,但Room明确禁止这样做。 要了解此决策背后的技术推理,请参阅了解Room不允许对象引用的原因。
    即使您不能使用直接关系,Room仍允许您在实体之间定义外键约束。
    例如,如果有另一个名为Book的实体,您可以使用@ForeignKey批注定义其与User实体的关系,如以下代码段所示:

    @Entity(foreignKeys = @ForeignKey(entity = User.class,
                                      parentColumns = "id",
                                      childColumns = "user_id"))
    public class Book {
        @PrimaryKey
        public int bookId;
    
        public String title;
    
        @ColumnInfo(name = "user_id")
        public int userId;
    }
    

    外键非常强大,因为它们允许您指定更新引用实体时发生的情况。 例如,如果通过在@ForeignKey批注中包含onDelete = CASCADE来删除相应的User实例,则可以告诉SQLite删除用户的所有书籍。

    注意:SQLite将@Insert(onConflict = REPLACE)作为一组REMOVE和REPLACE操作处理,而不是单个UPDATE操作。 这种替换冲突值的方法可能会影响您的外键约束。

    四、创建嵌套对象

    有时,您希望将实体或普通旧Java对象(POJO)表达为数据库逻辑中的一个整体,即使该对象包含多个字段。 在这些情况下,您可以使用@Embedded批注来表示要分解到表中子字段的对象。 然后,您可以像查找其他单个列一样查询嵌入字段。

    例如,我们的User类可以包含Address类型的字段,它表示名为street,city,state和postCode的字段的组合。 要将组合列分别存储在表中,请在User类中包含使用@Embedded注释的Address字段,如以下代码段所示:

    public class Address {
        public String street;
        public String state;
        public String city;
    
        @ColumnInfo(name = "post_code")
        public int postCode;
    }
    
    @Entity
    public class User {
        @PrimaryKey
        public int id;
    
        public String firstName;
    
        @Embedded
        public Address address;
    }
    

    然后,表示User对象的表包含具有以下名称的列:id,firstName,street,state,city和post_code。

    注意:嵌入字段还可以包含其他嵌入字段。

    如果实体具有多个相同类型的嵌入字段,则可以通过设置prefix属性使每个列保持唯一。 然后,Room将提供的值添加到嵌入对象中每个列名称的开头。

    相关文章

      网友评论

          本文标题:(二)使用Room实体定义数据

          本文链接:https://www.haomeiwen.com/subject/mxvgtqtx.html