如何在Android Room中存储对象?

时间:2017-06-24 12:55:03

标签: android android-room

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

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

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

将这两个对象作为字段:

@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;
}

它们比这更复杂,所以我无法使用@TypeConverters作为Room建议:

error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.

如何在室内存储此数据结构?

2 个答案:

答案 0 :(得分:30)

我认为回答此问题的最佳方法是存储结构的简要概述......

<强>解释

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

@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
}

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

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

BigObject b = db.BigObjectDao.findById(bOId);
List<SmallObject> s = db.smallObjectDao.findAllSOforBO(bOId);
b.setsmallObjects(s);

似乎有@Relation

形式的短手

类型转换器

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

<强>嵌入式

如果要在父POJO中获取所有嵌套POJO的字段并将其展平以存储在一个表中,则使用此选项。一个例子:

- name
- age
- location
    - x 
    - y
- DOB

..嵌入时,此结构将作为以下内容存储在数据库中:

- name 
- age 
- location_x
- location_y
- DOB

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

答案 1 :(得分:0)

将对象/ List<Object>转换为字符串,然后将其存储。

您可以将对象作为字符串存储在“房间库”中。为此,您可以序列化对象并将其存储为Room数据库中的String。

存储到房间

  

对象->序列化->字符串->存储

从会议室阅读

  
    

字符串->反序列化->对象->读取

  

如何序列化/反序列化?

有很多可用的选项。您可以手动执行此操作,也可以为此使用库。您可以使用Google的GSON library。它很容易使用。

  

代码:对象->字符串

public String stringFromObject(List<YourClass> list){

    Gson gson = new Gson();
    String jsonString = gson.toJson(list);
    return jsonString;

}
  

代码:字符串->对象

public List<YourClass> getObjectFromString(String jsonString){

    Type listType = new TypeToken<ArrayList<YourClass>>(){}.getType();
    List<YourClass> list = new Gson().fromJson(jsonString, listType);
    return list;

}