【问题标题】:Android Room: Query returns null in inherited fieldAndroid Room:查询在继承的字段中返回 null
【发布时间】:2018-03-09 20:03:09
【问题描述】:

我目前正在重构我的项目以使用 Room Persistence 库(顺便说一句,我很喜欢它),但我遇到了一个问题,我在数据库中查询从实体类继承的 pojo。超类中的字段由于某种原因没有加载来自查询的数据。

这是我的课程(顺便说一句,这是一个自定义课程,不是真正的课程,因为我无法分享真正的源代码):

Task.java:

public class Task extends SyncEntity {

    @PrimaryKey(autoGenerate = true)
    public final long taskId;

    public final String title;

     /** Status of the given task.
     * Enumerated Values: 0 (Active), 1 (Inactive), 2 (Completed)
     */
    @TypeConverters(StatusConverter.class)
    public final Status status;

    @TypeConverters(DateConverter.class)
    public Date startDate;

    public Task(@NonNull String taskId,
                   @NonNull String title,
                   @NonNull Status status,
                   @NonNull Date startDate,
                   @NonNull Long createdAt,
                   @Nullable Long updatedAt,
                   @Nullable Boolean deleted) {
        super(createdAt, updatedAt, deleted);
        this.taskId = taskId;
        this.title = title;
        this.status = status;
    }

    @Ignore
    public Task(@NonNull Builder builder) {
        super(builder);
        this.taskId = builder.taskId;
        this.title = builder.title;
        this.status = builder.status;
    }

    ...
    ** left out for brevity **

}

和我的查询:

@Dao
public interface TaskRepository {

    @Query("SELECT " +
            "taskId, " +
            "title, " +
            "status, " +
            "startDate, " +
            "created_at AS createdAt, " +
            "updated_at AS updatedAt " +
            "FROM tasks " +
            "WHERE status = 0 " +
            "AND deleted = 0")
    LiveData<List<Task>> getActiveTasks();
    ...
    ** left out for brevity **
}

查询返回 createdAt 为空的结果,它不应该是空值,因为所有 SyncEntities 默认 createdAt 为 System.currentTimeMillis() 并且我已经仔细检查了该值是否存在于数据库中。

编译时我也收到以下警告,但我不明白为什么:

警告:(33, 33) 查询返回一些列 [createdAt, updatedAt] com.example.project.data.models.entities.Task 不使用。 您可以在字段上使用 @ColumnInfo 注释来指定 映射。 com.example.project.data.models.entities.Task 有一些 未返回的字段 [created_at, updated_at, deleted] 询问。如果不应该从结果中读取它们,您可以 用@Ignore 注释标记它们。您可以通过以下方式抑制此警告 用注释方法 @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)。返回的列 查询:taskId、title、status、startDate、createdAt、updatedAt。 com.example.project.data.models.entities.Task 中的字段: created_at、updated_at、deleted、taskId、title、status、startDate。

这是我的超类: SynEntity.java

@Entity
public class SyncEntity implements Syncable {

    @NonNull
    @ColumnInfo(name = "created_at")
    public final Long createdAt;

    @Nullable
    @ColumnInfo(name = "updated_at")
    public final Long updatedAt;

    @Nullable
    public final Boolean deleted;

    SyncEntity(@NonNull Long createdAt,
               @Nullable Long updatedAt,
               @Nullable Boolean deleted) {
            this.createdAt = createdAt;
            this.updatedAt = updatedAt;
            this.deleted = deleted == null ? false : deleted;
    }

    @Ignore
    SyncEntity(@NonNull Builder<?> builder) {
            this.createdAt = builder.createdAt;
            this.updatedAt = builder.updatedAt;
            this.deleted = builder.deleted;
    }

    public static class Builder<T extends Builder<T>> {

        @NonNull
        private Long createdAt = System.currentTimeMillis();
        @Nullable
        private Long updatedAt = null;
        @NonNull
        private Boolean deleted = false;

        public Builder() {}

    ...
    ** left out for brevity **

}

这是 Room 中的错误还是预期行为?

【问题讨论】:

  • 很好的建议。没想到。只是检查...谁曾经发布过现在已删除的评论?!?
  • 是我,但是由于您忽略它超过 15 分钟,我虽然您不在乎,所以我删除了该评论
  • 哦,抱歉,不是故意的,而是去开会了。
  • 你实际上已经引导我找到答案了。
  • 所以出了什么问题? created_at AS createdAt ?应该只是created_at ?

标签: android android-room


【解决方案1】:

编辑 正如@pskink 在 cmets 中指出的那样,问题在于查询。

问题在于查询:

@Override
public LiveData<List<UserPet>> loadUserAndPetNames() {
    final String _sql = "SELECT users.firstName AS firstName, 
    users.lastName AS lastName, pets.name AS petName, pets.created_at 
    AS createdAt, pets.updated_at AS updatedAt, pets.deleted AS deleted 
    FROM users, pets WHERE users.userId = pets.user_id";
    final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);

查询将列名返回为“createdAt”,但实体的字段显式注释为“created_at”,因此它们不匹配。

【讨论】:

  • 好的,我没有时间检查您的示例项目,但似乎如果您将 "created_at AS createdAt, updated_at AS updatedAt " 替换为 "created_at, updated_at " 它应该可以正常工作,您需要 AS 别名做什么?跨度>
  • 你是对的。不知道我怎么会错过。我想我什至尝试过,但肯定忘记运行测试了。
  • 这是因为您有 @ColumnInfo 注释,它基本上说:“如果您的数据库列名称与您的实体字段名称不同,则在此处指定它,但在 db 查询中始终使用数据库列,我们会知道如何将数据库列映射到实体字段"
  • 您应该将其添加为答案
  • 感谢您的帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-19
  • 2021-04-08
  • 1970-01-01
  • 2012-04-29
  • 1970-01-01
相关资源
最近更新 更多