Android 房间:在继承字段中查询 returns null
Android Room: Query returns null in inherited field
我目前正在重构我的项目以使用 Room Persistence Library(顺便说一句,我很喜欢它),但是我 运行 遇到了一个问题,我正在查询我的数据库以查找继承自的 pojo一个实体-class。 super class 中的字段由于某种原因未加载查询中的数据。
这是我的 class(顺便说一下,这是定制的 class,不是真正的,因为我无法分享真正的源代码):
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 **
}
查询 return createdAt 为 null 的结果,它不应该是 null,因为所有 SyncEntities 默认 createdAt 为 System.currentTimeMillis() 并且我已经仔细检查了该值是否存在于数据库。
我在编译的时候也出现了下面的警告,但是我不明白为什么:
Warning:(33, 33) The query returns some columns [createdAt, updatedAt]
which are not use by com.example.project.data.models.entities.Task.
You can use @ColumnInfo annotation on the fields to specify the
mapping. com.example.project.data.models.entities.Task has some
fields [created_at, updated_at, deleted] which are not returned by the
query. If they are not supposed to be read from the result, you can
mark them with @Ignore annotation. You can suppress this warning by
annotating the method with
@SuppressWarnings(RoomWarnings.CURSOR_MISMATCH). Columns returned by
the query: taskId, title, status, startDate, createdAt, updatedAt.
Fields in com.example.project.data.models.entities.Task:
created_at, updated_at, deleted, taskId, title, status, startDate.
这是我的超级class:
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 中的错误还是预期的行为?
编辑
正如@pskink 在评论中指出的那样,问题出在查询上。
问题出在查询中:
@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);
查询 returns 列名称为 "createdAt",但实体的字段显式注释为 "created_at",因此它们不匹配。
我目前正在重构我的项目以使用 Room Persistence Library(顺便说一句,我很喜欢它),但是我 运行 遇到了一个问题,我正在查询我的数据库以查找继承自的 pojo一个实体-class。 super class 中的字段由于某种原因未加载查询中的数据。
这是我的 class(顺便说一下,这是定制的 class,不是真正的,因为我无法分享真正的源代码):
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 **
}
查询 return createdAt 为 null 的结果,它不应该是 null,因为所有 SyncEntities 默认 createdAt 为 System.currentTimeMillis() 并且我已经仔细检查了该值是否存在于数据库。
我在编译的时候也出现了下面的警告,但是我不明白为什么:
Warning:(33, 33) The query returns some columns [createdAt, updatedAt] which are not use by com.example.project.data.models.entities.Task. You can use @ColumnInfo annotation on the fields to specify the mapping. com.example.project.data.models.entities.Task has some fields [created_at, updated_at, deleted] which are not returned by the query. If they are not supposed to be read from the result, you can mark them with @Ignore annotation. You can suppress this warning by annotating the method with @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH). Columns returned by the query: taskId, title, status, startDate, createdAt, updatedAt. Fields in com.example.project.data.models.entities.Task: created_at, updated_at, deleted, taskId, title, status, startDate.
这是我的超级class: 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 中的错误还是预期的行为?
编辑 正如@pskink 在评论中指出的那样,问题出在查询上。
问题出在查询中:
@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);
查询 returns 列名称为 "createdAt",但实体的字段显式注释为 "created_at",因此它们不匹配。