RoomDatabase 中的 query() 方法无法按预期工作。 query() 的底层是如何工作的?

问题描述 投票:0回答:1

在探索 Room 库和 RoomDatabase 类的功能时,我决定测试 query() 方法。由于官方文档中的描述并没有对其使用进行任何限制,因此我决定测试两个最简单的方法:SELECT 和 INSERT。

我正在使用一个简单的数据库测试查询。我的选择看起来像这样:

Cursor cursor = db.query("select * from artist”, null);

艺术家表说明如下:

@Entity 
public class Artist {
    @PrimaryKey 
    public int Artist_id;
    public String Name;
}

这个方法效果很好,返回了一个 Cursor,我可以用它查看表数据。

但是当我决定尝试使用如下 INSERT 方法时:

Cursor cursor = db.query("insert into artist (name) values('Candido');”, null);

然后发现没有发生向表中插入新行的情况。我决定通过调试来找出为什么query()方法执行select操作并执行插入,但在库代码中找不到发生检查的地方。然后我决定执行 SELECT 和 INSERT,但是使用 SQLiteDatabase 类中的 rawQuery() 方法,结果是相同的。

在库类SQLiteDirectCursorDriver中逐步调试时,调试时,程序执行以下方法:

public Cursor query(CursorFactory factory, String[] selectionArgs) {
        final SQLiteQuery query = new SQLiteQuery(mDatabase, mSql, mCancellationSignal);
        final Cursor cursor;
        try {
            query.bindAllArgsAsStrings(selectionArgs);

            if (factory == null) {
                cursor = new SQLiteCursor(this, mEditTable, query);
            } else {
                cursor = factory.newCursor(mDatabase, this, mEditTable, query);
            }
        } catch (RuntimeException ex) {
            query.close();
            throw ex;
        }

        mQuery = query;
        return cursor;
    }

这是在创建 Cursor 对象期间调用的方法,它是由我正在测试的 query() 方法返回的。 创建 SQLiteQuery 时,其构造函数会调用父类 SQLiteProgram 的构造函数,其中包含以下几行:

db.getThreadSession().prepare(mSql,
                 db.getThreadDefaultConnectionFlags(assumeReadOnly),
                 cancellationSignalForPrepare, info);

我假设对数据库的查询发生在这个地方,但情况可能并非如此,因为 SQLiteSession 类的prepare()方法的描述说该方法“准备要执行的语句,但不绑定其参数或执行它”。 如果我们返回到 query() 方法,即我上面描述的代码,那么您应该注意以下行

cursor = new SQLiteCursor(this, mEditTable, query);

构造函数描述为:“执行查询并通过 Cursor 接口提供对其结果集的访问。”

但是如果我打开类构造函数的代码和父类构造函数的代码,那么我没有找到在数据库中执行我的sql的代码。

我无法理解对数据库的 SELECT/INSERT 查询是在哪里执行的,在什么地方,在什么类和方法中发生这种情况?光标随后处理的数据在哪里? 请帮我理解这个过程的内部结构。

代码在Android 13 API 33模拟器arm64-v8a上测试

android database sqlite android-room android-cursor
1个回答
0
投票

我无法理解对数据库的 SELECT/INSERT 查询在哪里执行

我不认为你需要这样做。

光标随后处理的数据在哪里?

然后发现没有发生向表中插入新行的情况。 没有数据。 INSERT 不返回任何数据。此外,由于它不返回任何数据,因此被视为不值得执行,因此不会执行 SQL(这是基于经验的假设,而不是调查底层代码)。

你可能会说,但是

@Insert
确实返回了artist_id,这是因为插入的底层代码(Room调用的SQLite API)在插入之后是另一个返回rowid的API调用(artist_id是一个的别名)。

官方文档不包含任何使用限制 好吧,当它说“使用参数查询数据库的便捷方法”时。。这意味着它不适用于更改数据库的操作。

更多内容(解决方案是使用
    execSQL
  • 方法而不是查询方法)
    
        
© www.soinside.com 2019 - 2024. All rights reserved.