会议室数据库:多个删除查询使应用崩溃

时间:2019-11-15 08:58:11

标签: android database sqlite android-room

我正在尝试基于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();
    }

5 个答案:

答案 0 :(得分:0)

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

  

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

希望这对您有帮助。

 @Delete
 void delete(WordLayListItem wordLayListItem);

答案 1 :(得分:0)

首先,我注意到您面临的困境可能是僵局。 其次,我注意到一个名为 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();
  

最后,您应该在后台使用do数据库操作,就像在下面使用async一样:

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 ?
    }
}

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

答案 2 :(得分:0)

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

即使我多次从数据库中删除,您上面粘贴的所有代码段也可以正常工作而不会崩溃

答案 3 :(得分:0)

我认为使用

在您的应用程序中关闭数据库实例的某些位置
 db.close();

找到以上行并将其注释掉,然后检查相同的情况。检查并告诉我是否可以解决此问题。

答案 4 :(得分:0)

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