RoomDB - JOIN 查询,其结果是一个数据类型列表,其中一个字段的值是 2 个表字段的乘积
RoomDB - JOIN query for which the result is a list of data types with a field whose value is a multiplication of 2 tables fields
假设我的 RoomDB 有以下实体:
enum class Type {
FOO,
BAR
}
@Entity(
tableName = "amount",
primaryKeys = ["id", "type"]
)
data class Amount(
val id: Long,
val type: Type,
val amount: Int
)
@Entity(
tableName = "value",
primaryKeys = ["id", "valueType"]
)
data class Value(
val id: Long,
val valueType: Type,
val value: Int
)
我想做的是以某种方式,使用 SQL 查询(或者理想情况下是 RoomDB 注释...)查询 amount
table,并将每个金额与相应的value
table 中的值行(使用 amount
中的 type
交叉引用 value
[= 上的 valueType
字段41=]) 通过将 amount
字段与 value
字段相乘得到如下对象:
data class ValueOfAmount(
val type: Type,
val valueOfAmount: Int // amount * value
)
我可以想办法做到这一点,但它需要在我的 repo 代码层中执行一些 JOIN “逻辑”,而我更愿意在查询层执行此操作(如果可能的话) ).
像这样创建连接数据class:
data class AmountWithValue(
@Embedded
val amount: Amount,
@Relation(
parentColumn = "type",
entityColumn = "valueType"
)
val value: Value
)
从我的 dao 中公开一个函数来检索连接的数据:
@Query("SELECT * from amount")
suspend fun getAmountsWithValues() : List<AmountWithValue>
使用此函数,并将结果映射到 ValueOfAmount
个实例,如下所示:
val valueOfAmounts = dao.getAmountsWithValues().map { amountWithValue ->
ValueOfAmount(
amountWithValue.amount.type,
amountWithValue.amount.amount * amountWithValue.value.value
)
}
// Do stuff with value of amounts
我想知道是否有某种方法可以将该映射代码编码到 QUERY 本身(通过 SQL 或者,如果 RoomDB 有一些支持这种类型的注释,则更好复杂查询作为我的数据类型的注释 - 类似于它让我为简单的 JOIN 操作定义关系的方式)。
相信以下可能是您想要的:-
首先要加入Class:-
data class AmountWithCalculatedValue(
@Embedded
val amount: Amount,
val calculatedValue: Int
)
然后是道:-
@Query("SELECT *,(amount * value) AS calculatedValue FROM amount JOIN value ON amount.type = valueType")
fun getAmountWithCalculatedValue(): List<AmountWithCalculatedValue>
如果您也想要值,由于 duplicate/ambiguous 列,它会稍微复杂一些,但您可以使用:-
data class AmountWithCalculatedValue(
@Embedded
val amount: Amount,
val calculatedValue: Int,
@Embedded(prefix = "_value_")
val value: Value
)
有:-
@Query("SELECT amount.id, amount.amount, amount.type,value.id AS _value_id, value.id AS _value_value, value.valueType AS _value_valueType,(amount * value) AS calculatedValue FROM amount JOIN value ON amount.type = valueType")
fun getAmountWithCalculatedValue(): List<AmountWithCalculatedValue>
或:-
@Query("SELECT amount.*,value.id AS _value_id, value.id AS _value_value, value.valueType AS _value_valueType,(amount * value) AS calculatedValue FROM amount JOIN value ON amount.type = valueType")
fun getAmountWithCalculatedValue(): List<AmountWithCalculatedValue>
使用 @Embedded 的前缀参数表示值将以前缀为前缀,因此您必须使用 AS 子句来消除各个列的歧义。由于金额列上没有使用前缀,因此可以使用金额。*(第二道)。
我想说,对于一对一关系,使用@Relationship(与@Embedded 相反)可能比使用 JOIN 效率低一些。由于 Room 的工作方式,它从给定的查询中获取父项,然后通过单独的查询从父项中检索 @Relation,因此它推荐 @Transaction 的原因。
假设我的 RoomDB 有以下实体:
enum class Type {
FOO,
BAR
}
@Entity(
tableName = "amount",
primaryKeys = ["id", "type"]
)
data class Amount(
val id: Long,
val type: Type,
val amount: Int
)
@Entity(
tableName = "value",
primaryKeys = ["id", "valueType"]
)
data class Value(
val id: Long,
val valueType: Type,
val value: Int
)
我想做的是以某种方式,使用 SQL 查询(或者理想情况下是 RoomDB 注释...)查询 amount
table,并将每个金额与相应的value
table 中的值行(使用 amount
中的 type
交叉引用 value
[= 上的 valueType
字段41=]) 通过将 amount
字段与 value
字段相乘得到如下对象:
data class ValueOfAmount(
val type: Type,
val valueOfAmount: Int // amount * value
)
我可以想办法做到这一点,但它需要在我的 repo 代码层中执行一些 JOIN “逻辑”,而我更愿意在查询层执行此操作(如果可能的话) ).
像这样创建连接数据class:
data class AmountWithValue(
@Embedded
val amount: Amount,
@Relation(
parentColumn = "type",
entityColumn = "valueType"
)
val value: Value
)
从我的 dao 中公开一个函数来检索连接的数据:
@Query("SELECT * from amount")
suspend fun getAmountsWithValues() : List<AmountWithValue>
使用此函数,并将结果映射到 ValueOfAmount
个实例,如下所示:
val valueOfAmounts = dao.getAmountsWithValues().map { amountWithValue ->
ValueOfAmount(
amountWithValue.amount.type,
amountWithValue.amount.amount * amountWithValue.value.value
)
}
// Do stuff with value of amounts
我想知道是否有某种方法可以将该映射代码编码到 QUERY 本身(通过 SQL 或者,如果 RoomDB 有一些支持这种类型的注释,则更好复杂查询作为我的数据类型的注释 - 类似于它让我为简单的 JOIN 操作定义关系的方式)。
相信以下可能是您想要的:-
首先要加入Class:-
data class AmountWithCalculatedValue(
@Embedded
val amount: Amount,
val calculatedValue: Int
)
然后是道:-
@Query("SELECT *,(amount * value) AS calculatedValue FROM amount JOIN value ON amount.type = valueType")
fun getAmountWithCalculatedValue(): List<AmountWithCalculatedValue>
如果您也想要值,由于 duplicate/ambiguous 列,它会稍微复杂一些,但您可以使用:-
data class AmountWithCalculatedValue(
@Embedded
val amount: Amount,
val calculatedValue: Int,
@Embedded(prefix = "_value_")
val value: Value
)
有:-
@Query("SELECT amount.id, amount.amount, amount.type,value.id AS _value_id, value.id AS _value_value, value.valueType AS _value_valueType,(amount * value) AS calculatedValue FROM amount JOIN value ON amount.type = valueType")
fun getAmountWithCalculatedValue(): List<AmountWithCalculatedValue>
或:-
@Query("SELECT amount.*,value.id AS _value_id, value.id AS _value_value, value.valueType AS _value_valueType,(amount * value) AS calculatedValue FROM amount JOIN value ON amount.type = valueType")
fun getAmountWithCalculatedValue(): List<AmountWithCalculatedValue>
使用 @Embedded 的前缀参数表示值将以前缀为前缀,因此您必须使用 AS 子句来消除各个列的歧义。由于金额列上没有使用前缀,因此可以使用金额。*(第二道)。
我想说,对于一对一关系,使用@Relationship(与@Embedded 相反)可能比使用 JOIN 效率低一些。由于 Room 的工作方式,它从给定的查询中获取父项,然后通过单独的查询从父项中检索 @Relation,因此它推荐 @Transaction 的原因。