【问题标题】:How to store objects in Android Room?如何在 Android Room 中存储对象?
【发布时间】:2017-11-27 22:18:08
【问题描述】:

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

假设我从服务器收到一个对象列表。他们每个人看起来像这样:

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

它们比这更复杂,所以我不能像 Room 建议的那样使用 @TypeConverters:

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

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

【问题讨论】:

  • 一般情况下,实体不会单独或以列表的形式在 Room 中保存其他实体。他们可能持有其他实体的外键。而其他结构,如视图模型,可以容纳任何需要的实体。所以,BigObject 需要去掉smallObjects 并用userId 替换user 作为外键。 UserSmallObject 会将外键返回到 BigObject。然后,设置一个视图模型或您从@Query DAO 方法填充的东西,该方法检索BigObject、其相关的User 及其相关的SmallObjects

标签: android android-room


【解决方案1】:

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

列表

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
}

请注意,我们已将 @Ignore 注释添加到 List&lt;SmallObject&gt;,因为我们希望在房间持久性期间忽略该字段(因为不支持列表)。它现在存在,因此当我们从数据库请求相关小对象列表时,我们仍然可以将它们存储在 POJO 中。

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

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

这似乎有一个简写形式,@Relation

类型转换器

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

嵌入式

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

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

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

- name 
- age 
- location_x
- location_y
- DOB

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

【讨论】:

【解决方案2】:

将 Object/List&lt;Object&gt; 转换为字符串,然后存储。

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

存储到房间

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

从房间读取

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

如何序列化/反序列化?

有很多选择。您可以手动完成,也可以为此使用库。你可以使用谷歌的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;

}

【讨论】:

  • 你从哪里序列化。
  • 来自 Java 对象。即对象----->字符串@GilbertS
  • 没有成功。我使用了@Relation。它允许您访问关联的列表
  • @Relation?这是什么意思?
  • 我认为docs 会更好地解释
猜你喜欢
  • 2018-05-28
  • 1970-01-01
  • 2013-01-08
  • 1970-01-01
  • 1970-01-01
  • 2019-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多