如何使用 Android ROOM 数据库中的关系对子数据进行排序(一对多关系)
How to sort child data using relation in Android ROOM database which uses (One to many relationship)
商店实体
data class Store(
val storeId: Int,
val name: String,
val storeRank:Int
)
产品实体
data class Product(
val productId: Int,
val name: String
)
参考实体
data class Reff(
val storeId: Int,
val productId: Int,
val productRankInStore:Int
)
关系
data class StoreAndProduct(
@Embedded
val store: Store,
@Relation(
entity = Product::class,
parentColumn = "storeId",
entityColumn = "productId",
associateBy = Junction(
parentColumn = "storeId",
entityColumn = "productId",
value = Reff::class
)
)
val product: List<Product>
)
这里我需要使用关键字 productRankInStore 对 Products 进行排序。我已经实现了关系并且工作正常。但是我找不到任何其他方法来使用 productRankInStore
对产品进行排序
注意:相同的产品在不同的商店有不同的排名(productRankInStore)
如果你有一个抽象 class 而不是 @Dao 注释的接口 class(es) 那么你可以有效地覆盖 Room 处理 @Relation 的方式,使用一个执行两个阶段的函数, 后者相应排序。
您可以通过使用 2 个 @Query 来做到这一点:-
- 主要(商店)和
- 二次查询(商品按排名排序)
然后您将它们组合成一个函数,例如:-
@Dao
abstract class AllDAO {
@Query("SELECT * FROM store")
abstract fun getAllStores(): List<Store>
@Query("SELECT product.* FROM reff JOIN product ON product.productId = reff.productId WHERE reff.storeId=:storeId ORDER BY productRankInStore DESC")
abstract fun getStoreProductsSortedByRank(storeId: Int): List<Product>
@Query("")
@Transaction
fun getStoreAndProductsSortedByProductRank(): List<StoreAndProduct> {
val rv = arrayListOf<StoreAndProduct>()
for (store in getAllStores() /* obviously change initial query if desired */) {
rv.add(StoreAndProduct(store,getStoreProductsSortedByRank(store.storeId)))
}
return rv
}
}
然后您可以使用:-
dao.getStoreAndProductsSortedByProductRank()
例如如果您的数据为:-
和
排名第一然后是以下
for(s in dao.getStoreAndProductsSortedByProductRank()) {
Log.d("DBINFO","Store is ${s.store.name}")
for (p in s.product) {
Log.d("DBINFO","\tProduct is ${p.name}")
}
}
将输出:-
2022-03-26 06:43:15.753 D/DBINFO: Store is Store1
2022-03-26 06:43:15.753 D/DBINFO: Product is ProductA
2022-03-26 06:43:15.753 D/DBINFO: Product is ProductB
2022-03-26 06:43:15.753 D/DBINFO: Product is ProductC
2022-03-26 06:43:15.753 D/DBINFO: Store is Store2
2022-03-26 06:43:15.753 D/DBINFO: Product is ProductC
2022-03-26 06:43:15.753 D/DBINFO: Product is ProductA
2022-03-26 06:43:15.753 D/DBINFO: Product is ProductB
2022-03-26 06:43:15.753 D/DBINFO: Store is Store3
2022-03-26 06:43:15.753 D/DBINFO: Product is ProductC
2022-03-26 06:43:15.753 D/DBINFO: Product is ProductB
2022-03-26 06:43:15.754 D/DBINFO: Product is ProductA
注意 rankInStore 将不可用(根据您的 StoreAndProduct)。
- 如果您需要可用的 rankInStore,那么您需要做一些事情,例如拥有并使用 ProductAndRank POJO。
商店实体
data class Store(
val storeId: Int,
val name: String,
val storeRank:Int
)
产品实体
data class Product(
val productId: Int,
val name: String
)
参考实体
data class Reff(
val storeId: Int,
val productId: Int,
val productRankInStore:Int
)
关系
data class StoreAndProduct(
@Embedded
val store: Store,
@Relation(
entity = Product::class,
parentColumn = "storeId",
entityColumn = "productId",
associateBy = Junction(
parentColumn = "storeId",
entityColumn = "productId",
value = Reff::class
)
)
val product: List<Product>
)
这里我需要使用关键字 productRankInStore 对 Products 进行排序。我已经实现了关系并且工作正常。但是我找不到任何其他方法来使用 productRankInStore
对产品进行排序注意:相同的产品在不同的商店有不同的排名(productRankInStore)
如果你有一个抽象 class 而不是 @Dao 注释的接口 class(es) 那么你可以有效地覆盖 Room 处理 @Relation 的方式,使用一个执行两个阶段的函数, 后者相应排序。
您可以通过使用 2 个 @Query 来做到这一点:-
- 主要(商店)和
- 二次查询(商品按排名排序)
然后您将它们组合成一个函数,例如:-
@Dao
abstract class AllDAO {
@Query("SELECT * FROM store")
abstract fun getAllStores(): List<Store>
@Query("SELECT product.* FROM reff JOIN product ON product.productId = reff.productId WHERE reff.storeId=:storeId ORDER BY productRankInStore DESC")
abstract fun getStoreProductsSortedByRank(storeId: Int): List<Product>
@Query("")
@Transaction
fun getStoreAndProductsSortedByProductRank(): List<StoreAndProduct> {
val rv = arrayListOf<StoreAndProduct>()
for (store in getAllStores() /* obviously change initial query if desired */) {
rv.add(StoreAndProduct(store,getStoreProductsSortedByRank(store.storeId)))
}
return rv
}
}
然后您可以使用:-
dao.getStoreAndProductsSortedByProductRank()
例如如果您的数据为:-
和
排名第一然后是以下
for(s in dao.getStoreAndProductsSortedByProductRank()) {
Log.d("DBINFO","Store is ${s.store.name}")
for (p in s.product) {
Log.d("DBINFO","\tProduct is ${p.name}")
}
}
将输出:-
2022-03-26 06:43:15.753 D/DBINFO: Store is Store1
2022-03-26 06:43:15.753 D/DBINFO: Product is ProductA
2022-03-26 06:43:15.753 D/DBINFO: Product is ProductB
2022-03-26 06:43:15.753 D/DBINFO: Product is ProductC
2022-03-26 06:43:15.753 D/DBINFO: Store is Store2
2022-03-26 06:43:15.753 D/DBINFO: Product is ProductC
2022-03-26 06:43:15.753 D/DBINFO: Product is ProductA
2022-03-26 06:43:15.753 D/DBINFO: Product is ProductB
2022-03-26 06:43:15.753 D/DBINFO: Store is Store3
2022-03-26 06:43:15.753 D/DBINFO: Product is ProductC
2022-03-26 06:43:15.753 D/DBINFO: Product is ProductB
2022-03-26 06:43:15.754 D/DBINFO: Product is ProductA
注意 rankInStore 将不可用(根据您的 StoreAndProduct)。
- 如果您需要可用的 rankInStore,那么您需要做一些事情,例如拥有并使用 ProductAndRank POJO。