【问题标题】:Room Database : Multiple delete query crashes app房间数据库:多个删除查询崩溃应用程序
【发布时间】:2020-03-11 09:27:40
【问题描述】:

我正在尝试根据我的 Android 应用程序中的 Room 从我的数据库中删除一行。当用户从数据库中删除一行时,操作成功。但是,当用户删除另一行时,应用程序会崩溃。 如果用户删除一行,然后重启应用删除另一行,删除操作正常。

这是日志:

     Caused by: java.lang.IllegalStateException: The database '/data/user/0/com.basusingh.blingoo/databases/wordLayList' is not open.
        at android.database.sqlite.SQLiteDatabase.throwIfNotOpenLocked(SQLiteDatabase.java:2943)
        at android.database.sqlite.SQLiteDatabase.createSession(SQLiteDatabase.java:564)
        at android.database.sqlite.-$$Lambda$RBWjWVyGrOTsQrLCYzJ_G8Uk25Q.get(Unknown Source:2)
        at java.lang.ThreadLocal$SuppliedThreadLocal.initialValue(ThreadLocal.java:284)
        at java.lang.ThreadLocal.setInitialValue(ThreadLocal.java:180)
        at java.lang.ThreadLocal.get(ThreadLocal.java:170)
        at android.database.sqlite.SQLiteDatabase.getThreadSession(SQLiteDatabase.java:558)
        at android.database.sqlite.SQLiteProgram.getSession(SQLiteProgram.java:123)
        at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:64)
        at androidx.sqlite.db.framework.FrameworkSQLiteStatement.executeUpdateDelete(FrameworkSQLiteStatement.java:46)
        at com.basusingh.blingoo.Database.WordLayList.WordLayListDao_Impl.DeleteWordLayList(WordLayListDao_Impl.java:94)
        at com.basusingh.blingoo.Activity.WordLayListViewer$1doTask.doInBackground(WordLayListViewer.java:156)
        at com.basusingh.blingoo.Activity.WordLayListViewer$1doTask.doInBackground(WordLayListViewer.java:148)
        at android.os.AsyncTask$2.call(AsyncTask.java:333)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at java.lang.Thread.run(Thread.java:764) 
E/ROOM: Cannot run invalidation tracker. Is the db closed?
    android.database.sqlite.SQLiteException: no such table: room_table_modification_log (code 1 SQLITE_ERROR[1]): , while compiling: SELECT * FROM room_table_modification_log WHERE invalidated = 1;
        at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
        at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1229)
        at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:703)
        at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
        at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:59)
        at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
        at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:46)
        at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1865)
        at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1840)
        at androidx.sqlite.db.framework.FrameworkSQLiteDatabase.query(FrameworkSQLiteDatabase.java:161)
        at androidx.room.RoomDatabase.query(RoomDatabase.java:328)
        at androidx.room.RoomDatabase.query(RoomDatabase.java:311)
        at androidx.room.InvalidationTracker$1.checkUpdatedTable(InvalidationTracker.java:415)
        at androidx.room.InvalidationTracker$1.run(InvalidationTracker.java:389)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)

这是 DAO 代码:

@Dao
public interface WordLayListDao {

    @Query("DELETE FROM WordLayListItems WHERE uid = :id")
    void DeleteWordLayList(int id);

}

和其他类,

public class WordLayListDatabaseClient {

    private Context mCtx;
    private static WordLayListDatabaseClient mInstance;

    private WordLayListAppDatabase appDatabase;


    private WordLayListDatabaseClient(Context mCtx) {
        this.mCtx = mCtx;



        appDatabase = Room.databaseBuilder(mCtx, WordLayListAppDatabase.class, "wordLayList").build();
    }

    public static synchronized WordLayListDatabaseClient getInstance(Context mCtx) {
        if (mInstance == null) {
            mInstance = new WordLayListDatabaseClient(mCtx);
        }
        return mInstance;
    }

    public WordLayListAppDatabase getAppDatabase() {
        return appDatabase;
    }
}

@Database(entities = {WordLayListItems.class}, version = 1)
public abstract class WordLayListAppDatabase extends RoomDatabase {
    public abstract WordLayListDao wordLayListDao();
}

这就是我调用数据库的方式:

 private void deleteLayList(){
        class doTask extends AsyncTask<Void, Void, String> {
            @Override
            protected void onPreExecute(){
                progressDialog.setTitle("Please wait");
                progressDialog.show();
            }
            @Override
            protected String doInBackground(Void... aa){
                WordLayListDatabaseClient.getInstance(WordLayListViewer.this).getAppDatabase().wordLayListDao().DeleteWordLayList(o.getID());
                return null;
            }
            @Override
            protected void onPostExecute(String var){
                progressDialog.dismiss();
                Toast.makeText(getApplicationContext(), "WordLay List Deleted", Toast.LENGTH_LONG).show();
                setResult(RESULT_OK);
                finish();
            }
        }

        doTask dt = new doTask();
        dt.execute();
    }

【问题讨论】:

  • 我注意到的第一件事是你的路径名是/data/user/0/com.basusingh,blingoo/databases/wordLayList,在你的包名中有一个','。这可能是一个原因吗?
  • 不,那是个错误。错字。我已经纠正了。谢谢!
  • 您使用的是哪个版本的 Room?碰撞版本可能有效:stackoverflow.com/questions/50370683/…
  • 我目前在 2.2.1
  • no such table: room_table_modification_log。我认为您忘记将新创建的表添加到实体中

标签: android database sqlite android-room


【解决方案1】:

尝试传递对象,而不是传递 Integer Id。!

创建一个异步任务以在后台删除数据。 Tutorial

希望这对你有帮助。

 @Delete
 void delete(WordLayListItem wordLayListItem);

【讨论】:

  • 尝试传递对象。仍然是错误。所有任务都在异步任务中完成。
【解决方案2】:

首先,我注意到您面临的可能是一个僵局。 其次,我注意到一个名为 room_table_modification_log 的表可能尚未创建但正在尝试访问! 最后,请注意,问题不在于您的道。 所以,如果你创建了一个可能失败的迁移,你会得到这种错误,所以你可能想提醒自己如何在 Room 中创建迁移......如下所示。

您的迁移:

private static final Migration ADDED_CARD_TABLE = new Migration(1, 2) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
        database.execSQL("CREATE TABLE `CardEntity` (`id` INTEGER NOT NULL PRIMARY KEY, "
                + "`type` TEXT, " + "`lastFour` TEXT)");
    }
};

//and Below to add it to your db builder and don't forget to update the version later.
        sampleDB = Room.databaseBuilder(context, sampleDB.class, "sample_db") .addMigrations(ADDED_CARD_TABLE).build();

最后你应该在后台使用数据库操作,比如使用下面的异步:

class DeleteItemInDb extends AsyncTask{

    @Override
    protected Object doInBackground(Object[] objects) {
        //Here goes your deleting process.
        return null;
    }

    @Override
    protected void onPreExecute() {
        //Setup precondition to execute some task after deleting ?
    }
}

在后台执行数据库操作可帮助您避免较长时间的操作减慢应用响应速度,因为它基本上是在主线程上运行的! 而且我不知道您使用多少线程来访问您的数据库,但您还需要知道如何使用多个线程访问您的数据库,您可以在此处发布您如何访问和更新您的数据库的代码如果以上所有解决方案都不适合您。

【讨论】:

    【解决方案3】:

    在 Github 上分享您的完整项目的链接。

    您在上面粘贴的所有代码都运行良好,即使我从数据库中删除了几次也没有任何崩溃

    【讨论】:

    • 您能否分享一下我应该使用的确切软件包和版本。我尝试将我的房间版本号替换为 1.1.1-rc1 并且 gradle 失败,因为它找不到文件。
    • 有一条您未与我们分享的信息导致了崩溃。我复制并粘贴了您拥有的所有代码,并对其进行了修改,以便在我的工作室中使用 todolist 应用程序。即使在我从 taskDetail 活动中删除了几个项目并使用房间 2.1.1 之后,也绝对没有崩溃。
    • 我使用您在问题中发布的所有代码构建了一个应用程序,一切正常,没有任何问题,也没有任何崩溃。
    【解决方案4】:

    我认为在您的应用程序中的某些地方您正在使用

    关闭数据库实例
     db.close();
    

    找到上面的行并将其注释掉,并检查相同的场景。检查并告诉我它是否解决了这个问题。

    【讨论】:

    • 我不是。我的代码中没有这样的行。可能是一个错误?
    【解决方案5】:

    删除后必须关闭数据库连接。重新加载数据库连接并更新您的列表视图。

    【讨论】:

    • 你能分享一些可以帮助关闭数据库的代码吗?基于我当前的代码。
    猜你喜欢
    • 2018-09-15
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多