我是Android Room新手。我想从表中读取并从相关表中读取。这种关系非常普遍。一个表定义实例。另一个表定义了类型。想象一下Animal表和AnimalType表。几乎每次必须读取Animal表时,都需要读取AnimalType表。例如,我们想要显示动物名称(来自Animal表格)和猴子图标(来自AnimalType表格)。
根据Android Room文档中的示例,这是对其进行建模的数据类:
public class AnimalWithType {
@Embedded
private Animal animal;
@Embedded
private AnimalType type;
...
DAO可以使用单个查询查询数据。房间应该足够聪明,可以填充两个孩子班。
@Dao
public interface ZooDao
@Query("select * from animal join animal_type on (animal.id = animal_type.id)")
List<AnimalWithType> getAllAnimals();
一如既往,理论很漂亮。现实被打破了。结果是以下错误:
Error:(8, 8) error: Multiple fields have the same columnName: id. Field names: animal > id, animalType > id.
显然,Room对于只获得一个&#34; id&#34;而感到困惑。查询中的列以及它所属的类。有两种可能的解决方案: 1)我们可以为building_type.id创建一个列名别名,并告诉Room它。 2)我们已经知道从Animal表到AnimalType表的外键(也许是animal_type_id)有另一个id列。
问题是我们如何与Room沟通。房间是否能够处理这种情况?
如何解决这个问题的提示表示赞赏。我希望Room不要做一些尴尬的事情,就像给每个id列一个唯一的名字。
答案 0 :(得分:7)
public class AnimalWithType {
@Embedded
private Animal animal;
@Embedded(prefix = "type_")
private AnimalType type;
...
列别名很长且很乱。我希望有人能找到更清洁的方式。
@Query("select animal.id, animal.name..., animal_type.id as type_id... from animal join animal_type on (animal.id = animal_type.id)")
答案 1 :(得分:2)
您需要专门提供列名,而不是使用*
来收集所有字段,因为在两个表中都找到 id ,从而导致错误。将您的查询更改为:
select animal.id AS 'ID', animal.columnA, animal.columnB,
animal_type.columnA, animal_type.columnB from animal
join animal_type on (animal.id = animal_type.id)
你不需要从两个表中获取ID,因为它们是相同的,所以一个就足够了。但是,将 coulmnA,columnB等替换为您要获取的有效列名。
答案 2 :(得分:2)
我通过在列名称中添加前缀来解决这个问题,因此它们是唯一的。如果您的案例不允许更改列名,则应使用一些提供的答案和@Embedded(前缀)注释。
@Entity(tableName = "animal")
public class Animal {
@PrimaryKey
@ColumnInfo(name = "animal_id")
public long id;
...
}
@Entity(tableName = "animal_type")
public class AnimalType {
@PrimaryKey
@ColumnInfo(name = "animal_type_id")
public long id;
...
}
您的查询将是:
SELECT * FROM animal JOIN animal_type ON animal_id = animal_type_id