【问题标题】:Not able to update sqlite_sequence table using RoomDatabase.query无法使用 RoomDatabase.query 更新 sqlite_sequence 表
【发布时间】:2019-05-03 13:33:56
【问题描述】:

我们尝试使用以下代码更新sqlite_sequence

WeNoteRoomDatabase weNoteRoomDatabase = WeNoteRoomDatabase.instance();
weNoteRoomDatabase.query(new SimpleSQLiteQuery("UPDATE sqlite_sequence SET seq = 0 WHERE name = 'attachment'"));

但是,它根本没有效果。我使用 SQLite 浏览器检查 sqlite_sequence 表内容。计数器未重置为 0。

如果我们尝试在同一个 SQLite 文件上使用 SQLite 浏览器手动运行相同的查询,它工作得很好。

我们的房间数据库非常简单。

@Database(
    entities = {Attachment.class},
    version = 6
)
public abstract class WeNoteRoomDatabase extends RoomDatabase {
    private volatile static WeNoteRoomDatabase INSTANCE;

    private static final String NAME = "wenote";

    public abstract AttachmentDao attachmentDao();

    public static WeNoteRoomDatabase instance() {
        if (INSTANCE == null) {
            synchronized (WeNoteRoomDatabase.class) {
                if (INSTANCE == null) {
                    INSTANCE = Room.databaseBuilder(
                        WeNoteApplication.instance(),
                        WeNoteRoomDatabase.class,
                        NAME
                    )
                        .build();
                }
            }
        }

        return INSTANCE;
    }
}

知道我们错过了什么吗?


其他信息:clearing sqlite_sequence is not working in android room

【问题讨论】:

  • name 的确切条件是什么? name = attachment 时会这样吗?为什么你使用name = \"attachment\"?为什么不name = 'attachment'
  • name = \"attachment\"name = 'attachment' 没有什么不同。如果我使用 Window SQLite 浏览器对其进行测试,两者都可以使用。但是,问题不在于 WHERE 条件。如果我执行weNoteRoomDatabase.query(new SimpleSQLiteQuery("UPDATE sqlite_sequence SET seq = 0"));sqlite_sequence 仍然没有被更新。 Room 似乎在处理sqlite_sequence 表时遇到问题。
  • 您能在后台线程上执行此操作吗?我不确定,但到目前为止,我只是使用后台线程来更新并在房间数据库中写入一些东西
  • 是的,在测试过程中,查询是在后台线程中执行的。
  • 你为什么不使用 DAO 类? Official docs也建议使用。

标签: android android-room


【解决方案1】:

Room 不使用SQLiteDatabase - 但它使用SupportSQLiteDatabase,虽然它是source code 状态,它delegates all calls to an implementation of {@link SQLiteDatabase}... 我什至可以进一步挖掘 - 但我确信,这是一种一致性功能,而不是错误。

SQLiteDatabase.execSQL() 仍然可以正常工作,但对于 SupportSQLiteDatabase.execSQL(),相同的 UPDATEDELETE 对内部表的查询无效并且不会引发错误。

我的MaintenanceHelper 可在GitHub 上找到。重要的是一开始让Room 创建数据库 - 然后可以使用SQLiteDatabase.execSQL() 操作内部表。在研究时,我遇到了注释@SkipQueryVerification,这可能可能允许UPDATEDELETE 在表sqlite_sequence 上;我只成功地执行了SELECTDao... 从公开可用的API 的角度来看,通常内部表的所有提示都被视为read-only;所有的操纵尝试都被默默地忽略了。

【讨论】:

  • 如果您使用SQLite浏览器打开sqlite文件,您可以毫无问题地执行查询UPDATE sqlite_sequence SET seq = 0 WHERE name = 'attachment'
  • @CheokYanCheng 有记录吗?它也可能是另一个驱动程序(一个负责一致性,一个不负责)。表 sqlite_sequence 本身没有键 - 但其他表。您在那里声称的内容只考虑了我回答的 50%。而Room 不是驱动程序,它是ORM 抽象层,堆叠在SQLite 驱动程序之上。
  • 我将SQLite文件从Android传输到桌面,并使用SQLite浏览器工具进行测试。那是唯一且唯一的一种工具在其上运行。我想提出的是,更新 sqlite_sequence 的内容是完全合法的操作 - stackoverflow.com/questions/5586269/… 。我的问题是为什么这种更新操作在 Room 下不起作用
  • @CheokYanCheng 如果您声称的内容属实,@Tjaart 的回答应该有效 - 除了SimpleSQLiteQuery 没有其他作用。在桌面上,驱动程序是sqlite3.sosqlite3.dll - 而Android 使用它自己的sqlite3.so 版本,由SQLiteDatabase 抽象,Room ORM 可选地堆叠在顶部。它在桌面上工作并不重要,因为使用无服务器数据库,驱动程序充当“服务器”。因此,驱动程序必须接受什么,而不是其他驱动程序接受什么,尽管两者都由相同的 .db 文件作为物理存储设施支持。
  • 虽然它看起来应该可以工作,但如果你进行实际测试,它就不行了。
【解决方案2】:

我认为查询错误,您应该尝试以下查询

weNoteRoomDatabase.query(new SimpleSQLiteQuery("UPDATE sqlite_sequence SET seq = 0 WHERE name = attachment"));

【讨论】:

  • 投反对票,因为提议的语法是错误的 - 而不是另一个。
【解决方案3】:

我正在使用房间数据库版本2.2.5

这里我无法使用 Room Dao 结构执行这个查询,所以像这样创建一个简单的类和访问方法,我得到了成功的结果,所以这个是测试结果。我正在使用 RxJava 和 RxAndroid。

public class SqlHelper {

    private static SqlHelper helper = null;

    public static SqlHelper getInstance() {
        if (helper == null) {
            helper = new SqlHelper();
        }
        return helper;
    }

    public Completable resetSequence(Context context) {
        return Completable.create(emitter -> {
            try {
                AppDatabase.getDatabase(context)
                        .getOpenHelper()
                        .getWritableDatabase()
                        .execSQL("DELETE FROM sqlite_sequence WHERE name='<YOUR_TABLE_NAME>'");
                emitter.onComplete();
            } catch (Exception e) {
                emitter.onError(e);
            }
        });
    }
}

Execute:

SqlHelper.getInstance()
         .resetQuizSequence(context)
         .subscribeOn(Schedulers.io()
         .observeOn(AndroidSchedulers.mainThread())
         .subscribe(() -> {}, error -> {});

【讨论】:

    【解决方案4】:

    sql_sequence 不由 Room 管理,因此您需要使用 SupportSQLiteDatabase 对其进行编辑。

    试试这个:

    String sqlQuery = "DELETE FROM sqlite_sequence WHERE name='attachment'";
    
    weNoteRoomDatabase().getOpenHelper().getWritableDatabase().execSQL(sqlQuery);
    

    【讨论】:

    • 您自己尝试过吗?因为,经过测试,建议的方法仍然对我不起作用。
    • 它对我也不起作用(使用 Room 2.0.0 测试)
    【解决方案5】:

    这对我有用 - 房间 2.2.6

    String sqlQuery = "DELETE FROM sqlite_sequence WHERE name='attachment'";

    <YourDatabase>.getInstance(mContext).getOpenHelper().getWritableDatabase().execSQL(sqlQuery);
         
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-24
      • 1970-01-01
      • 1970-01-01
      • 2011-12-23
      • 2016-01-06
      • 1970-01-01
      相关资源
      最近更新 更多