问题
是否有可能在运行时构造一个查询?
用例
@Query("SELECT * FROM playlist " +
"WHERE playlist_title LIKE '% :playlistTitle %' " +
"GROUP BY playlist_title " +
"ORDER BY playlist_title " +
"LIMIT :limit")
List<IPlaylist> searchPlaylists(String playlistTitle, int limit);
limit
部分是可选的 . 也就是说,它应该能够在有或没有限制的情况下执行相同的查询 .
更复杂的用例
在前一种情况下,可以使用和不使用限制部分进行两个静态查询,并且每次都可以使用适当的一个 . 但有时我们可能不得不处理更复杂的情况,例如构建过滤器 .
在这种情况下,与前面的示例不同,将有多个可选部分 . 对于书籍表,我们可能需要根据书籍所属的类别,作者姓名,价格范围,出版日期等进行过滤 . 使用这些部分的所有组合进行静态查询几乎是不可能的 .
7 回答
@Anderson K&@Juanky Soriano,我同意@CommonsWare,
房间库中有一些限制,那么我们也可以使用支持SQLite数据库的@query()在房间数据库上编写完全动态的查询
现在,您可以将游标行方式数据转换为POJO类 .
根据我的经验(简称)使用不可能的房间,而不是因为房间限制,而是由@CommonsWare隐含评论,SQLite的限制 . 您需要两个查询,因此DAO中有两个方法 .
我会有类似的东西:
然后在其他地方你做旁路:
这是我现在能想到的最佳选择 .
我没有写多个查询,而是将负值传递给limit子句 . 因为如果查询中有变化,我必须更新两个查询,这更容易出错 .
官方文档 - > If the LIMIT expression evaluates to a negative value, then there is no upper bound on the number of rows returned. 你可以在这里找到https://sqlite.org/lang_select.html并阅读限制条款部分 .
所以我会做这样的事,
并且当您不想应用过滤器时传递否定 .
它在我的情况下工作 .
Updated [21 Dec 2018]
如果您使用kotlin使用默认值 .
@JvmOverloads
使其与Java兼容 . 它为Java生成两个单独的方法 .在Room中没有类似可选参数的东西,但是有一个@RawQuery注释,您可以在其中将查询作为String传递,以便您可以在运行时中构建SQL查询 . 我认为这对你有用 .
以下是官方文档中的示例:
以下是如何使用它:
Important: RawQuery方法必须返回非void类型
Important: 这可以在房间1.1.0-alpha3中找到
Room支持@RawQuery注释以在运行时构造查询 .
步骤1:制作DAO方法
使用
@RawQuery
注释而不是正常@RawQuery
标记DAO方法 .步骤2:构造查询
Room使用准备好的语句进行安全性和编译时验证 . 因此,在构造查询时,我们需要分别存储查询字符串和绑定参数 .
在此示例中,我使用变量
queryString
作为查询字符串,使用args
作为绑定参数 .(请注意,我使用文本编辑器编写代码 . 因此可能会出现拼写错误或语法错误 . 如果您发现任何问题,请在评论中告诉我或编辑帖子 . )
步骤3:执行查询
注意事项
与普通
Query
一样,RawQuery
支持使用嵌入字段返回原始游标,实体,POJO和POJORawQuery
支持关系使用SupportSQLiteQuery .
https://developer.android.com/reference/android/arch/persistence/db/SupportSQLiteQuery
最新版本1.1.1现在使用SupportSQLiteQuery .
用法:
将您的gradle更新为1.1.1
注意:如果升级到1.1.1,并且使用String而不是SupportSQLiteQuery,
你会得到错误:
如上所述使用SupportSQLiteQuery将解决问题 .
注意:确保传入SupportSQLiteQuery查询参数,否则会出现此错误:
stdName1和stdId1是列名