2012-03-20 9 views
6

SQLiteOpenHelper tabanlı bir veritabanım var ve bu sürüm yükseltme için birkaç sürüm ve kod içeriyor ve iyi çalışıyor. Ancak bir kullanıcı uygulamanın daha eski bir sürümünü yüklediğinde (daha düşük bir veritabanı sürümü bekler), şu anda kilitlenecektir - kullanarak ContentProvider veritabanına erişemez. Çökmesini engellemek isterdim, ancak veritabanını gerçekten de düşürmek istemiyorum - bu kodun yapılması ağrıya sebep olur. Tüm tabloları bırakmak kesinlikle işe yarar ancak taze bir dosya ile başlamak imo temizleyici ve daha az hataya eğilimlidir.SQLiteOpenHelper.onDowngrade() içindeki veritabanı dosyasını silmek için iyi şema

  • dışarıdan Do it: catch istisnalar içinde
    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. 
        } 
    } 
    

    olan Yapacak geldim olası yolları

    - özel bir şey veritabanı yardımcı neye benzediğini ilgili

    ContentProvider, dosyayı silin ve veritabanını tekrar açmayı isteyin. - Bunu sevmiyorum çünkü sağlayıcının sorumluluğu değil. yerine onDowngrade çağırmak dosyayı siler bu sınıfın kendi kopyasıyla SQLiteOpenHelper değiştirilmesi

  • - Problem, benim de SQLiteDatabase kopyalamadan yerini alamaz SQLiteDatabase (örn .lock()) paket özel parçalar kullanarak olmasıdır (muhtemelen neden olacaktır tüm sqlite yığınının çoğaltılması).

Bunu yapmak için iyi bir yaklaşım var mı, yoksa DROP TABLES yolunu kullanmam gerekiyor mu? here açıklandığı gibi?

cevap

9

SQLiteOpenHelper'ı genişleterek güzel çalışan bir yöntem buldum ve MyDbHelper'da yapmam gereken tek şey bu sınıfı genişletmektir.

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); 
     } 
    } 
} 
İlgili konular