我想说我想在两个实体INNER JOIN
和Foo
之间进行Bar
:
@Query("SELECT * FROM Foo INNER JOIN Bar ON Foo.bar = Bar.id")
List<FooAndBar> findAllFooAndBar();
是否可以强制这样的返回类型?
public class FooAndBar {
Foo foo;
Bar bar;
}
当我尝试这样做时,我收到此错误:
error: Cannot figure out how to read this field from a cursor.
我还尝试使用表格名称别名来匹配字段名称,但这也不起作用。
如果这不可能,我应该如何干净地构建包含两个实体的所有字段的兼容返回类型?
答案 0 :(得分:38)
道
@Query("SELECT * FROM Foo")
List<FooAndBar> findAllFooAndBar();
班级FooAndBar
public class FooAndBar {
@Embedded
Foo foo;
@Relation(parentColumn = "Foo.bar_id", entityColumn = "Bar.id")
//Relation returns a list
//Even if we only want a single Bar object ..
List<Bar> bar;
//Getter and setter...
}
这个解决方案似乎有效,但我并不为此感到自豪。 你觉得怎么样?
编辑:另一种解决方案
道,我更愿意明确选择但是&#34; *&#34;将完成这项工作:)@Query("SELECT Foo.*, Bar.* FROM Foo INNER JOIN Bar ON Foo.bar = Bar.id")
List<FooAndBar> findAllFooAndBar();
班级FooAndBar
public class FooAndBar {
@Embedded
Foo foo;
@Embedded
Bar bar;
//Getter and setter...
}
答案 1 :(得分:7)
试试这种方式。
例如,我在Product
和Attribute
之间存在M2M(多对多)关系。许多产品有很多属性,我需要按Product.id
获取所有属性,并按PRODUCTS_ATTRIBUTES.DISPLAY_ORDERING
排序记录。< / p>
|--------------| |--------------| |-----------------------|
| PRODUCT | | ATTRIBUTE | | PRODUCTS_ATTRIBUTES |
|--------------| |--------------| |-----------------------|
| _ID: Long | | _ID: Long | | _ID: Long |
| NAME: Text | | NAME: Text | | _PRODUCT_ID: Long |
|______________| |______________| | _ATTRIBUTE_ID: Long |
| DISPLAY_ORDERING: Int |
|_______________________|
因此,模型如下所示:
@Entity(
tableName = "PRODUCTS",
indices = [
Index(value = arrayOf("NAME"), unique = true)
]
)
class Product {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "_ID")
var _id: Long = 0
@ColumnInfo(name = "NAME")
@SerializedName(value = "NAME")
var name: String = String()
}
@Entity(
tableName = "ATTRIBUTES",
indices = [
Index(value = arrayOf("NAME"), unique = true)
]
)
class Attribute {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "_ID")
var _id: Long = 0
@ColumnInfo(name = "NAME")
@SerializedName(value = "NAME")
var name: String = String()
}
“加入”表格将是:
@Entity(
tableName = "PRODUCTS_ATTRIBUTES",
indices = [
Index(value = ["_PRODUCT_ID", "_ATTRIBUTE_ID"])
],
foreignKeys = [
ForeignKey(entity = Product::class, parentColumns = ["_ID"], childColumns = ["_PRODUCT_ID"]),
ForeignKey(entity = Attribute::class, parentColumns = ["_ID"], childColumns = ["_ATTRIBUTE_ID"])
]
)
class ProductAttribute {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "_ID")
var _id: Long = 0
@ColumnInfo(name = "_PRODUCT_ID")
var _productId: Long = 0
@ColumnInfo(name = "_ATTRIBUTE_ID")
var _attributeId: Long = 0
@ColumnInfo(name = "DISPLAY_ORDERING")
var displayOrdering: Int = 0
}
在AttributeDAO
中,要获取基于Product._ID
的所有属性,您可以执行以下操作:
@Dao
interface AttributeDAO {
@Query("SELECT ATTRIBUTES.* FROM ATTRIBUTES INNER JOIN PRODUCTS_ATTRIBUTES ON PRODUCTS_ATTRIBUTES._ATTRIBUTE_ID = ATTRIBUTES._ID INNER JOIN PRODUCTS ON PRODUCTS._ID = PRODUCTS_ATTRIBUTES._PRODUCT_ID WHERE PRODUCTS._ID = :productId ORDER BY PRODUCTS_ATTRIBUTES.DISPLAY_ORDERING ASC")
fun getAttributesByProductId(productId: Long): LiveData<List<Attribute>>
}
如果您有任何疑问,请告诉我。
答案 2 :(得分:4)
另一种选择是编写一个新的POJO,表示JOIN查询的结果结构(甚至支持列重命名以避免冲突):
@Dao
public interface FooBarDao {
@Query("SELECT foo.field1 AS unique1, bar.field1 AS unique2 "
+ "FROM Foo INNER JOIN Bar ON Foo.bar = Bar.id")
public List<FooBar> getFooBars();
static class FooBar {
public String unique1;
public String unique2;
}
}
答案 3 :(得分:2)
是否可以强制这样的返回类型?
您可以在@Embedded
和foo
上尝试bar
注释。这将告诉Room尝试从您的查询中获取列并将它们转移到foo
和bar
个实例中。我只对实体尝试了这个,但是文档表明它也应该与POJO一起使用。
但是,如果您的两个表具有相同名称的列,则这可能无法正常工作。
答案 4 :(得分:0)
这是我的食物表
@Entity(tableName = "_food_table")
data class Food(@PrimaryKey(autoGenerate = false)
@ColumnInfo(name = "_food_id")
var id: Int = 0,
@ColumnInfo(name = "_name")
var name: String? = "")
这是我的购物车表和模型类(食物购物车)
@Entity(tableName = "_client_cart_table")
data class CartItem(
@PrimaryKey(autoGenerate = false)
@ColumnInfo(name = "_food_id")
var foodId: Int? = 0,
@Embedded(prefix = "_food")
var food: Food? = null,
@ColumnInfo(name = "_branch_id")
var branchId: Int = 0)
注意:在这里我们在两个表中看到_food_id列。它将引发编译时错误。在@Embedded doc中,您必须使用前缀来区分它们。
道内
@Query("select * from _client_cart_table inner join _food_table on _client_cart_table._food_id = _food_table._food_id where _client_cart_table._branch_id = :branchId")
fun getCarts(branchId: Int) : LiveData<List<CartItem>>
此查询将返回这样的数据
CartItem(foodId=5, food=Food(id=5, name=Black Coffee), branchId=1)
我已经在我的项目中做到了。所以试试吧。编码愉快