【问题标题】:Null Data Returned with Nested Relation in Room Database Android在房间数据库 Android 中返回带有嵌套关系的空数据
【发布时间】:2021-11-02 19:03:22
【问题描述】:

鉴于我有 3 个实体,Order 包含 LineItem 的列表,每个 LineItem 将通过 productId 与一个 Product 关联。

从OrderDao获取数据时,product字段返回null,但lineItem字段有数据的问题。虽然我可以使用 ProductWithLineItem 数据。 已经尝试了很多解决方法,但它不起作用。 这是我的实体和 dao 代码

实体

@Entity(tableName = DataConstant.ORDER_TABLE)
data class Order(
    @PrimaryKey
    @ColumnInfo(name = "orderId")
    val id: String,

    @ColumnInfo(name = "status")
    var status: String
)
@Entity(tableName = DataConstant.LINE_ITEM_TABLE)
data class LineItem(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "lineItemId")
    val id: Long,

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

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

    @ColumnInfo(name = "quantity")
    var quantity: Int,

    @ColumnInfo(name = "subtotal")
    var subtotal: Double
) 

@Entity(tableName = DataConstant.PRODUCT_TABLE)
data class Product(
    @PrimaryKey
    @NonNull
    @ColumnInfo(name = "productId")
    val id: String,

    @ColumnInfo(name = "name")
    var name: String?,

    @ColumnInfo(name = "description")
    var description: String?,

    @ColumnInfo(name = "price")
    var price: Double?,

    @ColumnInfo(name = "image")
    var image: String?,

    )

关系 POJO

data class ProductAndLineItem(
    @Embedded val lineItem: LineItem?,
    @Relation(
        parentColumn = "productId",
        entityColumn = "productId"
    )
    val product: Product?
)

data class OrderWithLineItems(
    @Embedded var order: Order,
    @Relation(
        parentColumn = "orderId",
        entityColumn = "orderId",
        entity = LineItem::class
    )
    val lineItemList: List<ProductAndLineItem>
)


@Dao
interface OrderDao {
    @Transaction
    @Query("SELECT * FROM `${DataConstant.ORDER_TABLE}` WHERE orderId = :id")
    fun getById(id: String): Flow<OrderWithLineItems>
}

Dao运行后的结果

Result after running query

【问题讨论】:

    标签: android sqlite kotlin android-room android-architecture-components


    【解决方案1】:

    这是我的实体和 dao 代码

    你的代码看起来很好,除了返回一个流,测试,使用你的代码,但是在主线程上使用 List(并且没有 WHERE 子句),即 Dao 是:-

    @Query("SELECT * FROM ${DataConstant.ORDER_TABLE}")
    @Transaction
    abstract fun getOrderWithLineItemsAndWithProduct(): List<OrderWithLineItems>
    

    结果:-

    正在加载/测试的数据使用:-

        db = TheDatabase.getInstance(this)
        orderDao = db.getOrderDao()
        orderDao.clearAll()
    
        orderDao.insert(Product("product1","P1","desc1",10.01,"image1"))
        orderDao.insert(Product("product2","P2","desc2",10.02,"image2"))
        orderDao.insert(Product("product3","P3","desc3",10.03,"image3"))
        orderDao.insert(Product("product4","P4","desc4",10.04,"image4"))
        orderDao.insert(Product("","","",0.0,""))
    
        val o1 = orderDao.insert(Order("Order1","initiaited"))
        val o2 = orderDao.insert(Order("Order2","finalised")) // Empty aka no List Items
    
        val o1l1 = orderDao.insert(LineItem(10,"product3","Order1",1,10.01))
        val o1l2 = orderDao.insert(LineItem(20,"product4","Order1",2,20.08))
        val o1l3 = orderDao.insert(LineItem(30,"","Order1",3,30.09))
        val o1l4 = orderDao.insert(LineItem(40,"","x",1,10.01))
        //val o1l3 = orderDao.insert(LineItem(30,"no such product id","Order1",10,0.0))
        // exception whilst trying to extract if not commented out at test = ....
        val TAG = "ORDERINFO"
        val test = orderDao.getOrderWithLineItemsAndWithProduct()
    
        for(owl: OrderWithLineItems in orderDao.getOrderWithLineItemsAndWithProduct()) {
            Log.d(TAG,"Order is ${owl.order.id} status is ${owl.order.status}")
            for(pal: ProductAndLineItem in owl.lineItemList) {
                Log.d(TAG,"\tLine Item is ${pal.lineItem.id} " +
                        "for Order ${pal.lineItem.orderId} " +
                        "for ProductID ${pal.lineItem.productId} " +
                        "Quantity=${pal.lineItem.quantity} " +
                        "Product description is ${pal.product.description} Product Image is ${pal.product.image} Price is ${pal.product.price}")
            }
        }
    

    因此,我认为问题可能是由于某种原因,Flow 正在检测第一个查询何时完成但在基础查询之前。

    也就是说,当使用@Relation 时,核心对象(订单)通过查询提取并创建核心对象,然后相关对象由另一个查询提取并用于将所有相关对象构建为列表(除非只是一个当它不必是一个列表时)。因此,在此基础查询之前,核心对象将具有基础对象的 null 或空列表。当然,对于@Relations 的层次结构,它会沿着/向下复制层次结构。

    我建议暂时将.allowMainThreadQueires 添加到databaseBuilder 并使用List&lt;OrderWithLineItems&gt; 或仅使用一个OrderWithLineItems。如果使用它,那么您将获得产品,那么问题在于流程(这是我怀疑的)。

    【讨论】:

    • 尚未尝试过,但感谢@MikeT 对此案例的深入解释。关于性能,在主线程上查询可能不好,这种情况有什么优化的方法吗?
    • 已经解决了这个问题。问题是因为我在编写测试时忘记插入产品数据。 Flow 运行良好,没有问题。再次感谢@MikeT 的回答
    猜你喜欢
    • 2022-08-24
    • 2020-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-13
    • 1970-01-01
    相关资源
    最近更新 更多