如何填写房间库中实体的非列字段
Posted
技术标签:
【中文标题】如何填写房间库中实体的非列字段【英文标题】:How to fill non column field of entity in room library 【发布时间】:2018-04-27 04:26:14 【问题描述】:我有一个类实体如下
@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 ) 部分给出, 但问题是它不是一个列,所以房间库不会在 dao 实现(自动生成)类中映射它的 getTaskList 方法。
有没有办法使用房间库的 dao 类的任何方法填充实体的非列字段(如我的情况下的 noOfSubTask)?
【问题讨论】:
你要填充哪个值? 查询中从 (SELECT count(*) FROM Task b WHERE a._id = b.ParentId ) 得到的值 @Kevan 提供的答案对您有用吗?它似乎对我不起作用...... 【参考方案1】:几天前我遇到了同样的问题,并查看了这个帖子。我正在使用 Kotlin data
类来创建数据库实体。鉴于 Kotlin 数据类不能很好地处理继承子类化,这不是一个可行的选择。我的解决方案是在包装类中使用@Embedded
关键字,如下:
data class TaskToDisplay(@Embedded
var task: Task,
var noOfSubTask: Int = 0)
此解决方案不会在数据库中创建额外的列,最重要的是匹配所有 Task 的字段与 Room 的响应列。
【讨论】:
这太棒了,使用包装器可以完全分离出计算列。在我的情况下,我需要它们作为全文搜索的 matchinfo,但不想回到使用 db 游标,谢谢!【参考方案2】:假设创建一个Task的子类
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();
【讨论】:
对我来说,这只有在我摆脱@Ignore
注释时才有效。我认为只要TaskDisplayModel
没有作为要序列化的实体之一提供给您的数据库类,noOfSubTask
字段就不会添加到任何数据库表中。将@Ignore
关闭还可以从查询结果中反序列化,查询结果可以直接来自字段,也可以计算。我还发现 transient
关键字是不必要的,但也许它提供了一些我不知道的好处。
太棒了!不使用@Ignore
和transient
也能完美运行。【参考方案3】:
您应该将@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 discussion
【讨论】:
【参考方案4】:我正在使用 Kotlin,我遇到了类似的问题,下面是我的解决方法。
添加附加字段带 ?(问号) 可空,不带 @Ignore 注释
@Entity(tableName = "task")
data class Task (
val name: String,
val parentId: Integer,
val userId: Integer,
val noOfSubTask: Integer?
)
为每个在 DAO 中选择 Task 的查询添加附加字段(在本例中为 noOfSubTask)。
@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>
...
如果这不起作用,您可以尝试最近在 Google I/O 2018 中引入的 RawQuery。
【讨论】:
这将创建一个名为 noOfSubTask 的附加列,这不是最佳的 是的,我也知道这种解决方法不是最佳的,也不干净。但在那个时候,这是我唯一知道的方式。现在可能有更好的解决方案。 由于我也在使用Kotlin和数据类,所以给了回复,请看看它可能对您的项目有用。 好吧,干净和优化的代码总是正确的,但在某些情况下,将其提高到一定水平也有利于更健康的生活。编码愉快!以上是关于如何填写房间库中实体的非列字段的主要内容,如果未能解决你的问题,请参考以下文章
为在 Sqlite 中具有 LONG 数据类型的字段的表创建房间实体