簡體   English   中英

房間數據庫:多個刪除查詢崩潰應用程序

[英]Room Database : Multiple delete query crashes app

我正在嘗試根據我的 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);

}

等class,

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();
    }

而不是通過 Integer Id 嘗試通過 object。!

或者

創建用於在后台刪除數據的異步任務。 教程

希望這可以幫助你。

 @Delete
 void delete(WordLayListItem wordLayListItem);

首先,我注意到你面臨的可能是一個僵局。 其次,我注意到一個名為room_table_modification_log的表可能尚未創建,但仍試圖訪問,最后。 請注意,問題不是來自您的 Dao,因此,如果您創建了一個可能失敗的遷移,您將收到此類錯誤。 所以你可能想提醒自己如何在 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 ?
    }
}

在后台進行數據庫操作可以幫助您避免更長的操作減慢您的應用程序響應,因為它基本上是在主線程上運行的,而且我不知道您使用多少線程來訪問您的數據庫,但您還需要知道如何使用多個線程訪問您的數據庫。 如果上述所有解決方案都不適合您,您可以在此處發布有關如何訪問和更新數據庫的代碼。

在 Github 上分享指向您的完整項目的鏈接。

您在上面粘貼的所有代碼都運行良好,即使我從數據庫中刪除了幾次也沒有任何崩潰

我認為在您的應用程序中的某些地方,您正在使用關閉數據庫實例

 db.close();

找到上面的行並將其注釋掉,並檢查相同的場景。 檢查並讓我知道它是否解決了這個問題。

刪除后必須關閉數據庫連接。 重新加載數據庫連接並更新您的列表視圖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM