当前位置: 首页 > 知识库问答 >
问题:

使用Room持久性在运行时生成查询

韩淇
2023-03-14

我想在运行时生成的SQLite数据库上运行查询(而不是@Dao中的标准compiletime查询)。例如,我可能想在SQLite数据库中搜索一个文本列,看看它是否包含N个长度的列表中的所有单词。在原始SQLITE中,N为3的查询如下所示:

SELECT * FROM table 
WHERE textValue LIKE %queryTerm1% 
AND textValue LIKE %queryTerm2%"
AND textValue LIKE %queryTerm3%"

我尝试过生成并传递查询的结尾,而不是仅仅传递变量。例如:

String generatedQuery = "textValue LIKE %queryTerm1% AND textValue LIKE %queryTerm2% AND textValue LIKE %queryTerm3%";
tableDao.find(generatedQuery);

在@Dao中:

@Query("SELECT * FROM tableName WHERE :endQuery")
List<POJO> find(String endQuery);

这似乎对我不起作用。你知道如何让运行时生成的查询与Room一起工作吗?

附言:

共有2个答案

徐昕
2023-03-14

问题是您希望传递SQL语句的一部分,但Room将其视为查询参数。

如果你愿意,你可以尝试使用Kripton持久性库,一个开源库(由我编写:)),它极大地简化了SQLite对Android平台的管理代码,并支持这样的情况。

克里普顿也使用DAO模式,所以概念非常相似。写一个符合您需求的例子:

给定一个模型类:

@BindType
public class User {
    public long id;
    public String name;
    public String username;
    public String email;
    public Address address;
    public String phone;
    public String website;
    public Company company;
}

DAO定义:

@BindDao(User.class)
public interface UserDao {
    @BindSqlInsert
    void insert(User bean);

    @BindSqlSelect
    List<User> selectDynamic(@BindSqlDynamicWhere String where, @BindSqlDynamicWhereParams String[] args);
}

以及数据源定义:

@BindDataSource(daoSet={UserDao.class}, fileName = "kripton.quickstart.db", generateAsyncTask = true)
public interface QuickStartDataSource {
}

Kridton将在编译时生成所有需要与数据库一起工作的代码。因此,为了完成你的任务与克里普顿你必须写一个代码类似:

BindQuickStartDataSource ds = BindQuickStartDataSource.instance();
// execute operation in a transaction
ds.execute(new BindQuickStartDataSource.SimpleTransaction() {
  @Override
  public boolean onExecute(BindQuickStartDaoFactory daoFactory) throws Throwable 
  {
    UserDaoImpl dao = daoFactory.getUserDao();
    String[] p={"hello"};
    dao.selectDynamic("name=?",p);
    return true;
  }
});

在logcat中,当执行上述代码时,您将看到生成的日志

database OPEN READ_AND_WRITE_OPENED (connections: 1)
UserDaoImpl, selectDynamic (line 352): SELECT id, name, username, email, address, phone, website, company FROM user WHERE name=?
selectDynamic (line 357): ==> param0: 'hello'
Rows found: 0
database CLOSED (READ_AND_WRITE_OPENED) (connections: 0)

Kripton显然也支持静态where条件和许多其他功能(我从2015年开始开发)。

有关克里普顿持久性库的更多信息:

  • https://github.com/xcesco/kripton
  • http://abubusoft.com/
  • https://github.com/xcesco/kripton/wiki
吉玉宸
2023-03-14

更新:Room的最新版本1.1.1现在使用SupportSQLiteQuery而不是String。

带有类型化绑定的查询。最好使用这个API而不是rawQuery(String,String[]),因为它允许绑定类型安全的参数。

新答案:

@Dao
     interface RawDao {
         @RawQuery(observedEntities = User.class)
         LiveData<List<User>> getUsers(SupportSQLiteQuery query);
     }

用法:

LiveData<List<User>> liveUsers = rawDao.getUsers( new 
SimpleSQLiteQuery("SELECT * FROM User ORDER BY name DESC"));

更新你的gradle到1.1.1(或任何当前版本)

implementation 'android.arch.persistence.room:runtime:1.1.1'
implementation 'android.arch.lifecycle:extensions:1.1.1'
annotationProcessor "android.arch.persistence.room:compiler:1.1.1"
 类似资料:
  • 我正在使用android的房间持久性库,如果有人能帮助我使用外键,如何通过使用外键获取数据,我将不胜感激。

  • 下面是Kotlin中的类: 但当我试图运行应用程序时,它立即崩溃。以下是崩溃日志: 类似乎不是自动生成的。我检查了从codelab下载的原始java应用程序,发现是自动生成的。

  • 我试图通过新的android room库更新我的数据库,但它不起作用。这就是我的方法 主要活动。JAVA CarViewModel。JAVA 卡ao.java 我做了调试,新数据出现并调用viewModel。updateItems(list)方法。提前谢谢!

  • 问题内容: 然而,从上述线程中摘录的一个重要观点是: Querydsl和jOOQ似乎是最流行和最成熟的选择,但是需要注意的一件事: 两者都依赖于代码生成的概念, 即为数据库表和字段生成元类。这有助于建立一个漂亮,干净的DSL,但是 在尝试为仅在运行时才知道的数据库创建查询时会遇到问题 。 除了仅使用纯JDBC +字符串串联外,还有什么方法可以在运行时创建查询吗? 我正在寻找的是一个Web应用程序,

  • 我用这个指南在我的Android应用程序中构建了持久性:https://developer.android.com/training/data-storage/room/index.html 并添加了依赖关系,如下所示:https://developer.android.com/topic/libraries/architecture/adding-components.html 当我构建调试版本

  • 问题内容: 我正在尝试通过ssh启动测试服务器,但是一旦我与ssh断开连接,它总是会死掉。 有没有办法启动一个进程(运行服务器),以使它不会在我的ssh会话结束时消失? 问题答案: 作为替代方案 ,您可以在终端多路复用器(例如GNU 或)中运行远程应用程序 。 使用这些工具可以轻松地从另一个主机重新连接到会话,这意味着您可以在离开工作场所之前进行冗长的构建或下载,并在回家后检查其状态。例如。当我在