如何在Android Room中存储对象?

ild*_*lin 13 android android-room

基本上,有两件事我不理解:带有对象的对象和带有对象列表的对象

假设我从服务器收到一个对象列表.他们每个人都是这样的:

@Entity
public class BigObject {
    @PrimaryKey
    private int id;
    private User user;
    private List<SmallObject> smallObjects;
}
Run Code Online (Sandbox Code Playgroud)

将这两个对象作为字段:

@Entity
public class User {
    @PrimaryKey
    private int id;
    private String name;
    @TypeConverters(GenderConverter.class)
    public MyEnums.Gender gender;
}

@Entity
public class SmallObject {
    @PrimaryKey (autoGenerate = true)
    private int id;
    private String smallValue;
}
Run Code Online (Sandbox Code Playgroud)

它们比这更复杂,所以我不能使用@TypeConverters,因为Room建议:

error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.
Run Code Online (Sandbox Code Playgroud)

如何在Room中存储此数据结构?

Jac*_*ton 30

我认为回答这个问题的最佳方法是在存储结构时进行简要介绍......

清单

Room不支持存储嵌套在POJO中的列表.存储列表的推荐方法是使用外键方法.将对象列表存储在单独的表(在本例中为smallObjects表)中,并使用外键到其相关的父对象(在本例中为"big_object_id").应该看起来像这样......

@Entity
public class BigObject {
    @PrimaryKey
    private int id;
    private User user;
    @Ignore
    private List<SmallObject> smallObjects;
}

@Entity(foreignKeys = {
            @ForeignKey(
                entity = BigObject.class,
                parentColumns = "id",
                childColumns = "big_object_fk"
            )})
public class SmallObject {
    @PrimaryKey (autoGenerate = true)
    private int id;
    private String smallValue;
    @ColumnInfo(name = "big_object_fk")
    private int bigObjectIdFk
}
Run Code Online (Sandbox Code Playgroud)

请注意,我们已经添加了@Ignore注释,List<SmallObject>因为我们希望在Room persistance期间忽略该字段(因为不支持列表).它现在存在,以便当我们从DB请求我们的相关小对象列表时,我们仍然可以将它们存储在POJO中.

据我所知,这意味着你要进行两次查询.

BigObject b = db.BigObjectDao.findById(bOId);
List<SmallObject> s = db.smallObjectDao.findAllSOforBO(bOId);
b.setsmallObjects(s);
Run Code Online (Sandbox Code Playgroud)

似乎有一个简短的手以@Relation的形式

类型转换器

这些用于您具有复杂数据结构的情况,该数据结构可以在不丢失信息的情况下展平,并存储在单个列中.一个很好的例子是Date对象.Date对象很复杂并且包含很多值,因此将它存储在数据库中是很棘手的.我们使用类型转换器来提取日期对象的milli表示并存储它.然后我们将millis转换为日期对象,从而保持数据的完整性.

嵌入式

当您想要在父POJO中获取所有嵌套POJO的字段并将它们展平以存储在一个表中时,可以使用此选项.一个例子 :

- name
- age
- location
    - x 
    - y
- DOB
Run Code Online (Sandbox Code Playgroud)

..当嵌入此结构时,将存储在数据库中:

- name 
- age 
- location_x
- location_y
- DOB
Run Code Online (Sandbox Code Playgroud)

从某种意义上说,Embedded可以节省您为包含String,int,float等主要类型字段的每个嵌套对象创建类型转换器的时间.

  • 嵌入式文档:https://developer.android.com/reference/android/arch/persistence/room/Embedded.html (2认同)