2017-07-27 67 views
0

正在創建超過20k條目的醫學詞典。在保存此數據以供脫機使用時,由於數據庫鎖定導致應用程序崩潰。我該如何解決這個問題?執行批量插入時鎖定的Android Sqlite數據庫

我插入功能

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; 

    } 

我似乎無法明白的地方問題。

回答

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


     } 
    } 

我正在嘗試建立新的連接,當上一個連接仍在進程中時。在同一個事務中,數據庫連接應該建立一次。

0

確保以下幾點存儲離線數據:

  • 保存緩存文件
  • 傳遞一個超時值作爲一個選項
  • 啓用離線功能
+1

完全脫離話題 –

0

首先,DbHelper helper = new DbHelper(context)是昂貴的類。是否有任何用例需要爲每次調用wordExists重新創建一個實例。正如你所說,有超過20K的條目,所以有超過20K實例一次又一次地創建...

第二,如果我沒有錯,這個函數db.setTransactionSuccessful();將關閉數據庫。而且你知道,當db在結束事務之前關閉時,它會導致錯誤。

它應該是這樣的

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