执行批量插入时,Android Sqlite数据库被锁定

时间:2017-07-27 03:06:47

标签: java android sqlite

创建超过20k条目的医学词典。保存此数据以供离线使用时,应用程序因数据库锁定而崩溃。我该如何解决这个问题?

我的插入功能

public static void saveWords(AppCompatActivity appCompatActivity, Context context, JSONArray response) {
        DbHelper helper = new DbHelper(context);


        ProgressDialog progressDialog = new ProgressDialog(context);
        progressDialog.setMessage("Finalising...");
        progressDialog.setCancelable(false);
        progressDialog.show();

        db = helper.getWritableDatabase();
        db.beginTransaction();
        try {
            ContentValues contentValues = new ContentValues();
            for (int i = 0; i < response.length(); i++) {
                JSONObject object = response.getJSONObject(i);
                String wordId = object.getString("wordid");
                String category = object.getString("category");
                String word = object.getString("word");
                String meaning = object.getString("meaning");
                String letter = object.getString("letter");

                if (!wordExists(context, wordId)) {
                    contentValues.put(DbConstants.WORD_ID, wordId);
                    contentValues.put(DbConstants.CATEGORY, category);
                    contentValues.put(DbConstants.WORD, word);
                    contentValues.put(DbConstants.MEANING, meaning);
                    contentValues.put(DbConstants.LETTER, letter);
                    contentValues.put(DbConstants.STATUS, "0");

                    db.insert(DbConstants.TABLE_WORDS, null, contentValues);
                }
            }
            db.setTransactionSuccessful();

        } catch (JSONException e) {
            e.printStackTrace();
        } finally {
            db.endTransaction();
            progressDialog.dismiss();
            appCompatActivity.recreate();
        }

    }

wordExists方法:

private static boolean wordExists(Context context, String wordId) {
       DbHelper helper = new DbHelper(context);
        db = helper.getWritableDatabase();
        String[] columns = {DbConstants.WORD_ID};
        String whereClause = DbConstants.WORD_ID + " = ? ";
        String whereArgs[] = {wordId};

        Cursor cursor = db.query(DbConstants.TABLE_WORDS, columns, whereClause, whereArgs, null, null, null, null);
        if (cursor.getCount() > 0) {
            cursor.close();
            return true;
        }
        cursor.close();
        return false;

    }

我似乎无法理解问题所在。

3 个答案:

答案 0 :(得分:1)

过了一段时间我得到了解决方案。我的问题是,我正忙着重新打开数据库。实际上,我的工作是wordExists方法。这是我的新代码:

 public static void saveWords(AppCompatActivity appCompatActivity, Context context, JSONArray response) {
        DbHelper helper = new DbHelper(context);


        ProgressDialog progressDialog = new ProgressDialog(context);
        progressDialog.setMessage("Finalising...");
        progressDialog.setCancelable(false);
        progressDialog.show();

        db = helper.getWritableDatabase();
        db.beginTransaction();
        try {
            ContentValues contentValues = new ContentValues();
            for (int i = 0; i < response.length(); i++) {
                JSONObject object = response.getJSONObject(i);
                String wordId = object.getString("wordid");
                String category = object.getString("category");
                String word = object.getString("word");
                String meaning = object.getString("meaning");
                String letter = object.getString("letter");

                String[] columns = {DbConstants.WORD_ID};
                String whereClause = DbConstants.WORD_ID + " = ? ";
                String whereArgs[] = {wordId};

                Cursor cursor = db.query(DbConstants.TABLE_WORDS, columns, whereClause, whereArgs, null, null, null, null);
                if (cursor.getCount() <= 0) {
                    contentValues.put(DbConstants.WORD_ID, wordId);
                    contentValues.put(DbConstants.CATEGORY, category);
                    contentValues.put(DbConstants.WORD, word);
                    contentValues.put(DbConstants.MEANING, meaning);
                    contentValues.put(DbConstants.LETTER, letter);
                    contentValues.put(DbConstants.STATUS, "0");

                    db.insert(DbConstants.TABLE_WORDS, null, contentValues);

                }
                cursor.close();
            }
            db.setTransactionSuccessful();

        } catch (JSONException e) {
            e.printStackTrace();
        } finally {
            db.endTransaction();
            progressDialog.dismiss();
            appCompatActivity.recreate();
        }


        }
    }

当前一个连接仍处于进行状态时,我正尝试建立新连接。在同一事务中,应建立一次数据库连接。

答案 1 :(得分:0)

确保以下事项离线存储数据:

  • 保存缓存文件
  • 将超时值作为选项传递
  • 启用离线功能

答案 2 :(得分:0)

首先,DbHelper helper = new DbHelper(context)是昂贵的课程。是否有任何用例需要为wordExists的每次调用重新创建一个实例。正如你所说,有超过20k的条目,所以有超过20k的实例一次又一次地创建......

其次,如果我没有错,这个函数db.setTransactionSuccessful();将关闭数据库。而且你知道,当db在结束事务之前关闭时,它将导致错误。

应该是这样的

finally {
        db.endTransaction();
        db.setTransactionSuccessful();
        progressDialog.dismiss();
        appCompatActivity.recreate();
    }