Как заполнить поле столбца объекта в библиотеке комнат

У меня есть объект класса, как показано ниже

@Entity
public class Task {    
    private String name; 
    private Integer ParentId;
    private Integer userId;   
    @Ignore
    private int noOfSubTask;
}

в классе DAO существует метод getTaskList()

@Dao
public interface TaskDao extends Dao<Task> {

@Query("SELECT *,(SELECT count(*) FROM Task b  WHERE a._id = b.ParentId ) AS noOfSubTask FROM Task a ")
LiveData<List<Task>> getTaskList();
}

Я хочу заполнить noOfSubTask номером, заданным (SELECT count (*) FROM Task b WHERE a._id = b.ParentId) частью запроса, но проблема в том, что это не столбец, поэтому библиотека комнаты не отображает его метод getTaskList в dao (автоматически сгенерированный) класс.

Есть ли способ заполнить поле без столбца объекта (например, noOfSubTask в моем случае) с помощью любого метода класса dao библиотеки комнат?

Ответ 1

Я столкнулся с той же проблемой несколько дней назад и посмотрел на эту тему. Я использую классы data Kotlin для создания объектов базы данных. Учитывая, что классы данных Kotlin не хорошо работают с наследованием, наследование не было жизнеспособным вариантом. Мое решение состояло в том, чтобы использовать ключевое слово @Embedded в классе упаковки следующим образом:

data class TaskToDisplay(@Embedded
                         var task: Task,
                         var noOfSubTask: Int = 0)

Это решение не создает дополнительный столбец в базе данных и, самое главное, соответствует всем полям "Задачи" с столбцами "Ответ на вопрос".

Ответ 2

Создайте подкласс класса Задача

public class TaskDisplayModel extends Task{

@Ignore
private transient int noOfSubTask;

}

Тогда ваш запрос будет

@Query("SELECT *,(SELECT count(*) FROM Task b  WHERE a._id = b.ParentId ) AS noOfSubTask FROM Task a ")
LiveData<List<TaskDisplayModel >> getTaskList();

Ответ 3

Я использую Kotlin, и у меня была аналогичная проблема, и ниже, как я ее решил.

  1. Добавить дополнительное поле с? ( Вопросительный знак) для nullable, без аннотации @Ignore

    @Entity(tableName = "task")
    data class Task (
        val name: String,
        val parentId: Integer,
        val userId: Integer,
        val noOfSubTask: Integer?
    )
    
  2. Добавьте дополнительное поле (noOfSubTask в этом случае) в каждый запрос, который выбирает задачу в DAO.

    @Dao
    interface TaskDao {
        @Query("SELECT *,(SELECT count(*) FROM Task b  WHERE a._id = b.ParentId ) AS noOfSubTask FROM Task a ")
        fun getTaskList(): LiveData<List<Task>>
    
        @Query("SELECT *, NULL AS noOfSubTask FROM Task WHERE name = :name")
        fun getTask(name: String): LiveData<Task>
    
        ...
    }
    

Если это не сработает, вы можете попробовать RawQuery, который был недавно введен в Google I/O 2018.

Ответ 4

Вы должны переместить поле @Ignore за пределы конструктора, например так:

Пример данных:

@Entity(primaryKeys = ["id"])
data class User(
    @SerializedName("id")
    val id: Int,

    @SerializedName("name")
    val name: String,

    @SerializedName("age")
    val age: Int
) {
   @Ignore
   val testme: String?
}

Обратитесь к обсуждению github для более подробной информации.