2016-01-26 29 views
5

Mam następujące klasy „Singleton”, aby obsługiwać połączenia SQLite i upewnij się, że 1 instancji połączenia dla całego procesu/aplikacji:SQLite w stanie otworzyć plik bazy danych (kod 14) na częste „wybierz” zapytania

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

I klasa DBHelper sama:

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

Kiedy często starają się "SELECT" pewne informacje z bazy danych otrzymuję następujący błąd:

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) 

Używam następujący kod do wykonania zapytania:

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 
} 

Jak zarządzać/poprawić połączenia z bazą danych w celu przezwyciężenia/uniknąć tego problemu?

+0

Gdzie podajesz bazę danych ** ścieżkę **? Możesz zobaczyć, że coś jest nie tak na tej ścieżce: 'open (/ data/user/0/uz.mycompany.myapp/databases/database.db-journal)'. Powinno to być coś takiego jak '/ data/data/uz.mycompany.myapp/databases/database.db' –

+0

@ HrundiV.Bakshi Dzięki za odpowiedź, myślę, że problem nie jest związany ze ścieżką do bazy danych ... ponieważ Moja aplikacja działa i wszystko jest w porządku, dopóki nie dojdzie do wykonania getData() często/często (co 2 sekundy) ... – JavaMachine

+0

'nie można otworzyć pliku bazy danych' mówi co? –

Odpowiedz

6

przed wykonaniem jakiegokolwiek zapytania do tych rzeczy (powinieneś otworzyć swoją bazę danych). Zamknij db po zakończeniu zadania.

private DBHelper dbHelper = new DBHelper(context); 

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

// Napisz teraz zapytanie ... a następnie zamknij bazę danych.

_db.close(); 

Możesz sprawdzić mój git link1git link2

+0

Dziękuję za odpowiedź. To może sprawić, że moja aplikacja będzie trochę nieprzewidywalna, więc moja aplikacja wymaga obsługi każdego żądania do bazy danych bez pomijania go ... – JavaMachine

+0

Albo mogę zmusić użytkownika, aby zaczekał, aż baza danych będzie dostępna do otwarcia (za pomocą twojego rozwiązania) ... ale będzie jest wydajny pod względem komfortu użytkowania? – JavaMachine

+0

można zamknąć bazę danych po zakończeniu zadania ... –

1

Twój kod ponownie otwiera bazę danych za każdym razem dbOpen() jest tzw.

Obiekt bazy danych SQLite jest dość lekki; nie ma sensu zamykanie i ponowne otwieranie.

Już masz swój singleton; wystarczy zapisać tam jedno odniesienie SQLiteDatabase.

+0

Dzięki za odpowiedź, już próbowałem to zrobić ... Dodałem 'if (writableDB == null) writableDB = dbHelper.getWritableDatabase(); return writableDB; 'in' dbOpen() 'Ale wygląda na to, że aplikacja wciąż próbuje ponownie otworzyć otworzoną bazę danych ... Myślę, że muszę to sprawdzić ... – JavaMachine

+1

Otrzymasz śledzenie stosu, gdy otwarte zawiedzie. Albo ten nie przechodzi przez singleton, albo singleton został wcześniej usunięty. –

3

Jako dodatek, uważam, że posiadanie zbyt wielu kursorów, a tym samym otwarcie, może również spowodować to samo "nie można otworzyć błąd pliku bazy danych". (w następujący kodu jest wiersze w shoplistcursor tak, aby była powyżej kursory wykorzystywane/ponownie wykorzystane w całości)

ja uzyskanie tej samej wiadomości. Jak na: -

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 

Kod, że był w błędzie, to: -

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

Lekarstwo było zamknąć kursory na każdej iteracji. Jak na: -

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

to był mój problem, po dokładnym sprawdzeniu mojej klasy bazy danych znalazłem kilka metod, w których kursor nie był zamknięty po użyciu. Nie stało się to problemem, dopóki mój zestaw danych nie powiększył się, powodując ten sam błąd co op. dzięki! – Corey

0

Używam kursor na wielkim zapytaniem gdzie kursor uderzy DB ponad 1350 razy przez trzy oddzielne „QUERY” w ciągu 800 milisekund. Więc mam błąd (android.database.sqlite.SQLiteCantOpenDatabaseException: nie można otworzyć pliku bazy danych (kod 14)). Rozwiązałem go, zamykając kursor przed rozpoczęciem nowego zapytania. To rozwiązuje mój problem. Mam nadzieję, że zadziała w przypadku większego zapytania niż moje.

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