4390


データベースのバージョンを変更し、データベースのアップグレードをしようとしたところ以下のようなエラーメッソージが返ってきました。  
「android.database.sqlite.SQLiteDatabaseLockedException: database is locked
(code 5): , while compiling: PRAGMA journal_mode」  
色々調べて、データベースをcloseしてみてもうまくいきません。（closeの仕方が間違っているのかもしれませんが...）  
下記にコードを記載します。  
現在setDataToDBメソッドの中でエラーが出ています。  
すみませんが、宜しくお願いします。

[code]

    public class MyDBHelper extends SQLiteOpenHelper {
    
            public MyDBHelper(Context context) {
                super(context, DB_NAME, null, DB_VERSION);
            }
    
            @Override
            public void onCreate(SQLiteDatabase db) {
                db.beginTransaction();
                try {
                    db.execSQL("CREATE TABLE IF NOT EXISTS " + TB_MAN + "(ID INTEGER PRIMARY KEY AUTOINCREMENT, VOICE TEXT)");
                    db.execSQL("CREATE TABLE IF NOT EXISTS " + TB_WOMAN + "(ID INTEGER PRIMARY KEY AUTOINCREMENT, VOICE TEXT)");
                    db.execSQL("CREATE TABLE IF NOT EXISTS " + TB_WOMAN_MAX + "(ID INTEGER PRIMARY KEY AUTOINCREMENT, VOICE TEXT)");
                    db.execSQL("CREATE TABLE IF NOT EXISTS " + TB_WOMAN_MAX + "(ID INTEGER PRIMARY KEY AUTOINCREMENT, VOICE TEXT)");
                }finally {
                    db.endTransaction();
                }
                setDataToDB("aaa", "bbb", Uri.parse("content://taro.thanks.MyContentProvider/" + TB_MAN));
                setDataToDB("AAA", "BBB", Uri.parse("content://taro.thanks.MyContentProvider/" + TB_MAN_MAX));
                setDataToDB("ccc", "ddd", Uri.parse("content://taro.thanks.MyContentProvider/" + TB_WOMAN));
                setDataToDB("CCC", "DDD", Uri.parse("content://taro.thanks.MyContentProvider/" + TB_WOMAN_MAX));
            }
    
            @Override
            public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
                db.beginTransaction();
                try {
                    db.execSQL("DROP TABLE IF EXISTS " + TB_MAN);
                    db.execSQL("DROP TABLE IF EXISTS " + TB_WOMAN);
                    db.execSQL("DROP TABLE IF EXISTS " + TB_MAN_MAX);
                    db.execSQL("DROP TABLE IF EXISTS " + TB_WOMAN_MAX);
                }finally {
                    db.endTransaction();
                }
                onCreate(db);
            }
    
            public void setDataToDB(String defaultData1, String defaultData2, Uri uri) {
                ContentValues values = new ContentValues();
                values.put(COLUMN_VOICE, defaultData1);
                values.put(COLUMN_VOICE, defaultData2);
                getContext().getContentResolver().insert(uri, values);
            }
        }
    
[/code]


CC BY-SA 3.0
2015-01-11T01:35:07.537
4387
2015-01-11T03:47:51.360
5210
question
android sqlite
エラー：SQLiteDatabaseLockedException: database is locked (code 5)


`close`を試したということは、どこかの`Activity`でも`SQLiteOpenHelper`インスタンスを生成していて、かつ`ContentProvider`でもインスタンスを生成しているということでしょうか。

とすると`SQLiteOpenHelper`のインスタンスが複数生成され、それぞれがトランザクションを確保しているためにロックが掛かっているだけだと思います。

解決策としては、

  1. `MyDBHelper`をシングルトンにして`Application`内で使いまわす
  2. `MyDBHelper`を直接扱わず、常に`ContentProvider`を経由する

この場合、`ContentProvider`を利用されているので、2.がいいと思います。

また、`MyDBHelper#onCreate()`でやっているテーブルの初期値の`insert`は、`ContentProvider`を経由させず、テーブル生成のトランザクション内で直接行うべきだと思います。


CC BY-SA 3.0
2015-01-11T02:45:25.863
4388
2015-01-11T02:45:25.863
5337
4387
answer


[Android開発初心者向け - Content
Providerの使い方](http://qiita.com/rayc5/items/1457331992e1eb02b29f#sqliteopenhelper-
basecolumns)を読みつつ、  
勉強させていただいている中で気づいたのですが、  
`setDataToDB`で使用しているContent Providerの`insert()`の実装で  
`SQLiteDatabase db = mDBHelper.getWritableDatabase()`みたいなことを  
していませんか。

DBHelperは複数のDBインタンスを中に持てないため、  
質問にあるような実装をDBHelper内で行うと、DBのインスタンスが複数→lockかかってるからエラーで落とすわとなります。おそらく。

対処としては`onCreate`の中に`setDataToDB`の処理を書かないで  
外に実装を出すことかなぁ。


CC BY-SA 3.0
2015-01-11T03:21:10.293
4390
2015-01-11T03:21:10.293
2904
4387
answer