【问题标题】:How to add Embedded and Relation to room database如何将嵌入式和关系添加到房间数据库
【发布时间】:2020-08-12 18:39:54
【问题描述】:

假设我有这些表:

表格 - 用户

存储用户

@Entity(
    tableName = "USER"
)
data class User(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "user_id")
    val id: Int,

    @ColumnInfo(name = "user_name")
    val name: String
)

表格 - 项目

像产品一样存储物品

@Entity(
    tableName = "ITEM"
)
data class Item(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "item_id")
    val id: Int,

    @ColumnInfo(name = "item_name")
    val name: String,

    @ColumnInfo(name = "item_description")
    val description: String
)

表格 - 特殊

为产品 1 存储一个特产 特殊需要一个产品存在

@Entity(
    tableName = "SPECIAL",
    foreignKeys = [ForeignKey(
        entity = Item::class,
        parentColumns = ["item_id"],
        childColumns = ["special_item_id"]
    )]
)
data class Special(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "special_id")
    val id: Int,

    @ColumnInfo(name = "special_item_id")
    val coupon_product_id: Int,

    @ColumnInfo(name = "special_name")
    val name: String,

    @ColumnInfo(name = "special_description")
    val description: String

)

表格 -- 收藏夹

存储用户最喜欢的特价商品

@Entity(
    tableName = "TB_FAVOURITE",
    foreignKeys = [ForeignKey(
        entity = User::class,
        parentColumns = ["user_id"],
        childColumns = ["favourite_user_id"]
    ), ForeignKey(
        entity = Special::class,
        parentColumns = ["special_id"],
        childColumns = ["favourite_special_id"]
    )]
)
data class Favourite(
    @PrimaryKey
    @ColumnInfo(name = "favourite_user_id")
    val id: Int,

    @ColumnInfo(name = "favourite_special_id")
    val specialId: Int

)

我的问题是,我如何进行查询以选择所有特价商品,然后创建一个类来存储用户是否喜欢它。目前它是一个用户应用程序,它是一个演示应用程序。因此,用户将始终相同,因此我可以硬编码 findById 并发送用户的 ID。

目标

是将查询的结果作为列表获取,其中包含:

  1. 所有特价商品
  2. 在 SomeClass 中应该包含 Special 里面的 Item
  3. 一个标志,知道它是否是该驱动程序的最爱

问题是我希望能够将房间数据库的结果映射到我想要的对象,所以我猜查询比映射器更重要,我知道如何做映射器。

请注意,我使用assets/database/mydb.db 文件来启动数据库我不知道这是否重要,所以我不知道在这里使用EmbeddedRelation 会如何工作

查询将如何做到这一点? db 的结构是否有任何改进以使其更容易?

【问题讨论】:

    标签: java android kotlin android-room


    【解决方案1】:

    我猜查询比mapper更重要,我知道mapper怎么做。

    嗯,查询取决于你想要得到的结果的结构。 我不认为@Relation 在这种情况下会有所帮助(表之间的关系太复杂了),所以我建议使用带有 JOIN 的自定义查询。

    我的建议是添加一些具有您需要的结构的类(尽管您可以更改它):

    data class SpecialityDetails( 
        @Embedded
        val special: Special, 
        @Embedded
        val item: Item,
        val favourite: Boolean
    )
    

    并在 DAO 中添加下一个方法(据我了解,您可以在此方法中传递 userId):

    @Query("select *, CASE WHEN tb_favourite.favourite_user_id is null THEN 0 else 1 END as favourite from special 
    INNER JOIN ITEM ON special.special_item_id = ITEM.item_id 
    LEFT JOIN tb_favourite ON special.special_id = tb_favourite.favourite_special_id 
    AND tb_favourite.favourite_user_id = :userId")
    
    fun getSpecials(userId: Int): List<SpecialityDetails>
    

    Room 将为您进行映射,因为 SpecialityDetails 包含查询中的所有字段。

    更新Favourite 类使用复合主键

    @Entity(
        tableName = "TB_FAVOURITE",
        primaryKeys = arrayOf("favourite_user_id", "favourite_special_id"),
        foreignKeys = [ForeignKey(
            entity = User::class,
            parentColumns = ["user_id"],
            childColumns = ["favourite_user_id"]
        ), ForeignKey(
            entity = Special::class,
            parentColumns = ["special_id"],
            childColumns = ["favourite_special_id"]
        )]
    )
    data class Favourite(
        @ColumnInfo(name = "favourite_user_id")
        val id: Int,
    
        @ColumnInfo(name = "favourite_special_id")
        val specialId: Int
    
    )
    

    【讨论】:

    • 这个 SpecialityDetails 是否与房间有关?我的意思是像@Entity?
    • 这是没有@Entity 的普通类,因为@Entity 告诉Room 创建SQLite 表,所以没有必要这样做。该类仅用于获取查询的结果。在这个类中还有@Embedded,这些是Room的注解,Room使用它们将原始Cursor类型的查询结果映射到类的实例(为了成功映射查询结果的所有字段都应该在这个对象中)。跨度>
    • 为什么我不能插入到 FAVORITE 表?失败(android.database.sqlite.SQLiteConstraintException:唯一约束失败:TB_FAVOURITE.favourite_user_id(代码 1555 SQLITE_CONSTRAINT_PRIMARYKEY))
    • 你应该为这个表创建复合主键(包括两个字段),否则你只能有一个选择user_id的行。您可以查看声明复合主键 in documentation 的示例 - 第一个示例。
    • 但是为什么我可以使用 SQLite 浏览器创建具有相同主键的不同行?你能添加一个如何创建复合主键的例子吗?
    猜你喜欢
    • 2021-10-16
    • 1970-01-01
    • 2020-07-08
    • 2017-04-22
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多