TL; DR:如何使用Room Persistence库在同一个“列表”中存储和检索从ClassA
继承的ClassB
和ClassP
类型的对象?
换句话说,我应该如何在房间DB中存储List<? extends BaseAnimal>
?
出于这个问题的目的,我有动物。
public abstract class BaseAnimal {
@PrimaryKey(autoGenerate = true)
private long id;
public BaseAnimal(long id){this.id = id;}
public abstract void func(int param);
public long getId() {
return id;
}
}
动物具有id
并实现某些功能func
。可能会有很多动物。首先,我有一个Elephant
和一个trunkLength
属性,另外还有一个Giraffe
属性和一个neckLength
属性。
public class Giraffe extends BaseAnimal {
public long neckLength;
public Giraffe(long id) {
super(id);
}
@Override
public void func(int param) {
}
}
我的应用程序中有多个Elephant
和Giraffe
的实例。我如何使用Android Room Persistence库存储和检索按BaseAnimal.id
排序的它们?
起初,我希望它会像这样简单:
用BaseAnimal
注释@Entity(tableName = "base_animal_table")
类
用{Annotate for your RoomDatabase
@Database(entities = {BaseAnimal.class},版本= 1)
添加用于插入数据访问对象的功能
@Insert
void insertAnimal(BaseAnimal animal);
向存储库添加方法
public void insertAnimal(BaseAnimal animal){
new insertAnimalAsyncTask(recipeDAO).execute(animal);
}
private static class insertAnimalAsyncTask extends AsyncTask<BaseAnimal, Void, Void> {
private RecipeDAO mAsyncTaskDao;
insertAnimalAsyncTask(RecipeDAO dao) {
mAsyncTaskDao = dao;
}
@Override
protected Void doInBackground(final BaseAnimal... params) {
mAsyncTaskDao.insertAnimal(params[0]);
return null;
}
}
我希望这会导致在空间中生成名为base_animal_table
的表,该表看起来像这样(带有一些示例数据):
| id | ElephantTrunkLength | GiraffeNeckLength |
| 0 | NULL | 12 |
| 12 | 1337 | NULL |
我还希望我可以从该表中检索数据,如下所示:
// this is in the DAO
@Query("SELECT * from `base_animal_table` ORDER BY id ASC")
LiveData<List<BaseAnimal>> getAllAnimals();
,然后获得一个列表,其中包含类型为Elephant
的实体和其trunkLength
属性集以及类型为Giraffe
的实体和其neckLength
集。
这似乎并不简单。我该如何实施?
我看到的一种方法是以下方法,但是我不确定这是否是最佳方法。而且我也开始怀疑Room是否比使用普通的SQLite更容易。我尝试为这种方法留出一个空间的可行例子,但是仍然存在一些未解决的问题。
创建一个表base_animals
,该表仅包含id
和其他基本动物属性以及其子类型的指示符:
// base_animals
| id | animalType |
| 0 | "GIRAFFE" |
| 12 | "ELEPHANT" |
使用此表保留所有动物及其id
的列表。使用elephants
及其特定属性(分别为giraffes
和id
)创建表trunkLength
和表neckLength
。
然后,我们可以通过在基表和子表中都创建一个条目,将动物存储在数据库中。
要通过id
检索特定动物,我们现在可以在animalType
表中找到base_animals
,并决定在哪个子表中-elephants
或giraffes
我们需要搜索。
此方法的问题在于,它要求我必须编写一些代码,并且每当创建新的动物实体时都必须对其进行更新-例如Dolphin
。
所以,我的问题是:我应该如何在Room DB中存储List<? extends BaseAnimal>
?
如果我可以给BaseAnimal
留下一个抽象类,我会更喜欢。
答案 0 :(得分:0)
我不确定在这里使用继承是个好主意。 我建议改用合成。
保留一个名为Animal(不是BaseAnimal)的类。
动物的类型应该与您建议的一样。
另一个表(AnimalProperties)将保存每个动物的属性。 它将具有“动物”表的外键以及属性名称和属性值。
现在...
如果这是您所需要的全部,意味着一个具有类型和属性的类,那么您就准备就绪了。 但是,如果您还需要该类的行为不同,例如为鸟实现fly()方法并为狗实现run(),则应考虑使用Composition来向Animal添加行为。
如果您不熟悉Composition,请查看here进行简单说明。