Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Room持久性在运行时生成查询_Java_Android_Sqlite_Android Sqlite_Android Room - Fatal编程技术网

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

Java 使用Room持久性在运行时生成查询,java,android,sqlite,android-sqlite,android-room,Java,Android,Sqlite,Android Sqlite,Android Room,我想在运行时生成的SQLite数据库上运行查询(而不是@Dao中的标准compiletime查询)。例如,我可能想在SQLite数据库中搜索一个文本列,看看它是否包含N个长度的列表中的所有单词。在原始SQLITE中,N为3的查询如下所示: SELECT * FROM table WHERE textValue LIKE %queryTerm1% AND textValue LIKE %queryTerm2%" AND textValue LIKE %queryTerm3%" 我已经尝试过生

我想在运行时生成的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);
@Query(“从tableName中选择*,其中:endQuery”)
列表查找(字符串结束查询);
这似乎对我不起作用。您知道如何让运行时生成的查询与Room一起工作吗

附言:

我已经调试了Dao实现,并查看了它正在运行的语句。这将确认生成的查询信息和查询是否正确传递。我认为这是SQL注入预防的一个问题(也就是更多的SQLITE问题,而不是房间问题)

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

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

Kripton也使用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 {
}
Kripton将在编译时生成处理数据库所需的所有代码。因此,要使用Kripton完成任务,您必须编写类似于以下内容的代码:

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年开始开发它)

有关Kripton持久性库的详细信息:


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

具有类型化绑定的查询。最好使用此API而不是 rawQuery(字符串,字符串[]),因为它允许绑定类型安全 参数

新答案:

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

,这在很大程度上是传递到底层
SQLiteDatabase
rawQuery()
。如果您没有像那样使用
(而是基于相等性比较
textValue
),您可以在
中使用
,该文件室直接支持该文件。此解决方案的可能重复会引发**错误:RawQuery不再允许传递字符串。请使用android.arch.persistence.db.SupportSQLiteQuery.*@mohammednathar我刚刚经历了这个问题,用字符串得到了这个错误,但是这个答案被更新以解决这个问题(显然,这就是我在看到错误后在这个页面上遇到的问题:)
LiveData<List<User>> liveUsers = rawDao.getUsers( new 
SimpleSQLiteQuery("SELECT * FROM User ORDER BY name DESC"));
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"