【问题标题】:How to deal with Relational Data in nested 1-to-1 objects in Room (Convert ForeignKey to Object)如何处理Room中嵌套的1对1对象中的关系数据(将ForeignKey转换为对象)
【发布时间】:2018-08-22 00:32:39
【问题描述】:

假设我有一个Order 和一个User Entity,类似于这样:

User.java:

@Entity
public class User {
    @PrimaryKey    
    public long id;
    @NonNull    
    public String username;
}

Order.java:

@Entity(foreignKeys = @ForeignKey(entity = User.class,
                                  parentColumns = "id",
                                  childColumns = "user_id",
                                  onDelete = ForeignKey.CASCADE,
                                  onUpdate = ForeignKey.CASCADE),
        indices = @Index("user_id"))
public class Order {
    @PrimaryKey
    public long id;
    public String description;

    @ColumnInfo(name = "user_id")
    public long userId;
    @Ignore
    private User user;
}

这样,我有一个Order,里面有一个User,在数据库中我只将这个与用户ID的关系保存为Foreign Key,而不是对象本身(它是@Ignored ),所以一切都很好并且是相关的,并且可以扩展为以几种不同的方式和查询等与其他类型一起使用。

现在的问题是,我如何获得一个 Order 对象,其中的 User 对象自动由 Room 填充?

如果我使用@Embedded,那么OrderUser 将位于同一张表上,这不利于类型的关系分离。我可以将它们与JOIN 一起返回,但这仍然只适用于具有不同名称的数据类型(也许它们都有一个名为“description”的列?),此外,插入一个Order 和一个User 在里面使用JOIN 并不简单。 @Relation 仅适用于一对多,它需要 List,这不是我的情况。

我认为@TypeConverter 可能是这里的最佳选择,在longUser 之间进行转换,但这也很棘手。 @TypeConverter 需要对DAO 的引用,以便它可以查询User,而@TypeConverter 是由Room 调用的静态方法,因此传递DAO 可能会很棘手并导致许多代码异味,除了每个User 的额外查询将触发多个搜索,这些搜索不会在同一个@Transaction 中。

我是 Room 的新手,但我敢打赌有一个合适的方法来解决这个问题,将 Room 与原本打算使用的关系类型一起使用,我只是不知道如何让这项工作简单而完美,也不我可以在任何文档中找到它。

【问题讨论】:

  • 恕我直言,使用 @Embedded 是进行 1:1 映射的最简单方法。很多时候 Room 数据库只是充当服务器响应的快照,很少在上面做业务逻辑,这是服务器的职责,那么为什么我们需要这种关系分离呢?
  • 因为有时相同的数据会在不同的服务器响应中,所以如果我们为每个响应创建一个表,我们会浪费存储空间,例如Order可能有一个User里面它,但Shopping Cart 里面也可能有User。所以我们会在两张不同的桌子上拥有相同的User?如果User 更改了他的名字并且我们在应用程序的购物车页面上获得了更新,但随后用户下线了怎么办?我们将在“订单”页面中以旧名称显示用户。如果我们尝试手动同步,如果没有关系分离,他会不会一团糟
  • 这是有道理的!
  • 我现在看到的唯一选择是使用@embedded 并将查询中的对象分开,以便它们从单独的表中更新、插入和选择,至少我认为这样我们可以依靠关系隔离并在数据 chenfes 时从 Room 获取自动更新(虽然不确定这个有复杂的查询)

标签: android android-room android-architecture-components android-jetpack


【解决方案1】:

现在的问题是,我如何获得一个 Order,其中包含 Room 自动填充的 User 对象?

我认为没有现成的解决方案。

恕我直言,实体模型(即 Order 映射 FK 与 User.id不应像域/表示层一样传播到上层,提供 DataMapper 将实体模型转换为上层的域模型(即User 包含Order)可能是更好的选择。

【讨论】:

  • 这是不正确的,你必须传播 FK,否则你怎么能再次将该实体保存回数据库中,如果你碰巧它的任何值?如果删除 FK,则删除与数据库的链接
  • 我不明白propagate the FK的意思。
  • 你是说要从数据库返回的对象中删除FK对吧?
  • 不,我的意思是保持你当前的建模,并使用@Relation为查询结果创建另一个pojo,然后将这个pojo转换为你想要的上层。
  • 当使用 Room 返回 DataSource.Factory 时,这会变得更加复杂。您将不得不自己转换值,而不是使用框架提供的值....更多麻烦,因为没有太多回报恕我直言
猜你喜欢
  • 1970-01-01
  • 2020-07-07
  • 1970-01-01
  • 2021-05-28
  • 2021-12-13
  • 1970-01-01
  • 1970-01-01
  • 2020-07-03
  • 1970-01-01
相关资源
最近更新 更多