2012-03-20 13 views
6

Mam istniejącą bazę danych opartą na SQLiteOpenHelper, która ma kilka wersji i kod do aktualizacji i działa dobrze. Ale w przypadku, gdy użytkownik zainstaluje starszą wersję aplikacji (która spodziewa się niższej wersji bazy danych), będzie się teraz zawieszał - przy użyciu tej funkcji nie będzie można uzyskać dostępu do bazy danych. Chciałbym zapobiec awariom, ale nie chcę obniżać wersji bazy danych - dodanie do tego kodu byłoby bolesne. Zrzucenie wszystkich tabel na pewno by działało, ale począwszy od świeżego pliku jest imo cleaner i mniej podatne na błędy.Dobry schemat usuwania pliku bazy danych w SQLiteOpenHelper.onDowngrade()

To o co pomocnik baza wygląda - nic specjalnego

public class MyDbHelper extends SQLiteOpenHelper { 
    private static final int DATABASE_VERSION = 3; 
    private static final String DATABASE_NAME = "my.db"; 

    public MyDbHelper(Context context) { 
     super(context, DATABASE_NAME, null, DATABASE_VERSION); 
    } 

    @Override 
    public void onCreate(SQLiteDatabase db) { 
     onUpgrade(db, 0, DATABASE_VERSION); 
    } 

    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     if (newVersion < 1) db.execSQL("CREATE TABLE A..."); 
     if (newVersion < 2) db.execSQL("CREATE TABLE B..."); 
     if (newVersion < 3) db.execSQL("CREATE TABLE C..."); 
    } 

    @Override 
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     // I'd like to delete the database here 
     // the only problem is that I can't from here 
     // since this is called in the middle of getWritableDatabase() 
     // and SQLiteDatabase has no .recreate() method. 
    } 
} 

możliwych sposobów Doszedłem do nadrobienia, które:

  • Zrób to z zewnątrz: wyjątki dotyczące połowów ContentProvider, usuń plik i żądanie ponownego otwarcia bazy danych. - Nie podoba mi się to, ponieważ nie jest to odpowiedzialność dostawcy.
  • Wymiana SQLiteOpenHelper z własną kopią tej klasy, które usuwa plik zamiast dzwonić onDowngrade - Problem jest to, że za pomocą pakietu prywatnej części SQLiteDatabase (np .lock()), których nie można zastąpić bez powielania SQLiteDatabase zbyt (prawdopodobnie spowodowałoby w duplikowaniu całego stosu sqlite).

Czy jest to dobre podejście, czy muszę jechać drogą np. DROP TABLES jak opisano here?

Odpowiedz

9

Udało mi się znaleźć sposób, który działa ładnie przez rozszerzenie SQLiteOpenHelper i wszystko, co muszę zrobić w MyDbHelper jest rozszerzenie tej klasy.

public abstract class DeletingSQLiteOpenHelper extends SQLiteOpenHelper { 
    private static final String TAG = DeletingSQLiteOpenHelper.class.getSimpleName(); 

    private final File mDatabaseFile; 

    public DeletingSQLiteOpenHelper(Context context, String name, CursorFactory factory, int version, 
      DatabaseErrorHandler errorHandler) { 
     super(context, name, factory, version, errorHandler); 
     mDatabaseFile = context.getDatabasePath(name); 
    } 

    public DeletingSQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) { 
     super(context, name, factory, version); 
     mDatabaseFile = context.getDatabasePath(name); 
    } 

    @Override 
    public synchronized SQLiteDatabase getWritableDatabase() { 
     try { 
      return super.getWritableDatabase(); 
     } catch (SQLiteDowngradeFailedException e) { 
      // that's our notification 
     } 

     // try to delete the file 
     mDatabaseFile.delete() 

     // now return a freshly created database 
     return super.getWritableDatabase(); 
    } 

    @Override 
    public final void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     // throwing a custom Exception to catch it in getWritableDatabase 
     throw new SQLiteDowngradeFailedException(); 
    } 

    // that's the exception 
    static class SQLiteDowngradeFailedException extends SQLiteException { 
     public SQLiteDowngradeFailedException() {} 

     public SQLiteDowngradeFailedException(String error) { 
      super(error); 
     } 
    } 
} 
Powiązane problemy