Android 如何处理房间中嵌套的1对1对象中的关系数据(将ForeignKey转换为Object)
假设我有一个Android 如何处理房间中嵌套的1对1对象中的关系数据(将ForeignKey转换为Object),android,android-room,android-architecture-components,android-jetpack,Android,Android Room,Android Architecture Components,Android Jetpack,假设我有一个订单和一个用户实体,类似如下: User.java: @Entity public class User { @PrimaryKey public long id; @NonNull public String username; } @Entity(foreignKeys = @ForeignKey(entity = User.class, parentColumn
订单
和一个用户
实体
,类似如下:
User.java
:
@Entity
public class User {
@PrimaryKey
public long id;
@NonNull
public String username;
}
@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.java
:
@Entity
public class User {
@PrimaryKey
public long id;
@NonNull
public String username;
}
@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;
}
这样,我就有了一个订单
,里面有一个用户
,在数据库上,我只把这个与用户id的关系保存为外键
,而不是对象本身(它是@忽略
d),因此,一切都是好的和相关的,并且可以扩展为以几种不同的方式和查询等与其他类型一起使用
现在的问题是,如何通过用户
对象自动填充订单?
如果我使用@Embedded
,那么Order
和User
将位于同一个表中,这不利于类型之间的关系分离。我可以将它们与JOIN
一起返回,但这仍然只适用于具有不同名称的数据类型(可能它们都有一个名为“description”的列),此外,在Order
中插入一个用户
的顺序对于JOIN
来说并不简单@Relation
只适用于一对多,它需要一个列表
,这不是我的情况
我认为在long
和User
之间进行转换时,@TypeConverter
可能是最好的选择,但这也很棘手。@TypeConverter
需要一个对DAO
的引用,这样它就可以查询用户
,而@TypeConverter
是一个静态方法,由Room调用,因此传递DAO
可能会很棘手,并导致许多代码气味,此外,对每个用户的额外查询将触发不在同一@事务中的多个搜索
我不熟悉Room,但我敢打赌有一个合适的方法来解决这个问题,将Room与预期使用的关系类型一起使用,我只是不知道如何简单、良好地工作,也无法在任何文档中找到它
现在,问题是,我如何获得一个订单,其中的用户对象由其内部的房间自动填充
我认为没有现成的解决方案
IMHO,实体模型(即,订单
将FK与用户id
映射)不应传播到上层类似的域/表示层,提供一个数据映射器
将实体模型转换为域模型(即,用户
包含一个订单
)对于上层可能是更好的选择。IMHO,使用@Embedded
是进行1:1映射的最简单方法。大部分的time Room数据库就像服务器响应的快照一样,很少对其执行业务逻辑,这是服务器的责任,那么为什么我们需要这样的关系分离呢?因为有时相同的数据会出现在不同的服务器响应中,所以如果我们为每个响应创建一个表,我们将浪费存储空间,例如,Order
中可能有一个User
,但Shopping Cart
中也可能有User
。那么我们将在两个不同的表上使用相同的用户
?如果用户
更改了他的名字,我们在应用程序的购物车页面上得到了更新,但是用户离线了怎么办?我们将在订单页面中以旧名称显示用户。如果我们试图手动同步,没有关系分离,他会变得一团糟吗?这是有道理的!我现在看到的唯一选择是使用@embedded并分离查询中的对象,以便它们从单独的表中进行更新、插入和选择,这样至少我认为我们可以依靠关系隔离,并在数据不正确时从房间中自动更新(尽管对于复杂查询,我们不确定这一点),您必须传播FK,否则,如果您偶然发现它的任何值,如何将该实体再次保存回数据库?如果删除FK,则删除与数据库的链接我不理解传播FK
的含义。您说必须从数据库返回的对象中删除FK,对吗?不,我的意思是保留当前建模,并使用@Relation为查询结果创建另一个pojo,然后将此pojo转换为上层所需的内容。当使用Room返回DataSource.Factory
时,这会变得更加复杂。您必须自行转换这些值,而不是使用框架提供的值。。。。更多的麻烦,没有更多的回报