在Room数据库中硬编码布尔查询

98

我正在开发一个Android应用程序,它可以显示用户潜在匹配列表。用户可以点击其中一个来喜欢该用户,并且我会将所有这些喜欢保存在本地。

我可以编写一个查询来获取匹配列表,如下所示:

@Query("SELECT * FROM match WHERE liked = :liked ORDER BY match DESC LIMIT :limit")
fun getMatches(limit: Int = 6, liked: Boolean = true): Flowable<List<Match>>

我学到这个可以正常工作。然而,我预见不到任何情况下我会将liked设置为false,所以我想知道是否有一种方法可以硬编码我的布尔条件?如果我尝试:

@Query("SELECT * FROM match WHERE liked = true ORDER BY match DESC LIMIT :limit")

我在编译时遇到了以下错误:

Error:(8, 0) Gradle: error: There is a problem with the query: [SQLITE_ERROR] SQL error or missing database (no such column: true)

如何在我的查询字符串中硬编码这个布尔值?

我也尝试过:

  • 将条件用单引号括起来
    • @Query("SELECT * FROM match WHERE liked = 'true' ORDER BY match DESC LIMIT :limit")
4个回答

249

SQLite没有布尔数据类型。Room将其映射到一个INTEGER列,将true映射为1,将false映射为0

因此,我期望这样可以工作:

@Query("SELECT * FROM match WHERE liked = 1 ORDER BY match DESC LIMIT :limit")

记住,这种行为是未记录的。但是,它不应该改变—至少不会在没有警报声响起的情况下—因为我们需要使用迁移来处理任何更改。


7
@AdamMc331:特别是在他们最近的一轮更改之后,我认为Room文档在Room文档中被忽略了。 :-( 但是,我很高兴它对你有用! - CommonsWare
2
哦,是的,Room文档非常稀少...谢谢! - techfly
1
Room数据库显然将1生成为True,将0生成为False,但我的查询返回null或空列表。问题可能是什么? - TheRealChx101
那么,我只需要在查询中将true/false替换为0/1吗?还是我还需要更新表和我的代码呢? - Vivek Thummar
1
@VivekThummar:很可能只是查询,但我已经好几年没有使用Room了,所以我不确定。 - CommonsWare
显示剩余5条评论

34
CommonWare的方法确实可行,直接回答了OP的问题;然而,我不喜欢对数据库进行这样的假设。这种假设应该是安全的,但如果Room决定更改其布尔实现,则可能在未来出现意外的工作。
我建议更好的方法是不将布尔值1或0硬编码到查询中。如果数据库在仓库后面,仍然有可能为仓库公开一个优雅的API。就个人而言,我认为将大型代码库与数据库实现隔离开来是一件好事。
Dao方法(从OP的问题复制):
@Query("SELECT * FROM match WHERE liked = :liked ORDER BY match DESC LIMIT :limit")
fun getMatches(limit: Int = 6, liked: Boolean = true): Flowable<List<Match>>

仓库

class Repository {
    public Flowable<List<Match>> getLikedMatches() {
        return dao.getMatches(6, true);
    }
}

当然,这是一种带有个人观点的选项,因为它假设了某种架构风格。然而,它并不对内部数据库做出假设。即使没有仓库保护数据库,也可以通过在每个地方传递 true 来调用数据库——也不需要假定底层数据。


如果您使用不同的架构风格,可以直接在DAO定义中屏蔽默认值,但需要将DAO定义为抽象类,而不是接口。与上面相同的定义: @Query("SELECT * FROM match WHERE liked = :liked ORDER BY match DESC LIMIT :limit") protected abstract fun getMatches(limit: Int, liked: Boolean): Flowable<List<Match>>公共版本如下:fun getLikedMatches(limit: Int = 6) = getMatches(limit, true) - Almighty
如果Room决定更改其布尔实现,他们必须不这样做,因为在升级Room时,每个人都会“损坏”现有的布尔数据。我从未见过针对Room库更改的数据迁移逻辑。 - The incredible Jan
他们不应该这样做 - 他们可以这样做。他们可能会慢慢地做,但他们绝对可以。依赖Room的底层实现可能是危险的。仅仅因为某些东西被公开并不足以证明它是值得使用的 - 特别是当通过文档记录的行为也能达到同样的目的时。 - methodsignature
“他们可以”,但那将是一个bug。我也能编写bug,但令人惊讶的是,没有人喜欢那样做。 - The incredible Jan
1
一个存储库改变其内部实现并不是一个错误。我也可以简洁,但令人惊讶的是,没有人喜欢那样。 - methodsignature

16
你不需要将布尔列与值进行比较。只需将列值本身用作布尔表达式即可。您可以轻松地将查询更改为SELECT * FROM match WHERE liked ORDER BY match DESC LIMIT :limit。 如果要与false值进行比较,可以使用以下表达式:where not liked

你是正确的。 - 卡尔斯路西法

0
@Query("SELECT * FROM searched_data_table WHERE favourit_history==1 ORDER BY lang_id DESC")

使用此查询语句从表中搜索数据,将根据关键值降序排列并返回相应结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接