Room Persistence Library中的继承

时间:2019-05-15 05:14:40

标签: android android-room

TL; DR:如何使用Room Persistence库在同一个“列表”中存储和检索从ClassA继承的ClassBClassP类型的对象?

换句话说,我应该如何在房间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) {

    }
}

我的应用程序中有多个ElephantGiraffe的实例。我如何使用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及其特定属性(分别为giraffesid)创建表trunkLength和表neckLength。 然后,我们可以通过在基表和子表中都创建一个条目,将动物存储在数据库中。
要通过id检索特定动物,我们现在可以在animalType表中找到base_animals,并决定在哪个子表中-elephantsgiraffes我们需要搜索。

此方法的问题在于,它要求我必须编写一些代码,并且每当创建新的动物实体时都必须对其进行更新-例如Dolphin

所以,我的问题是:我应该如何在Room DB中存储List<? extends BaseAnimal>
如果我可以给BaseAnimal留下一个抽象类,我会更喜欢。

1 个答案:

答案 0 :(得分:0)

我不确定在这里使用继承是个好主意。 我建议改用合成。

保留一个名为Animal(不是BaseAnimal)的类。

动物的类型应该与您建议的一样。

另一个表(AnimalProperties)将保存每个动物的属性。 它将具有“动物”表的外键以及属性名称和属性值。

现在...

如果这是您所需要的全部,意味着一个具有类型和属性的类,那么您就准备就绪了。 但是,如果您还需要该类的行为不同,例如为鸟实现fly()方法并为狗实现run(),则应考虑使用Composition来向Animal添加行为。

如果您不熟悉Composition,请查看here进行简单说明。