本文介绍了房间持久性库中的继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TL; DR:如何使用Room Persistence库在同一个列表"中存储和检索都继承自ClassPClassAClassB类型的对象?

TL;DR: How can I store and retrieve objects of type ClassA and ClassB which both inherit from ClassP in the same "list", using the Room Persistence Library?

换句话说,我应该如何在房间DB中存储List<? extends BaseAnimal>?

In other words, How should I store a List<? extends BaseAnimal> in my Room DB?

出于这个问题的目的,我有动物.

I have Animals, for the purpose of this question.

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属性.

An animal has an id and implements some function func. There will likely be many kinds of animals. To start with, I have an Elephant which additionally has a trunkLength property, and a Giraffe which additionally has a neckLength property.

public class Giraffe extends BaseAnimal {
    public long neckLength;

    public Giraffe(long id) {
        super(id);
    }

    @Override
    public void func(int param) {

    }
}

我的应用程序中有几个ElephantGiraffe实例.如何使用Android Room Persistence Library存储和检索按BaseAnimal.id排序的它们?

I have several instances of Elephant and Giraffe in my application. How can I, using the Android Room Persistence Library, store and retrieve them sorted by BaseAnimal.id?

起初,我希望它会像这样简单:

At first, I hoped that it would be as simple as this:

  • @Entity(tableName = "base_animal_table")

注释RoomDatabase的扩展名 @Database(entities = {BaseAnimal.class},版本= 1)

Annotate my extension of the RoomDatabase with @Database(entities = {BaseAnimal.class }, version = 1)

添加用于插入数据访问对象的功能
@Insert void insertAnimal(BaseAnimal animal);

Add a function for inserting to the Data Access Object
@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的表,该表看起来像这样(带有一些示例数据):

I expected that this would lead to room generating a table named base_animal_table which would look somewhat like this (with some sample data):

| id | ElephantTrunkLength | GiraffeNeckLength |
| 0  | NULL                | 12                |
| 12 | 1337                | NULL              |

我还希望我可以从该表中检索数据,如下所示:

I also expected that I could retrieve the data from this table something like this:

// this is in the DAO
@Query("SELECT * from `base_animal_table` ORDER BY id ASC")
LiveData<List<BaseAnimal>> getAllAnimals();

,然后获得一个列表,该列表包含设置为trunkLength的类型为Elephant的实体和设置为neckLength的类型为Giraffe的实体.这似乎并不简单.我该如何实施?

and then get a list that contains both, entities of type Elephant with their trunkLength property set, and entities of type Giraffe with their neckLength set.This seems not to be straightforward. How can I implement this?

我看到的一种方法是以下方法,但是我不确定这是否是最佳方法.而且我也开始怀疑Room是否比使用普通的SQLite更容易.我尝试为这种方法留出空间,并给出了一个可行的示例,但是仍然存在一些未解决的问题.

One approach I see is the following, but I am not sure whether it is the best way. And I am also starting to doubt that Room makes this any easier than using plain SQLite. I tried to produce a working example for this approach with room, but there are still some unresolved issues.

创建一个表base_animals,该表仅包含id和其他基本动物属性以及其子类型的指示符:

Create a table base_animals which only contains the id and other base animal attributes, along with an indicator of their child type:

// base_animals
| id | animalType |
| 0  | "GIRAFFE"  |
| 12 | "ELEPHANT" |

使用此表保留所有动物及其id的列表.创建具有id及其特定属性(分别为trunkLengthneckLength)的表elephants和表giraffes.然后,我们可以通过在基表和子表中都创建一个条目,将动物存储在数据库中.
要通过id检索特定动物,我们现在可以在base_animals表中找到animalType,并决定要在哪个子表-elephantsgiraffes中进行搜索.

Use this table to keep a list of all animals and their ids. Create a table elephants and a table giraffes with the id and their specific properties (trunkLength and neckLength, respectively).Then we can store an animal in the DB by creating an entry in both the base table and the child table.
To retrieve a specific animal by id, we can now find the animalType in the base_animals table and with that decide in which child table - elephants or giraffes we need to search.

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

The problem I have with this approach is that it requires that I have to write quite some code and I have to update it whenever I create a new animal entity - e.g. a Dolphin.

所以,我的问题是:我应该如何在房间DB中存储List<? extends BaseAnimal>?
如果可以将BaseAnimal保留为抽象类,我会更喜欢.

So, my question is: How should I store a List<? extends BaseAnimal> in my Room DB?
I would prefer it if I could leave BaseAnimal an abstract class.

推荐答案

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

I'm not sure that using inheritance is a good idea here.I would suggest using composition instead.

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

Keep a class named Animal (not BaseAnimal).

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

The animal should have a type just like you suggested.

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

Another table (AnimalProperties) would hold the properties of each animal.It will have a foreign key to the Animals table and a property name and property value.

现在...

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

If this is all that you need, meaning a class with type and properties then you're all set.But if you also need the class to behave differently like implementing a fly() method for a bird and run() a dog then you should consider using Composition to add behaviors to the Animal.

如果您不熟悉Composition,请在此处进行简单说明

If you are not familiar with Composition have a look here for a simple explanation.

这篇关于房间持久性库中的继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-05 12:35