使用Room Persistance

时间:2017-06-19 18:41:24

标签: java android sqlite android-sqlite android-room

我想在我的SQLite数据库上运行已在运行时生成的查询(而不是@Dao中的标准编译时查询)。例如,我可能想要搜索SQLite数据库中的TEXT列,以查看它是否包含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运行生成的查询?

PS:

我调试了Dao实现并查看了它正在运行的语句。这确认生成的查询信息和查询正在正确传递。我认为这是SQL注入预防的问题(更多的是SQLITE问题,而不是Room问题) enter image description here

2 个答案:

答案 0 :(得分:5)

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

  

带有类型绑定的查询。最好使用此API代替   rawQuery(String,String [])因为它允许绑定类型安全   参数。

新答案:

[Object Object]

用法:

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

将您的gradle更新为1.1.1

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

答案 1 :(得分:0)

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

如果你想要,你可以尝试使用Kripton Persistence Library,这是一个开源库(由我:)编写,它大大简化了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显然支持静态的条件和许多其他功能(我在2015年开始开发它)。

有关Kripton Persistence Library的更多信息: