TL; DR: Как я могу хранить и извлекать объекты типа ClassA
и ClassB
, которые оба наследуются от ClassP
в одном и том же «списке», используя Библиотеку постоянства помещения?
Другими словами, Как мне сохранить List<? extends BaseAnimal>
в моей комнате DB?
У меня есть Животные, для целей этого вопроса.
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, сохранять и извлекать их, отсортированные по BaseAnimal.id
?
Ожидания
Сначала я надеялся, что все будет так просто:
Аннотируйте класс BaseAnimal
с помощью @Entity(tableName = "base_animal_table")
Аннотируйте мое расширение RoomDatabase
с
@Database (entity = {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
.
Итак, мой вопрос: Как мне хранить List<? extends BaseAnimal>
в моей комнате DB?
Я бы предпочел, чтобы я мог оставить BaseAnimal
абстрактный класс.