web-dev-qa-db-ja.com

SQLiteは頻繁な "SELECT"クエリでデータベースファイル(コード14)を開くことができません

SQLite接続を処理し、プロセス/アプリ全体の接続のインスタンスが1つあることを確認するために、次のクラス「シングルトン」を持っています。

public class DBController {
  private static DBController instance = new DBController();
  private static DBHelper dbHelper;
  public static DBController getInstance()
  {
    return instance;
  }
  public SQLiteDatabase dbOpen(Context context)
  {
    if(dbHelper == null)
        dbHelper = new DBHelper(context);
    return dbHelper.getWritableDatabase();
  }
}

そしてDBHelperクラス自体:

public class DBHelper extends SQLiteOpenHelper {

  public DBHelper(Context context) {
    super(context, "database.db", null, 1);
  }
  @Override
  public void onCreate(SQLiteDatabase db) {
    final String position = "CREATE TABLE test (" +
            "test TEXT NOT NULL);";
    db.execSQL(position);
  }
}

私が頻繁にデータベースから情報を「選択」しようとすると、次のエラーが発生します。

SQLiteLog: (14) cannot open file at line 31278 of [2ef4f3a5b1]
SQLiteLog: (14) os_unix.c:31278: (24) open(/data/user/0/uz.mycompany.myapp/databases/database.db-journal) - 
SQLiteLog: (14) cannot open file at line 31278 of [2ef4f3a5b1]
SQLiteLog: (14) os_unix.c:31278: (24) open(/data/user/0/uz.mycompany.myapp/databases/database.db-journal) - 
SQLiteLog: (14) statement aborts at 29: [SELECT * FROM test WHERE test='testdata1'] unable to open database file
SQLiteQuery: exception: unable to open database file (code 14); query: SELECT * FROM test WHERE test='testdata1'
Android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file (code 14)

クエリを実行する次のコードを実行しています:

public String getData(Context context)
{
    SQLiteDatabase _db = dbOpen(context);
    Cursor c = _db.rawQuery("SELECT * FROM test WHERE test='testdata1'", null);
    return getDataFromCursor(c).get(0); //gets data from cursor and returns first one
}

この問題を克服/回避するためにデータベース接続をどのように管理/改善できますか?

8
JavaMachine

これにクエリを実行する前(データベースを開く必要があります)。タスクの完了後にdbを閉じます。

private DBHelper dbHelper = new DBHelper(context);

try {
    _db = dbHelper.getWritableDatabase();
} catch (SQLException s) {
    new Exception("Error with DB Open");
}

//次に、今すぐクエリを記述して...データベースを閉じます。

_db.close();

あなたは私の git link1git link2 をチェックすることができます

11

さらに、カーソルの数が多すぎてカーソルが開いた場合も、同じ「データベースファイルを開けません」というエラーが発生する可能性があると思います。 (次のコードでは、shoplistcursor507行があるため、-150合計で使用/再利用されたカーソル

同じメッセージが表示されました。に従って:-

10-29 19:57:00.901 12845-12845/mjt.shopper E/SQLiteLog: (14) cannot open file at line 30046 of [9491ba7d73]
10-29 19:57:00.901 12845-12845/mjt.shopper E/SQLiteLog: (14) os_unix.c:30046: (24) open(/data/data/mjt.shopper/databases/Shopper-journal) - 
10-29 19:57:00.901 12845-12845/mjt.shopper E/SQLiteLog: (14) cannot open file at line 30046 of [9491ba7d73]
10-29 19:57:00.901 12845-12845/mjt.shopper E/SQLiteLog: (14) os_unix.c:30046: (24) open(/data/data/mjt.shopper/databases/Shopper-journal) - 
10-29 19:57:00.901 12845-12845/mjt.shopper E/SQLiteLog: (14) statement aborts at 24: [SELECT *  FROM productusage WHERE productailseref = 60 AND productproductref = 75 ;] unable to open database file
10-29 19:57:00.902 12845-12845/mjt.shopper E/SQLiteQuery: exception: unable to open database file (code 14); query: SELECT *  FROM productusage WHERE productailseref = 60 AND productproductref = 75 ;
10-29 19:57:00.902 12845-12845/mjt.shopper D/AndroidRuntime: Shutting down VM
10-29 19:57:00.903 12845-12845/mjt.shopper E/AndroidRuntime: FATAL EXCEPTION: main

エラーになったコードは:-

 SQLiteDatabase db = getWritableDatabase();
        Cursor shoplistcursor = getAllRowsFromTable(SHOPLIST_TABLE_NAME);
        Cursor productcsr;
        Cursor aislecsr;
        Cursor prdusecsr;
        while(shoplistcursor.moveToNext()) {
            productcsr = getProductFromProductId(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_PRODUCTREF)));
            aislecsr = getAisleFromAisleId(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_AISLEREF)));
            prdusecsr = getProductUsage(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_AISLEREF)),
                    shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_PRODUCTREF)));
            if (productcsr.getCount() < 1 | aislecsr.getCount() < 1 | prdusecsr.getCount() < 1) {
                deleteShopListEntry(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_ID)));
            } 
            if(shoplistcursor.isLast()) {
                prdusecsr.close();
                aislecsr.close();
                productcsr.close();
            }
        }
        shoplistcursor.close();
        db.close();
}

解決策は、各反復でカーソルを閉じることでした。に従って:-

 SQLiteDatabase db = getWritableDatabase();
        Cursor shoplistcursor = getAllRowsFromTable(SHOPLIST_TABLE_NAME);
        Cursor productcsr;
        Cursor aislecsr;
        Cursor prdusecsr;
        while(shoplistcursor.moveToNext()) {
            productcsr = getProductFromProductId(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_PRODUCTREF)));
            aislecsr = getAisleFromAisleId(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_AISLEREF)));
            prdusecsr = getProductUsage(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_AISLEREF)),
                    shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_PRODUCTREF)));
            if (productcsr.getCount() < 1 | aislecsr.getCount() < 1 | prdusecsr.getCount() < 1) {
                productcsr.close();
                aislecsr.close();
                prdusecsr.close();
                deleteShopListEntry(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_ID)));
            } else {
                productcsr.close();
                aislecsr.close();
                prdusecsr.close();
            }
        }
        shoplistcursor.close();
        db.close();
    }
6
MikeT

カーソルを大きなクエリに使用しています。カーソルは、DBに1350回以上ヒットし、800ミリ秒以内に3つの別の 'クエリ'でヒットします。そのため、エラーが発生しました(Android.database.sqlite.SQLiteCantOpenDatabaseException:データベースファイルを開けません(コード14))。新しいクエリを開始する前にカーソルを閉じることで解決しました。これで問題は解決しました。私よりも大きなクエリが機能することを願っています。

String data_query = "SELECT * FROM test WHERE id= " + c_id + " AND memberId = " + memberId;           
Cursor cu_cu = userHelper.getData(data_query);
float cu_cu_count = cu_cu.getCount();
System.out.println("ALL ANSWER COUNT : " + cu_cu_count);
cu_cu.close();
2

コードは、dbOpen()が呼び出されるたびにデータベースを開きます。

SQLiteデータベースオブジェクトは非常に軽量です。閉じて開きなおしても意味がありません。

シングルトンはすでにあります。単一のSQLiteDatabase参照をそこに格納するだけです。

2
CL.

あなたのアプリケーションクラス

public static SQLiteDatabase database;

@Override
public void onCreate() {
    super.onCreate();

    SQLiteOpenHelper helper = Database.getInstance(getApplicationContext());

    if (database == null) {
        database = helper.getWritableDatabase();
    } else {
        if (!database.isOpen()) {
            database = helper.getWritableDatabase();
        }
    }
}

あなたのクエリクラスで

 public DataSources() {
    database = ApplicationController.database;
 }

このようにして、書き込み可能なdbオブジェクトを一度作成します

0
FK Khan